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