]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
1. Sync the latest network stack. Add NetLibCreateIPv4DPathNode () in netlib library.
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConIn.c
1 /**@file
2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
3
4 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Terminal.h"
16
17
18 EFI_STATUS
19 EFIAPI
20 TerminalConInReset (
21 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
22 IN BOOLEAN ExtendedVerification
23 )
24 /*++
25 Routine Description:
26
27 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
28 This driver only perform dependent serial device reset regardless of
29 the value of ExtendeVerification
30
31 Arguments:
32
33 This - Indicates the calling context.
34
35 ExtendedVerification - Skip by this driver.
36
37 Returns:
38
39 EFI_SUCCESS
40 The reset operation succeeds.
41
42 EFI_DEVICE_ERROR
43 The dependent serial port reset fails.
44
45 --*/
46 {
47 EFI_STATUS Status;
48 TERMINAL_DEV *TerminalDevice;
49
50 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
51
52 //
53 // Report progress code here
54 //
55 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
56 EFI_PROGRESS_CODE,
57 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),
58 TerminalDevice->DevicePath
59 );
60
61 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
62
63 //
64 // clear all the internal buffer for keys
65 //
66 InitializeRawFiFo (TerminalDevice);
67 InitializeUnicodeFiFo (TerminalDevice);
68 InitializeEfiKeyFiFo (TerminalDevice);
69
70 if (EFI_ERROR (Status)) {
71 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
72 EFI_ERROR_CODE | EFI_ERROR_MINOR,
73 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),
74 TerminalDevice->DevicePath
75 );
76 }
77
78 return Status;
79 }
80
81 EFI_STATUS
82 EFIAPI
83 TerminalConInReadKeyStroke (
84 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
85 OUT EFI_INPUT_KEY *Key
86 )
87 /*++
88 Routine Description:
89
90 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
91
92 Arguments:
93
94 This - Indicates the calling context.
95
96 Key - A pointer to a buffer that is filled in with the keystroke
97 information for the key that was sent from terminal.
98
99 Returns:
100
101 EFI_SUCCESS
102 The keystroke information is returned successfully.
103
104 EFI_NOT_READY
105 There is no keystroke data available.
106
107 EFI_DEVICE_ERROR
108 The dependent serial device encounters error.
109
110 --*/
111 {
112 TERMINAL_DEV *TerminalDevice;
113 EFI_STATUS Status;
114
115 //
116 // Initialize *Key to nonsense value.
117 //
118 Key->ScanCode = SCAN_NULL;
119 Key->UnicodeChar = 0;
120 //
121 // get TERMINAL_DEV from "This" parameter.
122 //
123 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
124
125 Status = TerminalConInCheckForKey (This);
126 if (EFI_ERROR (Status)) {
127 return EFI_NOT_READY;
128 }
129
130 EfiKeyFiFoRemoveOneKey (TerminalDevice, Key);
131
132 return EFI_SUCCESS;
133
134 }
135
136 VOID
137 TranslateRawDataToEfiKey (
138 IN TERMINAL_DEV *TerminalDevice
139 )
140 /*++
141 Step1: Turn raw data into Unicode (according to different encode).
142 Step2: Translate Unicode into key information.
143 (according to different terminal standard).
144 --*/
145 {
146 switch (TerminalDevice->TerminalType) {
147
148 case PcAnsiType:
149 case VT100Type:
150 case VT100PlusType:
151 AnsiRawDataToUnicode (TerminalDevice);
152 UnicodeToEfiKey (TerminalDevice);
153 break;
154
155 case VTUTF8Type:
156 //
157 // Process all the raw data in the RawFIFO,
158 // put the processed key into UnicodeFIFO.
159 //
160 VTUTF8RawDataToUnicode (TerminalDevice);
161
162 //
163 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
164 // then put into EfiKeyFIFO.
165 //
166 UnicodeToEfiKey (TerminalDevice);
167
168 break;
169 }
170 }
171
172 VOID
173 EFIAPI
174 TerminalConInWaitForKey (
175 IN EFI_EVENT Event,
176 IN VOID *Context
177 )
178 /*++
179 Routine Description:
180
181 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
182 Signal the event if there is key available
183
184 Arguments:
185
186 Event - Indicates the event that invoke this function.
187
188 Context - Indicates the calling context.
189
190 Returns:
191
192 N/A
193
194 --*/
195 {
196 //
197 // Someone is waiting on the keystroke event, if there's
198 // a key pending, signal the event
199 //
200 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
201 //
202 if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {
203
204 gBS->SignalEvent (Event);
205 }
206 }
207
208 EFI_STATUS
209 TerminalConInCheckForKey (
210 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
211 )
212 /*++
213 Routine Description:
214
215 Check for a pending key in the Efi Key FIFO or Serial device buffer.
216
217 Arguments:
218
219 This - Indicates the calling context.
220
221 Returns:
222
223 EFI_SUCCESS
224 There is key pending.
225
226 EFI_NOT_READY
227 There is no key pending.
228
229 EFI_DEVICE_ERROR
230
231 --*/
232 {
233 EFI_STATUS Status;
234 TERMINAL_DEV *TerminalDevice;
235 UINT32 Control;
236 UINT8 Input;
237 EFI_SERIAL_IO_MODE *Mode;
238 EFI_SERIAL_IO_PROTOCOL *SerialIo;
239 UINTN SerialInTimeOut;
240
241 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
242
243 SerialIo = TerminalDevice->SerialIo;
244 if (SerialIo == NULL) {
245 return EFI_DEVICE_ERROR;
246 }
247 //
248 // if current timeout value for serial device is not identical with
249 // the value saved in TERMINAL_DEV structure, then recalculate the
250 // timeout value again and set serial attribute according to this value.
251 //
252 Mode = SerialIo->Mode;
253 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
254
255 SerialInTimeOut = 0;
256 if (Mode->BaudRate != 0) {
257 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
258 }
259
260 Status = SerialIo->SetAttributes (
261 SerialIo,
262 Mode->BaudRate,
263 Mode->ReceiveFifoDepth,
264 (UINT32) SerialInTimeOut,
265 (EFI_PARITY_TYPE) (Mode->Parity),
266 (UINT8) Mode->DataBits,
267 (EFI_STOP_BITS_TYPE) (Mode->StopBits)
268 );
269
270 if (EFI_ERROR (Status)) {
271 TerminalDevice->SerialInTimeOut = 0;
272 } else {
273 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
274 }
275 }
276 //
277 // check whether serial buffer is empty
278 //
279 Status = SerialIo->GetControl (SerialIo, &Control);
280
281 if (Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) {
282 //
283 // Translate all the raw data in RawFIFO into EFI Key,
284 // according to different terminal type supported.
285 //
286 TranslateRawDataToEfiKey (TerminalDevice);
287
288 //
289 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
290 // return directly.
291 //
292 if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {
293 return EFI_SUCCESS;
294 } else {
295 return EFI_NOT_READY;
296 }
297 }
298 //
299 // Fetch all the keys in the serial buffer,
300 // and insert the byte stream into RawFIFO.
301 //
302 do {
303
304 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
305
306 if (EFI_ERROR (Status)) {
307 if (Status == EFI_DEVICE_ERROR) {
308 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
309 EFI_ERROR_CODE | EFI_ERROR_MINOR,
310 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError),
311 TerminalDevice->DevicePath
312 );
313 }
314 break;
315 }
316
317 RawFiFoInsertOneKey (TerminalDevice, Input);
318 } while (TRUE);
319
320 //
321 // Translate all the raw data in RawFIFO into EFI Key,
322 // according to different terminal type supported.
323 //
324 TranslateRawDataToEfiKey (TerminalDevice);
325
326 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
327 return EFI_NOT_READY;
328 }
329
330 return EFI_SUCCESS;
331 }
332
333 EFI_STATUS
334 GetOneKeyFromSerial (
335 EFI_SERIAL_IO_PROTOCOL *SerialIo,
336 UINT8 *Input
337 )
338 /*++
339 Get one key out of serial buffer.
340 If serial buffer is empty, return EFI_NOT_READY;
341 if reading serial buffer encounter error, returns EFI_DEVICE_ERROR;
342 if reading serial buffer successfully, put the fetched key to
343 the parameter "Input", and return EFI_SUCCESS.
344 --*/
345 {
346 EFI_STATUS Status;
347 UINTN Size;
348
349 Size = 1;
350 *Input = 0;
351
352 Status = SerialIo->Read (SerialIo, &Size, Input);
353
354 if (EFI_ERROR (Status)) {
355
356 if (Status == EFI_TIMEOUT) {
357 return EFI_NOT_READY;
358 }
359
360 return EFI_DEVICE_ERROR;
361
362 }
363
364 if (*Input == 0) {
365 return EFI_NOT_READY;
366 }
367
368 return EFI_SUCCESS;
369 }
370
371 BOOLEAN
372 RawFiFoInsertOneKey (
373 TERMINAL_DEV *TerminalDevice,
374 UINT8 Input
375 )
376 /*++
377 Insert one byte raw data into the Raw Data FIFO.
378 If FIFO is FULL before data insertion,
379 return FALSE, and the key is lost.
380 --*/
381 {
382 UINT8 Tail;
383
384 Tail = TerminalDevice->RawFiFo.Tail;
385
386 if (IsRawFiFoFull (TerminalDevice)) {
387 //
388 // Raw FIFO is full
389 //
390 return FALSE;
391 }
392
393 TerminalDevice->RawFiFo.Data[Tail] = Input;
394
395 TerminalDevice->RawFiFo.Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
396
397 return TRUE;
398 }
399
400 BOOLEAN
401 RawFiFoRemoveOneKey (
402 TERMINAL_DEV *TerminalDevice,
403 UINT8 *Output
404 )
405 /*++
406 Remove one byte raw data out of the Raw Data FIFO.
407 If FIFO buffer is empty before remove operation,
408 return FALSE.
409 --*/
410 {
411 UINT8 Head;
412
413 Head = TerminalDevice->RawFiFo.Head;
414
415 if (IsRawFiFoEmpty (TerminalDevice)) {
416 //
417 // FIFO is empty
418 //
419 *Output = 0;
420 return FALSE;
421 }
422
423 *Output = TerminalDevice->RawFiFo.Data[Head];
424
425 TerminalDevice->RawFiFo.Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
426
427 return TRUE;
428 }
429
430 BOOLEAN
431 IsRawFiFoEmpty (
432 TERMINAL_DEV *TerminalDevice
433 )
434 /*++
435 Clarify whether FIFO buffer is empty.
436 --*/
437 {
438 if (TerminalDevice->RawFiFo.Head == TerminalDevice->RawFiFo.Tail) {
439 return TRUE;
440 } else {
441 return FALSE;
442 }
443 }
444
445 BOOLEAN
446 IsRawFiFoFull (
447 TERMINAL_DEV *TerminalDevice
448 )
449 /*++
450 Clarify whether FIFO buffer is full.
451 --*/
452 {
453 UINT8 Tail;
454 UINT8 Head;
455
456 Tail = TerminalDevice->RawFiFo.Tail;
457 Head = TerminalDevice->RawFiFo.Head;
458
459 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
460
461 return TRUE;
462 }
463
464 return FALSE;
465 }
466
467 BOOLEAN
468 EfiKeyFiFoInsertOneKey (
469 TERMINAL_DEV *TerminalDevice,
470 EFI_INPUT_KEY Key
471 )
472 /*++
473 Insert one pre-fetched key into the FIFO buffer.
474 If FIFO buffer is FULL before key insertion,
475 return FALSE, and the key is lost.
476 --*/
477 {
478 UINT8 Tail;
479
480 Tail = TerminalDevice->EfiKeyFiFo.Tail;
481
482 if (IsEfiKeyFiFoFull (TerminalDevice)) {
483 //
484 // Efi Key FIFO is full
485 //
486 return FALSE;
487 }
488
489 TerminalDevice->EfiKeyFiFo.Data[Tail] = Key;
490
491 TerminalDevice->EfiKeyFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
492
493 return TRUE;
494 }
495
496 BOOLEAN
497 EfiKeyFiFoRemoveOneKey (
498 TERMINAL_DEV *TerminalDevice,
499 EFI_INPUT_KEY *Output
500 )
501 /*++
502 Remove one pre-fetched key out of the FIFO buffer.
503 If FIFO buffer is empty before remove operation,
504 return FALSE.
505 --*/
506 {
507 UINT8 Head;
508
509 Head = TerminalDevice->EfiKeyFiFo.Head;
510
511 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
512 //
513 // FIFO is empty
514 //
515 Output->ScanCode = SCAN_NULL;
516 Output->UnicodeChar = 0;
517 return FALSE;
518 }
519
520 *Output = TerminalDevice->EfiKeyFiFo.Data[Head];
521
522 TerminalDevice->EfiKeyFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
523
524 return TRUE;
525 }
526
527 BOOLEAN
528 IsEfiKeyFiFoEmpty (
529 TERMINAL_DEV *TerminalDevice
530 )
531 /*++
532 Clarify whether FIFO buffer is empty.
533 --*/
534 {
535 if (TerminalDevice->EfiKeyFiFo.Head == TerminalDevice->EfiKeyFiFo.Tail) {
536 return TRUE;
537 } else {
538 return FALSE;
539 }
540 }
541
542 BOOLEAN
543 IsEfiKeyFiFoFull (
544 TERMINAL_DEV *TerminalDevice
545 )
546 /*++
547 Clarify whether FIFO buffer is full.
548 --*/
549 {
550 UINT8 Tail;
551 UINT8 Head;
552
553 Tail = TerminalDevice->EfiKeyFiFo.Tail;
554 Head = TerminalDevice->EfiKeyFiFo.Head;
555
556 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
557
558 return TRUE;
559 }
560
561 return FALSE;
562 }
563
564 BOOLEAN
565 UnicodeFiFoInsertOneKey (
566 TERMINAL_DEV *TerminalDevice,
567 UINT16 Input
568 )
569 /*++
570 Insert one pre-fetched key into the FIFO buffer.
571 If FIFO buffer is FULL before key insertion,
572 return FALSE, and the key is lost.
573 --*/
574 {
575 UINT8 Tail;
576
577 Tail = TerminalDevice->UnicodeFiFo.Tail;
578
579 if (IsUnicodeFiFoFull (TerminalDevice)) {
580 //
581 // Unicode FIFO is full
582 //
583 return FALSE;
584 }
585
586 TerminalDevice->UnicodeFiFo.Data[Tail] = Input;
587
588 TerminalDevice->UnicodeFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
589
590 return TRUE;
591 }
592
593 BOOLEAN
594 UnicodeFiFoRemoveOneKey (
595 TERMINAL_DEV *TerminalDevice,
596 UINT16 *Output
597 )
598 /*++
599 Remove one pre-fetched key out of the FIFO buffer.
600 If FIFO buffer is empty before remove operation,
601 return FALSE.
602 --*/
603 {
604 UINT8 Head;
605
606 Head = TerminalDevice->UnicodeFiFo.Head;
607
608 if (IsUnicodeFiFoEmpty (TerminalDevice)) {
609 //
610 // FIFO is empty
611 //
612 Output = NULL;
613 return FALSE;
614 }
615
616 *Output = TerminalDevice->UnicodeFiFo.Data[Head];
617
618 TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
619
620 return TRUE;
621 }
622
623 BOOLEAN
624 IsUnicodeFiFoEmpty (
625 TERMINAL_DEV *TerminalDevice
626 )
627 /*++
628 Clarify whether FIFO buffer is empty.
629 --*/
630 {
631 if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) {
632 return TRUE;
633 } else {
634 return FALSE;
635 }
636 }
637
638 BOOLEAN
639 IsUnicodeFiFoFull (
640 TERMINAL_DEV *TerminalDevice
641 )
642 /*++
643 Clarify whether FIFO buffer is full.
644 --*/
645 {
646 UINT8 Tail;
647 UINT8 Head;
648
649 Tail = TerminalDevice->UnicodeFiFo.Tail;
650 Head = TerminalDevice->UnicodeFiFo.Head;
651
652 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
653
654 return TRUE;
655 }
656
657 return FALSE;
658 }
659
660 UINT8
661 UnicodeFiFoGetKeyCount (
662 TERMINAL_DEV *TerminalDevice
663 )
664 {
665 UINT8 Tail;
666 UINT8 Head;
667
668 Tail = TerminalDevice->UnicodeFiFo.Tail;
669 Head = TerminalDevice->UnicodeFiFo.Head;
670
671 if (Tail >= Head) {
672 return (UINT8) (Tail - Head);
673 } else {
674 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
675 }
676 }
677
678 STATIC
679 VOID
680 UnicodeToEfiKeyFlushState (
681 IN TERMINAL_DEV *TerminalDevice
682 )
683 {
684 EFI_INPUT_KEY Key;
685
686 if (TerminalDevice->InputState & INPUT_STATE_ESC) {
687 Key.ScanCode = SCAN_ESC;
688 Key.UnicodeChar = 0;
689 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
690 }
691
692 if (TerminalDevice->InputState & INPUT_STATE_CSI) {
693 Key.ScanCode = SCAN_NULL;
694 Key.UnicodeChar = CSI;
695 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
696 }
697
698 if (TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) {
699 Key.ScanCode = SCAN_NULL;
700 Key.UnicodeChar = LEFTOPENBRACKET;
701 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
702 }
703
704 if (TerminalDevice->InputState & INPUT_STATE_O) {
705 Key.ScanCode = SCAN_NULL;
706 Key.UnicodeChar = 'O';
707 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
708 }
709
710 if (TerminalDevice->InputState & INPUT_STATE_2) {
711 Key.ScanCode = SCAN_NULL;
712 Key.UnicodeChar = '2';
713 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
714 }
715
716 gBS->SetTimer (
717 TerminalDevice->TwoSecondTimeOut,
718 TimerCancel,
719 0
720 );
721
722 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
723 }
724
725 VOID
726 UnicodeToEfiKey (
727 IN TERMINAL_DEV *TerminalDevice
728 )
729 /*++
730 Routine Description:
731
732 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
733 can be read through the Simple Input Protocol. The table below shows the keyboard
734 input mappings that this function supports. If the ESC sequence listed in one of the
735 columns is presented, then it is translated into the coorespoding EFI Scan Code. If a
736 matching sequence is not found, then the raw key strokes are converted into EFI Keys.
737
738 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
739 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
740 converted into EFI Keys.
741
742 There is one special input sequence that will force the system to reset.
743 This is ESC R ESC r ESC R.
744
745 Arguments:
746
747 TerminaDevice : The terminal device to use to translate raw input into EFI Keys
748
749 Returns:
750
751 None
752
753 Symbols used in table below
754 ===========================
755 ESC = 0x1B
756 CSI = 0x9B
757 DEL = 0x7f
758 ^ = CTRL
759
760 +=========+======+===========+==========+==========+
761 | | EFI | EFI 1.10 | | |
762 | | Scan | | VT100+ | |
763 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
764 +=========+======+===========+==========+==========+
765 | NULL | 0x00 | | | |
766 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
767 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
768 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
769 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
770 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
771 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
772 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
773 | | | ESC [ L | | ESC [ L |
774 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
775 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
776 | | | | | ESC [ ? |
777 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
778 | | | | | ESC [ / |
779 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
780 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
781 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
782 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
783 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
784 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
785 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
786 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
787 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
788 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
789 | Escape | 0x17 | ESC | ESC | ESC |
790 +=========+======+===========+==========+=========+
791
792 Special Mappings
793 ================
794 ESC R ESC r ESC R = Reset System
795
796 --*/
797 {
798 EFI_STATUS Status;
799 EFI_STATUS TimerStatus;
800 UINT16 UnicodeChar;
801 EFI_INPUT_KEY Key;
802 BOOLEAN SetDefaultResetState;
803
804 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
805
806 if (!EFI_ERROR (TimerStatus)) {
807 UnicodeToEfiKeyFlushState (TerminalDevice);
808 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
809 }
810
811 while (!IsUnicodeFiFoEmpty(TerminalDevice)) {
812
813 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
814 //
815 // Check to see if the 2 second timer has expired
816 //
817 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
818 if (!EFI_ERROR (TimerStatus)) {
819 UnicodeToEfiKeyFlushState (TerminalDevice);
820 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
821 }
822 }
823
824 //
825 // Fetch one Unicode character from the Unicode FIFO
826 //
827 UnicodeFiFoRemoveOneKey (TerminalDevice,&UnicodeChar);
828
829 SetDefaultResetState = TRUE;
830
831 switch (TerminalDevice->InputState) {
832 case INPUT_STATE_DEFAULT:
833
834 break;
835
836 case INPUT_STATE_ESC:
837
838 if (UnicodeChar == LEFTOPENBRACKET) {
839 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
840 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
841 continue;
842 }
843
844 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100Type) {
845 TerminalDevice->InputState |= INPUT_STATE_O;
846 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
847 continue;
848 }
849
850 Key.ScanCode = SCAN_NULL;
851
852 if (TerminalDevice->TerminalType == VT100PlusType ||
853 TerminalDevice->TerminalType == VTUTF8Type) {
854 switch (UnicodeChar) {
855 case '1':
856 Key.ScanCode = SCAN_F1;
857 break;
858 case '2':
859 Key.ScanCode = SCAN_F2;
860 break;
861 case '3':
862 Key.ScanCode = SCAN_F3;
863 break;
864 case '4':
865 Key.ScanCode = SCAN_F4;
866 break;
867 case '5':
868 Key.ScanCode = SCAN_F5;
869 break;
870 case '6':
871 Key.ScanCode = SCAN_F6;
872 break;
873 case '7':
874 Key.ScanCode = SCAN_F7;
875 break;
876 case '8':
877 Key.ScanCode = SCAN_F8;
878 break;
879 case '9':
880 Key.ScanCode = SCAN_F9;
881 break;
882 case '0':
883 Key.ScanCode = SCAN_F10;
884 break;
885 case 'h':
886 Key.ScanCode = SCAN_HOME;
887 break;
888 case 'k':
889 Key.ScanCode = SCAN_END;
890 break;
891 case '+':
892 Key.ScanCode = SCAN_INSERT;
893 break;
894 case '-':
895 Key.ScanCode = SCAN_DELETE;
896 break;
897 case '/':
898 Key.ScanCode = SCAN_PAGE_DOWN;
899 break;
900 case '?':
901 Key.ScanCode = SCAN_PAGE_UP;
902 break;
903 default :
904 break;
905 }
906 }
907
908 switch (UnicodeChar) {
909 case 'R':
910 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
911 TerminalDevice->ResetState = RESET_STATE_ESC_R;
912 SetDefaultResetState = FALSE;
913 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {
914 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
915 }
916 Key.ScanCode = SCAN_NULL;
917 break;
918 case 'r':
919 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
920 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;
921 SetDefaultResetState = FALSE;
922 }
923 Key.ScanCode = SCAN_NULL;
924 break;
925 default :
926 break;
927 }
928
929 if (SetDefaultResetState) {
930 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
931 }
932
933 if (Key.ScanCode != SCAN_NULL) {
934 Key.UnicodeChar = 0;
935 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
936 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
937 UnicodeToEfiKeyFlushState (TerminalDevice);
938 continue;
939 }
940
941 UnicodeToEfiKeyFlushState (TerminalDevice);
942
943 break;
944
945 case INPUT_STATE_ESC | INPUT_STATE_O:
946
947 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
948
949 Key.ScanCode = SCAN_NULL;
950
951 if (TerminalDevice->TerminalType == VT100Type) {
952 switch (UnicodeChar) {
953 case 'P':
954 Key.ScanCode = SCAN_F1;
955 break;
956 case 'Q':
957 Key.ScanCode = SCAN_F2;
958 break;
959 case 'w':
960 Key.ScanCode = SCAN_F3;
961 break;
962 case 'x':
963 Key.ScanCode = SCAN_F4;
964 break;
965 case 't':
966 Key.ScanCode = SCAN_F5;
967 break;
968 case 'u':
969 Key.ScanCode = SCAN_F6;
970 break;
971 case 'q':
972 Key.ScanCode = SCAN_F7;
973 break;
974 case 'r':
975 Key.ScanCode = SCAN_F8;
976 break;
977 case 'p':
978 Key.ScanCode = SCAN_F9;
979 break;
980 case 'M':
981 Key.ScanCode = SCAN_F10;
982 break;
983 default :
984 break;
985 }
986 }
987
988 if (Key.ScanCode != SCAN_NULL) {
989 Key.UnicodeChar = 0;
990 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
991 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
992 UnicodeToEfiKeyFlushState (TerminalDevice);
993 continue;
994 }
995
996 UnicodeToEfiKeyFlushState (TerminalDevice);
997
998 break;
999
1000 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
1001
1002 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1003
1004 Key.ScanCode = SCAN_NULL;
1005
1006 if (TerminalDevice->TerminalType == PcAnsiType ||
1007 TerminalDevice->TerminalType == VT100Type ||
1008 TerminalDevice->TerminalType == VT100PlusType ||
1009 TerminalDevice->TerminalType == VTUTF8Type) {
1010 switch (UnicodeChar) {
1011 case 'A':
1012 Key.ScanCode = SCAN_UP;
1013 break;
1014 case 'B':
1015 Key.ScanCode = SCAN_DOWN;
1016 break;
1017 case 'C':
1018 Key.ScanCode = SCAN_RIGHT;
1019 break;
1020 case 'D':
1021 Key.ScanCode = SCAN_LEFT;
1022 break;
1023 case 'H':
1024 if (TerminalDevice->TerminalType == PcAnsiType ||
1025 TerminalDevice->TerminalType == VT100Type) {
1026 Key.ScanCode = SCAN_HOME;
1027 }
1028 break;
1029 case 'F':
1030 if (TerminalDevice->TerminalType == PcAnsiType) {
1031 Key.ScanCode = SCAN_END;
1032 }
1033 break;
1034 case 'K':
1035 if (TerminalDevice->TerminalType == VT100Type) {
1036 Key.ScanCode = SCAN_END;
1037 }
1038 break;
1039 case 'L':
1040 case '@':
1041 if (TerminalDevice->TerminalType == PcAnsiType ||
1042 TerminalDevice->TerminalType == VT100Type) {
1043 Key.ScanCode = SCAN_INSERT;
1044 }
1045 break;
1046 case 'X':
1047 if (TerminalDevice->TerminalType == PcAnsiType) {
1048 Key.ScanCode = SCAN_DELETE;
1049 }
1050 break;
1051 case 'P':
1052 if (TerminalDevice->TerminalType == VT100Type) {
1053 Key.ScanCode = SCAN_DELETE;
1054 } else if (TerminalDevice->TerminalType == PcAnsiType) {
1055 Key.ScanCode = SCAN_F4;
1056 }
1057 break;
1058 case 'I':
1059 if (TerminalDevice->TerminalType == PcAnsiType) {
1060 Key.ScanCode = SCAN_PAGE_UP;
1061 }
1062 break;
1063 case 'V':
1064 if (TerminalDevice->TerminalType == PcAnsiType) {
1065 Key.ScanCode = SCAN_F10;
1066 }
1067 case '?':
1068 if (TerminalDevice->TerminalType == VT100Type) {
1069 Key.ScanCode = SCAN_PAGE_UP;
1070 }
1071 break;
1072 case 'G':
1073 if (TerminalDevice->TerminalType == PcAnsiType) {
1074 Key.ScanCode = SCAN_PAGE_DOWN;
1075 }
1076 break;
1077 case 'U':
1078 if (TerminalDevice->TerminalType == PcAnsiType) {
1079 Key.ScanCode = SCAN_F9;
1080 }
1081 case '/':
1082 if (TerminalDevice->TerminalType == VT100Type) {
1083 Key.ScanCode = SCAN_PAGE_DOWN;
1084 }
1085 break;
1086 case 'M':
1087 if (TerminalDevice->TerminalType == PcAnsiType) {
1088 Key.ScanCode = SCAN_F1;
1089 }
1090 break;
1091 case 'N':
1092 if (TerminalDevice->TerminalType == PcAnsiType) {
1093 Key.ScanCode = SCAN_F2;
1094 }
1095 break;
1096 case 'O':
1097 if (TerminalDevice->TerminalType == PcAnsiType) {
1098 Key.ScanCode = SCAN_F3;
1099 }
1100 break;
1101 case 'Q':
1102 if (TerminalDevice->TerminalType == PcAnsiType) {
1103 Key.ScanCode = SCAN_F5;
1104 }
1105 break;
1106 case 'R':
1107 if (TerminalDevice->TerminalType == PcAnsiType) {
1108 Key.ScanCode = SCAN_F6;
1109 }
1110 break;
1111 case 'S':
1112 if (TerminalDevice->TerminalType == PcAnsiType) {
1113 Key.ScanCode = SCAN_F7;
1114 }
1115 break;
1116 case 'T':
1117 if (TerminalDevice->TerminalType == PcAnsiType) {
1118 Key.ScanCode = SCAN_F8;
1119 }
1120 break;
1121 default :
1122 break;
1123 }
1124 }
1125
1126 if (Key.ScanCode != SCAN_NULL) {
1127 Key.UnicodeChar = 0;
1128 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1129 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1130 UnicodeToEfiKeyFlushState (TerminalDevice);
1131 continue;
1132 }
1133
1134 UnicodeToEfiKeyFlushState (TerminalDevice);
1135
1136 break;
1137
1138
1139 default:
1140 //
1141 // Invalid state. This should never happen.
1142 //
1143 ASSERT (FALSE);
1144
1145 UnicodeToEfiKeyFlushState (TerminalDevice);
1146
1147 break;
1148 }
1149
1150 if (UnicodeChar == ESC) {
1151 TerminalDevice->InputState = INPUT_STATE_ESC;
1152 }
1153
1154 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1155 Status = gBS->SetTimer(
1156 TerminalDevice->TwoSecondTimeOut,
1157 TimerRelative,
1158 (UINT64)20000000
1159 );
1160 ASSERT_EFI_ERROR (Status);
1161 continue;
1162 }
1163
1164 if (SetDefaultResetState) {
1165 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1166 }
1167
1168 if (UnicodeChar == DEL) {
1169 Key.ScanCode = SCAN_DELETE;
1170 Key.UnicodeChar = 0;
1171 } else {
1172 Key.ScanCode = SCAN_NULL;
1173 Key.UnicodeChar = UnicodeChar;
1174 }
1175
1176 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1177 }
1178 }