]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
MdeModulePkg: Source fixes and cleanup for ARMGCC compiles
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConIn.c
1 /** @file
2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
3
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Terminal.h"
17
18
19 /**
20 Reads the next keystroke from the input device. The WaitForKey Event can
21 be used to test for existence of a keystroke via WaitForEvent () call.
22
23 @param TerminalDevice Terminal driver private structure
24 @param KeyData A pointer to a buffer that is filled in with the
25 keystroke state data for the key that was
26 pressed.
27
28 @retval EFI_SUCCESS The keystroke information was returned.
29 @retval EFI_NOT_READY There was no keystroke data available.
30 @retval EFI_INVALID_PARAMETER KeyData is NULL.
31
32 **/
33 EFI_STATUS
34 ReadKeyStrokeWorker (
35 IN TERMINAL_DEV *TerminalDevice,
36 OUT EFI_KEY_DATA *KeyData
37 )
38 {
39 if (KeyData == NULL) {
40 return EFI_INVALID_PARAMETER;
41 }
42
43 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
44 return EFI_NOT_READY;
45 }
46
47 KeyData->KeyState.KeyShiftState = 0;
48 KeyData->KeyState.KeyToggleState = 0;
49
50
51 return EFI_SUCCESS;
52
53 }
54
55 /**
56 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
57 This driver only perform dependent serial device reset regardless of
58 the value of ExtendeVerification
59
60 @param This Indicates the calling context.
61 @param ExtendedVerification Skip by this driver.
62
63 @retval EFI_SUCCESS The reset operation succeeds.
64 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
65
66 **/
67 EFI_STATUS
68 EFIAPI
69 TerminalConInReset (
70 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
71 IN BOOLEAN ExtendedVerification
72 )
73 {
74 EFI_STATUS Status;
75 TERMINAL_DEV *TerminalDevice;
76
77 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
78
79 //
80 // Report progress code here
81 //
82 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
83 EFI_PROGRESS_CODE,
84 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
85 TerminalDevice->DevicePath
86 );
87
88 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
89
90 //
91 // Make all the internal buffer empty for keys
92 //
93 TerminalDevice->RawFiFo->Head = TerminalDevice->RawFiFo->Tail;
94 TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;
95 TerminalDevice->EfiKeyFiFo->Head = TerminalDevice->EfiKeyFiFo->Tail;
96
97 if (EFI_ERROR (Status)) {
98 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
99 EFI_ERROR_CODE | EFI_ERROR_MINOR,
100 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
101 TerminalDevice->DevicePath
102 );
103 }
104
105 return Status;
106 }
107
108 /**
109 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
110
111 @param This Indicates the calling context.
112 @param Key A pointer to a buffer that is filled in with the
113 keystroke information for the key that was sent
114 from terminal.
115
116 @retval EFI_SUCCESS The keystroke information is returned successfully.
117 @retval EFI_NOT_READY There is no keystroke data available.
118 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
119
120 **/
121 EFI_STATUS
122 EFIAPI
123 TerminalConInReadKeyStroke (
124 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
125 OUT EFI_INPUT_KEY *Key
126 )
127 {
128 TERMINAL_DEV *TerminalDevice;
129 EFI_STATUS Status;
130 EFI_KEY_DATA KeyData;
131
132 //
133 // get TERMINAL_DEV from "This" parameter.
134 //
135 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
136
137 Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);
138 if (EFI_ERROR (Status)) {
139 return Status;
140 }
141
142 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
143
144 return EFI_SUCCESS;
145
146 }
147
148 /**
149 Check if the key already has been registered.
150
151 If both RegsiteredData and InputData is NULL, then ASSERT().
152
153 @param RegsiteredData A pointer to a buffer that is filled in with the
154 keystroke state data for the key that was
155 registered.
156 @param InputData A pointer to a buffer that is filled in with the
157 keystroke state data for the key that was
158 pressed.
159
160 @retval TRUE Key be pressed matches a registered key.
161 @retval FALSE Match failed.
162
163 **/
164 BOOLEAN
165 IsKeyRegistered (
166 IN EFI_KEY_DATA *RegsiteredData,
167 IN EFI_KEY_DATA *InputData
168 )
169 {
170 ASSERT (RegsiteredData != NULL && InputData != NULL);
171
172 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
173 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
174 return FALSE;
175 }
176
177 return TRUE;
178 }
179
180
181
182 /**
183 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
184 Signal the event if there is key available
185
186 @param Event Indicates the event that invoke this function.
187 @param Context Indicates the calling context.
188
189 **/
190 VOID
191 EFIAPI
192 TerminalConInWaitForKeyEx (
193 IN EFI_EVENT Event,
194 IN VOID *Context
195 )
196 {
197 TerminalConInWaitForKey (Event, Context);
198 }
199
200 //
201 // Simple Text Input Ex protocol functions
202 //
203
204 /**
205 Reset the input device and optionally run diagnostics
206
207 @param This Protocol instance pointer.
208 @param ExtendedVerification Driver may perform diagnostics on reset.
209
210 @retval EFI_SUCCESS The device was reset.
211 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
212 not be reset.
213
214 **/
215 EFI_STATUS
216 EFIAPI
217 TerminalConInResetEx (
218 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
219 IN BOOLEAN ExtendedVerification
220 )
221 {
222 EFI_STATUS Status;
223 TERMINAL_DEV *TerminalDevice;
224
225 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
226
227 Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);
228 if (EFI_ERROR (Status)) {
229 return EFI_DEVICE_ERROR;
230 }
231
232 return EFI_SUCCESS;
233
234 }
235
236
237 /**
238 Reads the next keystroke from the input device. The WaitForKey Event can
239 be used to test for existence of a keystroke via WaitForEvent () call.
240
241 @param This Protocol instance pointer.
242 @param KeyData A pointer to a buffer that is filled in with the
243 keystroke state data for the key that was
244 pressed.
245
246 @retval EFI_SUCCESS The keystroke information was returned.
247 @retval EFI_NOT_READY There was no keystroke data available.
248 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
249 to hardware errors.
250 @retval EFI_INVALID_PARAMETER KeyData is NULL.
251
252 **/
253 EFI_STATUS
254 EFIAPI
255 TerminalConInReadKeyStrokeEx (
256 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
257 OUT EFI_KEY_DATA *KeyData
258 )
259 {
260 TERMINAL_DEV *TerminalDevice;
261
262 if (KeyData == NULL) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
267
268 return ReadKeyStrokeWorker (TerminalDevice, KeyData);
269
270 }
271
272
273 /**
274 Set certain state for the input device.
275
276 @param This Protocol instance pointer.
277 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
278 state for the input device.
279
280 @retval EFI_SUCCESS The device state was set successfully.
281 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
282 could not have the setting adjusted.
283 @retval EFI_UNSUPPORTED The device does not have the ability to set its
284 state.
285 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
286
287 **/
288 EFI_STATUS
289 EFIAPI
290 TerminalConInSetState (
291 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
292 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
293 )
294 {
295 if (KeyToggleState == NULL) {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
300 return EFI_UNSUPPORTED;
301 }
302
303 return EFI_SUCCESS;
304 }
305
306
307 /**
308 Register a notification function for a particular keystroke for the input device.
309
310 @param This Protocol instance pointer.
311 @param KeyData A pointer to a buffer that is filled in with the
312 keystroke information data for the key that was
313 pressed.
314 @param KeyNotificationFunction Points to the function to be called when the key
315 sequence is typed specified by KeyData.
316 @param NotifyHandle Points to the unique handle assigned to the
317 registered notification.
318
319 @retval EFI_SUCCESS The notification function was registered
320 successfully.
321 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
322 structures.
323 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
324
325 **/
326 EFI_STATUS
327 EFIAPI
328 TerminalConInRegisterKeyNotify (
329 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
330 IN EFI_KEY_DATA *KeyData,
331 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
332 OUT VOID **NotifyHandle
333 )
334 {
335 TERMINAL_DEV *TerminalDevice;
336 TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify;
337 LIST_ENTRY *Link;
338 LIST_ENTRY *NotifyList;
339 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
340
341 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
342 return EFI_INVALID_PARAMETER;
343 }
344
345 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
346
347 //
348 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
349 //
350 NotifyList = &TerminalDevice->NotifyList;
351 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
352 CurrentNotify = CR (
353 Link,
354 TERMINAL_CONSOLE_IN_EX_NOTIFY,
355 NotifyEntry,
356 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
357 );
358 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
359 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
360 *NotifyHandle = CurrentNotify;
361 return EFI_SUCCESS;
362 }
363 }
364 }
365
366 //
367 // Allocate resource to save the notification function
368 //
369 NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));
370 if (NewNotify == NULL) {
371 return EFI_OUT_OF_RESOURCES;
372 }
373
374 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
375 NewNotify->KeyNotificationFn = KeyNotificationFunction;
376 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
377 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);
378
379 *NotifyHandle = NewNotify;
380
381 return EFI_SUCCESS;
382 }
383
384
385 /**
386 Remove a registered notification function from a particular keystroke.
387
388 @param This Protocol instance pointer.
389 @param NotificationHandle The handle of the notification function being
390 unregistered.
391
392 @retval EFI_SUCCESS The notification function was unregistered
393 successfully.
394 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
395
396 **/
397 EFI_STATUS
398 EFIAPI
399 TerminalConInUnregisterKeyNotify (
400 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
401 IN VOID *NotificationHandle
402 )
403 {
404 TERMINAL_DEV *TerminalDevice;
405 LIST_ENTRY *Link;
406 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
407 LIST_ENTRY *NotifyList;
408
409 if (NotificationHandle == NULL) {
410 return EFI_INVALID_PARAMETER;
411 }
412
413 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
414
415 NotifyList = &TerminalDevice->NotifyList;
416 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
417 CurrentNotify = CR (
418 Link,
419 TERMINAL_CONSOLE_IN_EX_NOTIFY,
420 NotifyEntry,
421 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
422 );
423 if (CurrentNotify == NotificationHandle) {
424 //
425 // Remove the notification function from NotifyList and free resources
426 //
427 RemoveEntryList (&CurrentNotify->NotifyEntry);
428
429 gBS->FreePool (CurrentNotify);
430 return EFI_SUCCESS;
431 }
432 }
433
434 //
435 // Can not find the matching entry in database.
436 //
437 return EFI_INVALID_PARAMETER;
438 }
439
440 /**
441 Translate raw data into Unicode (according to different encode), and
442 translate Unicode into key information. (according to different standard).
443
444 @param TerminalDevice Terminal driver private structure.
445
446 **/
447 VOID
448 TranslateRawDataToEfiKey (
449 IN TERMINAL_DEV *TerminalDevice
450 )
451 {
452 switch (TerminalDevice->TerminalType) {
453
454 case PCANSITYPE:
455 case VT100TYPE:
456 case VT100PLUSTYPE:
457 AnsiRawDataToUnicode (TerminalDevice);
458 UnicodeToEfiKey (TerminalDevice);
459 break;
460
461 case VTUTF8TYPE:
462 //
463 // Process all the raw data in the RawFIFO,
464 // put the processed key into UnicodeFIFO.
465 //
466 VTUTF8RawDataToUnicode (TerminalDevice);
467
468 //
469 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
470 // then put into EfiKeyFIFO.
471 //
472 UnicodeToEfiKey (TerminalDevice);
473
474 break;
475 }
476 }
477
478 /**
479 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
480 Signal the event if there is key available
481
482 @param Event Indicates the event that invoke this function.
483 @param Context Indicates the calling context.
484
485 **/
486 VOID
487 EFIAPI
488 TerminalConInWaitForKey (
489 IN EFI_EVENT Event,
490 IN VOID *Context
491 )
492 {
493 //
494 // Someone is waiting on the keystroke event, if there's
495 // a key pending, signal the event
496 //
497 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {
498
499 gBS->SignalEvent (Event);
500 }
501 }
502
503 /**
504 Timer handler to poll the key from serial.
505
506 @param Event Indicates the event that invoke this function.
507 @param Context Indicates the calling context.
508 **/
509 VOID
510 EFIAPI
511 TerminalConInTimerHandler (
512 IN EFI_EVENT Event,
513 IN VOID *Context
514 )
515 {
516 EFI_STATUS Status;
517 TERMINAL_DEV *TerminalDevice;
518 UINT32 Control;
519 UINT8 Input;
520 EFI_SERIAL_IO_MODE *Mode;
521 EFI_SERIAL_IO_PROTOCOL *SerialIo;
522 UINTN SerialInTimeOut;
523
524 TerminalDevice = (TERMINAL_DEV *) Context;
525
526 SerialIo = TerminalDevice->SerialIo;
527 if (SerialIo == NULL) {
528 return ;
529 }
530 //
531 // if current timeout value for serial device is not identical with
532 // the value saved in TERMINAL_DEV structure, then recalculate the
533 // timeout value again and set serial attribute according to this value.
534 //
535 Mode = SerialIo->Mode;
536 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
537
538 SerialInTimeOut = 0;
539 if (Mode->BaudRate != 0) {
540 //
541 // According to BAUD rate to calculate the timeout value.
542 //
543 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
544 }
545
546 Status = SerialIo->SetAttributes (
547 SerialIo,
548 Mode->BaudRate,
549 Mode->ReceiveFifoDepth,
550 (UINT32) SerialInTimeOut,
551 (EFI_PARITY_TYPE) (Mode->Parity),
552 (UINT8) Mode->DataBits,
553 (EFI_STOP_BITS_TYPE) (Mode->StopBits)
554 );
555
556 if (EFI_ERROR (Status)) {
557 TerminalDevice->SerialInTimeOut = 0;
558 } else {
559 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
560 }
561 }
562 //
563 // Check whether serial buffer is empty.
564 //
565 Status = SerialIo->GetControl (SerialIo, &Control);
566
567 if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0) {
568 //
569 // Fetch all the keys in the serial buffer,
570 // and insert the byte stream into RawFIFO.
571 //
572 while (!IsRawFiFoFull (TerminalDevice)) {
573
574 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
575
576 if (EFI_ERROR (Status)) {
577 if (Status == EFI_DEVICE_ERROR) {
578 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
579 EFI_ERROR_CODE | EFI_ERROR_MINOR,
580 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),
581 TerminalDevice->DevicePath
582 );
583 }
584 break;
585 }
586
587 RawFiFoInsertOneKey (TerminalDevice, Input);
588 }
589 }
590
591 //
592 // Translate all the raw data in RawFIFO into EFI Key,
593 // according to different terminal type supported.
594 //
595 TranslateRawDataToEfiKey (TerminalDevice);
596 }
597
598 /**
599 Get one key out of serial buffer.
600
601 @param SerialIo Serial I/O protocol attached to the serial device.
602 @param Output The fetched key.
603
604 @retval EFI_NOT_READY If serial buffer is empty.
605 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
606 @retval EFI_SUCCESS If reading serial buffer successfully, put
607 the fetched key to the parameter output.
608
609 **/
610 EFI_STATUS
611 GetOneKeyFromSerial (
612 EFI_SERIAL_IO_PROTOCOL *SerialIo,
613 UINT8 *Output
614 )
615 {
616 EFI_STATUS Status;
617 UINTN Size;
618
619 Size = 1;
620 *Output = 0;
621
622 //
623 // Read one key from serial I/O device.
624 //
625 Status = SerialIo->Read (SerialIo, &Size, Output);
626
627 if (EFI_ERROR (Status)) {
628
629 if (Status == EFI_TIMEOUT) {
630 return EFI_NOT_READY;
631 }
632
633 return EFI_DEVICE_ERROR;
634
635 }
636
637 if (*Output == 0) {
638 return EFI_NOT_READY;
639 }
640
641 return EFI_SUCCESS;
642 }
643
644 /**
645 Insert one byte raw data into the Raw Data FIFO.
646
647 @param TerminalDevice Terminal driver private structure.
648 @param Input The key will be input.
649
650 @retval TRUE If insert successfully.
651 @retval FALSE If Raw Data buffer is full before key insertion,
652 and the key is lost.
653
654 **/
655 BOOLEAN
656 RawFiFoInsertOneKey (
657 TERMINAL_DEV *TerminalDevice,
658 UINT8 Input
659 )
660 {
661 UINT8 Tail;
662
663 Tail = TerminalDevice->RawFiFo->Tail;
664
665 if (IsRawFiFoFull (TerminalDevice)) {
666 //
667 // Raw FIFO is full
668 //
669 return FALSE;
670 }
671
672 TerminalDevice->RawFiFo->Data[Tail] = Input;
673
674 TerminalDevice->RawFiFo->Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
675
676 return TRUE;
677 }
678
679 /**
680 Remove one pre-fetched key out of the Raw Data FIFO.
681
682 @param TerminalDevice Terminal driver private structure.
683 @param Output The key will be removed.
684
685 @retval TRUE If insert successfully.
686 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
687
688 **/
689 BOOLEAN
690 RawFiFoRemoveOneKey (
691 TERMINAL_DEV *TerminalDevice,
692 UINT8 *Output
693 )
694 {
695 UINT8 Head;
696
697 Head = TerminalDevice->RawFiFo->Head;
698
699 if (IsRawFiFoEmpty (TerminalDevice)) {
700 //
701 // FIFO is empty
702 //
703 *Output = 0;
704 return FALSE;
705 }
706
707 *Output = TerminalDevice->RawFiFo->Data[Head];
708
709 TerminalDevice->RawFiFo->Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
710
711 return TRUE;
712 }
713
714 /**
715 Clarify whether Raw Data FIFO buffer is empty.
716
717 @param TerminalDevice Terminal driver private structure
718
719 @retval TRUE If Raw Data FIFO buffer is empty.
720 @retval FALSE If Raw Data FIFO buffer is not empty.
721
722 **/
723 BOOLEAN
724 IsRawFiFoEmpty (
725 TERMINAL_DEV *TerminalDevice
726 )
727 {
728 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {
729 return TRUE;
730 } else {
731 return FALSE;
732 }
733 }
734
735 /**
736 Clarify whether Raw Data FIFO buffer is full.
737
738 @param TerminalDevice Terminal driver private structure
739
740 @retval TRUE If Raw Data FIFO buffer is full.
741 @retval FALSE If Raw Data FIFO buffer is not full.
742
743 **/
744 BOOLEAN
745 IsRawFiFoFull (
746 TERMINAL_DEV *TerminalDevice
747 )
748 {
749 UINT8 Tail;
750 UINT8 Head;
751
752 Tail = TerminalDevice->RawFiFo->Tail;
753 Head = TerminalDevice->RawFiFo->Head;
754
755 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
756
757 return TRUE;
758 }
759
760 return FALSE;
761 }
762
763 /**
764 Insert one pre-fetched key into the FIFO buffer.
765
766 @param TerminalDevice Terminal driver private structure.
767 @param Key The key will be input.
768
769 @retval TRUE If insert successfully.
770 @retval FALSE If FIFO buffer is full before key insertion,
771 and the key is lost.
772
773 **/
774 BOOLEAN
775 EfiKeyFiFoInsertOneKey (
776 TERMINAL_DEV *TerminalDevice,
777 EFI_INPUT_KEY *Key
778 )
779 {
780 UINT8 Tail;
781 LIST_ENTRY *Link;
782 LIST_ENTRY *NotifyList;
783 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
784 EFI_KEY_DATA KeyData;
785
786 Tail = TerminalDevice->EfiKeyFiFo->Tail;
787
788 CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));
789 KeyData.KeyState.KeyShiftState = 0;
790 KeyData.KeyState.KeyToggleState = 0;
791
792 //
793 // Invoke notification functions if exist
794 //
795 NotifyList = &TerminalDevice->NotifyList;
796 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
797 CurrentNotify = CR (
798 Link,
799 TERMINAL_CONSOLE_IN_EX_NOTIFY,
800 NotifyEntry,
801 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
802 );
803 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
804 CurrentNotify->KeyNotificationFn (&KeyData);
805 }
806 }
807 if (IsEfiKeyFiFoFull (TerminalDevice)) {
808 //
809 // Efi Key FIFO is full
810 //
811 return FALSE;
812 }
813
814 CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));
815
816 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
817
818 return TRUE;
819 }
820
821 /**
822 Remove one pre-fetched key out of the FIFO buffer.
823
824 @param TerminalDevice Terminal driver private structure.
825 @param Output The key will be removed.
826
827 @retval TRUE If insert successfully.
828 @retval FALSE If FIFO buffer is empty before remove operation.
829
830 **/
831 BOOLEAN
832 EfiKeyFiFoRemoveOneKey (
833 TERMINAL_DEV *TerminalDevice,
834 EFI_INPUT_KEY *Output
835 )
836 {
837 UINT8 Head;
838
839 Head = TerminalDevice->EfiKeyFiFo->Head;
840 ASSERT (Head < FIFO_MAX_NUMBER + 1);
841
842 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
843 //
844 // FIFO is empty
845 //
846 Output->ScanCode = SCAN_NULL;
847 Output->UnicodeChar = 0;
848 return FALSE;
849 }
850
851 CopyMem (Output, &TerminalDevice->EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
852
853 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
854
855 return TRUE;
856 }
857
858 /**
859 Clarify whether FIFO buffer is empty.
860
861 @param TerminalDevice Terminal driver private structure
862
863 @retval TRUE If FIFO buffer is empty.
864 @retval FALSE If FIFO buffer is not empty.
865
866 **/
867 BOOLEAN
868 IsEfiKeyFiFoEmpty (
869 TERMINAL_DEV *TerminalDevice
870 )
871 {
872 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {
873 return TRUE;
874 } else {
875 return FALSE;
876 }
877 }
878
879 /**
880 Clarify whether FIFO buffer is full.
881
882 @param TerminalDevice Terminal driver private structure
883
884 @retval TRUE If FIFO buffer is full.
885 @retval FALSE If FIFO buffer is not full.
886
887 **/
888 BOOLEAN
889 IsEfiKeyFiFoFull (
890 TERMINAL_DEV *TerminalDevice
891 )
892 {
893 UINT8 Tail;
894 UINT8 Head;
895
896 Tail = TerminalDevice->EfiKeyFiFo->Tail;
897 Head = TerminalDevice->EfiKeyFiFo->Head;
898
899 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
900
901 return TRUE;
902 }
903
904 return FALSE;
905 }
906
907 /**
908 Insert one pre-fetched key into the Unicode FIFO buffer.
909
910 @param TerminalDevice Terminal driver private structure.
911 @param Input The key will be input.
912
913 @retval TRUE If insert successfully.
914 @retval FALSE If Unicode FIFO buffer is full before key insertion,
915 and the key is lost.
916
917 **/
918 BOOLEAN
919 UnicodeFiFoInsertOneKey (
920 TERMINAL_DEV *TerminalDevice,
921 UINT16 Input
922 )
923 {
924 UINT8 Tail;
925
926 Tail = TerminalDevice->UnicodeFiFo->Tail;
927 ASSERT (Tail < FIFO_MAX_NUMBER + 1);
928
929
930 if (IsUnicodeFiFoFull (TerminalDevice)) {
931 //
932 // Unicode FIFO is full
933 //
934 return FALSE;
935 }
936
937 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;
938
939 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
940
941 return TRUE;
942 }
943
944 /**
945 Remove one pre-fetched key out of the Unicode FIFO buffer.
946 The caller should guarantee that Unicode FIFO buffer is not empty
947 by IsUnicodeFiFoEmpty ().
948
949 @param TerminalDevice Terminal driver private structure.
950 @param Output The key will be removed.
951
952 **/
953 VOID
954 UnicodeFiFoRemoveOneKey (
955 TERMINAL_DEV *TerminalDevice,
956 UINT16 *Output
957 )
958 {
959 UINT8 Head;
960
961 Head = TerminalDevice->UnicodeFiFo->Head;
962 ASSERT (Head < FIFO_MAX_NUMBER + 1);
963
964 *Output = TerminalDevice->UnicodeFiFo->Data[Head];
965
966 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
967 }
968
969 /**
970 Clarify whether Unicode FIFO buffer is empty.
971
972 @param TerminalDevice Terminal driver private structure
973
974 @retval TRUE If Unicode FIFO buffer is empty.
975 @retval FALSE If Unicode FIFO buffer is not empty.
976
977 **/
978 BOOLEAN
979 IsUnicodeFiFoEmpty (
980 TERMINAL_DEV *TerminalDevice
981 )
982 {
983 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {
984 return TRUE;
985 } else {
986 return FALSE;
987 }
988 }
989
990 /**
991 Clarify whether Unicode FIFO buffer is full.
992
993 @param TerminalDevice Terminal driver private structure
994
995 @retval TRUE If Unicode FIFO buffer is full.
996 @retval FALSE If Unicode FIFO buffer is not full.
997
998 **/
999 BOOLEAN
1000 IsUnicodeFiFoFull (
1001 TERMINAL_DEV *TerminalDevice
1002 )
1003 {
1004 UINT8 Tail;
1005 UINT8 Head;
1006
1007 Tail = TerminalDevice->UnicodeFiFo->Tail;
1008 Head = TerminalDevice->UnicodeFiFo->Head;
1009
1010 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
1011
1012 return TRUE;
1013 }
1014
1015 return FALSE;
1016 }
1017
1018 /**
1019 Count Unicode FIFO buffer.
1020
1021 @param TerminalDevice Terminal driver private structure
1022
1023 @return The count in bytes of Unicode FIFO.
1024
1025 **/
1026 UINT8
1027 UnicodeFiFoGetKeyCount (
1028 TERMINAL_DEV *TerminalDevice
1029 )
1030 {
1031 UINT8 Tail;
1032 UINT8 Head;
1033
1034 Tail = TerminalDevice->UnicodeFiFo->Tail;
1035 Head = TerminalDevice->UnicodeFiFo->Head;
1036
1037 if (Tail >= Head) {
1038 return (UINT8) (Tail - Head);
1039 } else {
1040 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
1041 }
1042 }
1043
1044 /**
1045 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1046
1047 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1048
1049 **/
1050 VOID
1051 UnicodeToEfiKeyFlushState (
1052 IN TERMINAL_DEV *TerminalDevice
1053 )
1054 {
1055 EFI_INPUT_KEY Key;
1056 UINT32 InputState;
1057
1058 InputState = TerminalDevice->InputState;
1059
1060 if (IsEfiKeyFiFoFull (TerminalDevice)) {
1061 return;
1062 }
1063
1064 if ((InputState & INPUT_STATE_ESC) != 0) {
1065 Key.ScanCode = SCAN_ESC;
1066 Key.UnicodeChar = 0;
1067 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1068 }
1069
1070 if ((InputState & INPUT_STATE_CSI) != 0) {
1071 Key.ScanCode = SCAN_NULL;
1072 Key.UnicodeChar = CSI;
1073 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1074 }
1075
1076 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
1077 Key.ScanCode = SCAN_NULL;
1078 Key.UnicodeChar = LEFTOPENBRACKET;
1079 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1080 }
1081
1082 if ((InputState & INPUT_STATE_O) != 0) {
1083 Key.ScanCode = SCAN_NULL;
1084 Key.UnicodeChar = 'O';
1085 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1086 }
1087
1088 if ((InputState & INPUT_STATE_2) != 0) {
1089 Key.ScanCode = SCAN_NULL;
1090 Key.UnicodeChar = '2';
1091 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1092 }
1093
1094 //
1095 // Cancel the timer.
1096 //
1097 gBS->SetTimer (
1098 TerminalDevice->TwoSecondTimeOut,
1099 TimerCancel,
1100 0
1101 );
1102
1103 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1104 }
1105
1106
1107 /**
1108 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1109 can be read through the Simple Input Protocol.
1110
1111 The table below shows the keyboard input mappings that this function supports.
1112 If the ESC sequence listed in one of the columns is presented, then it is translated
1113 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1114 key strokes are converted into EFI Keys.
1115
1116 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1117 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1118 converted into EFI Keys.
1119 There is one special input sequence that will force the system to reset.
1120 This is ESC R ESC r ESC R.
1121
1122 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1123 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1124 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1125
1126 Symbols used in table below
1127 ===========================
1128 ESC = 0x1B
1129 CSI = 0x9B
1130 DEL = 0x7f
1131 ^ = CTRL
1132
1133 +=========+======+===========+==========+==========+
1134 | | EFI | UEFI 2.0 | | |
1135 | | Scan | | VT100+ | |
1136 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1137 +=========+======+===========+==========+==========+
1138 | NULL | 0x00 | | | |
1139 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1140 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1141 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1142 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1143 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1144 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1145 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1146 | | | ESC [ L | | ESC [ L |
1147 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1148 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1149 | | | | | ESC [ ? |
1150 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1151 | | | | | ESC [ / |
1152 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1153 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1154 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1155 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1156 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1157 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1158 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1159 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1160 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1161 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1162 | Escape | 0x17 | ESC | ESC | ESC |
1163 | F11 | 0x15 | | ESC ! | |
1164 | F12 | 0x16 | | ESC @ | |
1165 +=========+======+===========+==========+==========+
1166
1167 Special Mappings
1168 ================
1169 ESC R ESC r ESC R = Reset System
1170
1171 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1172
1173 **/
1174 VOID
1175 UnicodeToEfiKey (
1176 IN TERMINAL_DEV *TerminalDevice
1177 )
1178 {
1179 EFI_STATUS Status;
1180 EFI_STATUS TimerStatus;
1181 UINT16 UnicodeChar;
1182 EFI_INPUT_KEY Key;
1183 BOOLEAN SetDefaultResetState;
1184
1185 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1186
1187 if (!EFI_ERROR (TimerStatus)) {
1188 UnicodeToEfiKeyFlushState (TerminalDevice);
1189 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1190 }
1191
1192 while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) {
1193
1194 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1195 //
1196 // Check to see if the 2 seconds timer has expired
1197 //
1198 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1199 if (!EFI_ERROR (TimerStatus)) {
1200 UnicodeToEfiKeyFlushState (TerminalDevice);
1201 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1202 }
1203 }
1204
1205 //
1206 // Fetch one Unicode character from the Unicode FIFO
1207 //
1208 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);
1209
1210 SetDefaultResetState = TRUE;
1211
1212 switch (TerminalDevice->InputState) {
1213 case INPUT_STATE_DEFAULT:
1214
1215 break;
1216
1217 case INPUT_STATE_ESC:
1218
1219 if (UnicodeChar == LEFTOPENBRACKET) {
1220 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
1221 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1222 continue;
1223 }
1224
1225 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {
1226 TerminalDevice->InputState |= INPUT_STATE_O;
1227 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1228 continue;
1229 }
1230
1231 Key.ScanCode = SCAN_NULL;
1232
1233 if (TerminalDevice->TerminalType == VT100PLUSTYPE ||
1234 TerminalDevice->TerminalType == VTUTF8TYPE) {
1235 switch (UnicodeChar) {
1236 case '1':
1237 Key.ScanCode = SCAN_F1;
1238 break;
1239 case '2':
1240 Key.ScanCode = SCAN_F2;
1241 break;
1242 case '3':
1243 Key.ScanCode = SCAN_F3;
1244 break;
1245 case '4':
1246 Key.ScanCode = SCAN_F4;
1247 break;
1248 case '5':
1249 Key.ScanCode = SCAN_F5;
1250 break;
1251 case '6':
1252 Key.ScanCode = SCAN_F6;
1253 break;
1254 case '7':
1255 Key.ScanCode = SCAN_F7;
1256 break;
1257 case '8':
1258 Key.ScanCode = SCAN_F8;
1259 break;
1260 case '9':
1261 Key.ScanCode = SCAN_F9;
1262 break;
1263 case '0':
1264 Key.ScanCode = SCAN_F10;
1265 break;
1266 case '!':
1267 Key.ScanCode = SCAN_F11;
1268 break;
1269 case '@':
1270 Key.ScanCode = SCAN_F12;
1271 break;
1272 case 'h':
1273 Key.ScanCode = SCAN_HOME;
1274 break;
1275 case 'k':
1276 Key.ScanCode = SCAN_END;
1277 break;
1278 case '+':
1279 Key.ScanCode = SCAN_INSERT;
1280 break;
1281 case '-':
1282 Key.ScanCode = SCAN_DELETE;
1283 break;
1284 case '/':
1285 Key.ScanCode = SCAN_PAGE_DOWN;
1286 break;
1287 case '?':
1288 Key.ScanCode = SCAN_PAGE_UP;
1289 break;
1290 default :
1291 break;
1292 }
1293 }
1294
1295 switch (UnicodeChar) {
1296 case 'R':
1297 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
1298 TerminalDevice->ResetState = RESET_STATE_ESC_R;
1299 SetDefaultResetState = FALSE;
1300 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {
1301 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1302 }
1303 Key.ScanCode = SCAN_NULL;
1304 break;
1305 case 'r':
1306 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
1307 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;
1308 SetDefaultResetState = FALSE;
1309 }
1310 Key.ScanCode = SCAN_NULL;
1311 break;
1312 default :
1313 break;
1314 }
1315
1316 if (SetDefaultResetState) {
1317 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1318 }
1319
1320 if (Key.ScanCode != SCAN_NULL) {
1321 Key.UnicodeChar = 0;
1322 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1323 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1324 UnicodeToEfiKeyFlushState (TerminalDevice);
1325 continue;
1326 }
1327
1328 UnicodeToEfiKeyFlushState (TerminalDevice);
1329
1330 break;
1331
1332 case INPUT_STATE_ESC | INPUT_STATE_O:
1333
1334 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1335
1336 Key.ScanCode = SCAN_NULL;
1337
1338 if (TerminalDevice->TerminalType == VT100TYPE) {
1339 switch (UnicodeChar) {
1340 case 'P':
1341 Key.ScanCode = SCAN_F1;
1342 break;
1343 case 'Q':
1344 Key.ScanCode = SCAN_F2;
1345 break;
1346 case 'w':
1347 Key.ScanCode = SCAN_F3;
1348 break;
1349 case 'x':
1350 Key.ScanCode = SCAN_F4;
1351 break;
1352 case 't':
1353 Key.ScanCode = SCAN_F5;
1354 break;
1355 case 'u':
1356 Key.ScanCode = SCAN_F6;
1357 break;
1358 case 'q':
1359 Key.ScanCode = SCAN_F7;
1360 break;
1361 case 'r':
1362 Key.ScanCode = SCAN_F8;
1363 break;
1364 case 'p':
1365 Key.ScanCode = SCAN_F9;
1366 break;
1367 case 'M':
1368 Key.ScanCode = SCAN_F10;
1369 break;
1370 default :
1371 break;
1372 }
1373 }
1374
1375 if (Key.ScanCode != SCAN_NULL) {
1376 Key.UnicodeChar = 0;
1377 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1378 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1379 UnicodeToEfiKeyFlushState (TerminalDevice);
1380 continue;
1381 }
1382
1383 UnicodeToEfiKeyFlushState (TerminalDevice);
1384
1385 break;
1386
1387 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
1388
1389 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1390
1391 Key.ScanCode = SCAN_NULL;
1392
1393 if (TerminalDevice->TerminalType == PCANSITYPE ||
1394 TerminalDevice->TerminalType == VT100TYPE ||
1395 TerminalDevice->TerminalType == VT100PLUSTYPE ||
1396 TerminalDevice->TerminalType == VTUTF8TYPE) {
1397 switch (UnicodeChar) {
1398 case 'A':
1399 Key.ScanCode = SCAN_UP;
1400 break;
1401 case 'B':
1402 Key.ScanCode = SCAN_DOWN;
1403 break;
1404 case 'C':
1405 Key.ScanCode = SCAN_RIGHT;
1406 break;
1407 case 'D':
1408 Key.ScanCode = SCAN_LEFT;
1409 break;
1410 case 'H':
1411 if (TerminalDevice->TerminalType == PCANSITYPE ||
1412 TerminalDevice->TerminalType == VT100TYPE) {
1413 Key.ScanCode = SCAN_HOME;
1414 }
1415 break;
1416 case 'F':
1417 if (TerminalDevice->TerminalType == PCANSITYPE) {
1418 Key.ScanCode = SCAN_END;
1419 }
1420 break;
1421 case 'K':
1422 if (TerminalDevice->TerminalType == VT100TYPE) {
1423 Key.ScanCode = SCAN_END;
1424 }
1425 break;
1426 case 'L':
1427 case '@':
1428 if (TerminalDevice->TerminalType == PCANSITYPE ||
1429 TerminalDevice->TerminalType == VT100TYPE) {
1430 Key.ScanCode = SCAN_INSERT;
1431 }
1432 break;
1433 case 'X':
1434 if (TerminalDevice->TerminalType == PCANSITYPE) {
1435 Key.ScanCode = SCAN_DELETE;
1436 }
1437 break;
1438 case 'P':
1439 if (TerminalDevice->TerminalType == VT100TYPE) {
1440 Key.ScanCode = SCAN_DELETE;
1441 } else if (TerminalDevice->TerminalType == PCANSITYPE) {
1442 Key.ScanCode = SCAN_F4;
1443 }
1444 break;
1445 case 'I':
1446 if (TerminalDevice->TerminalType == PCANSITYPE) {
1447 Key.ScanCode = SCAN_PAGE_UP;
1448 }
1449 break;
1450 case 'V':
1451 if (TerminalDevice->TerminalType == PCANSITYPE) {
1452 Key.ScanCode = SCAN_F10;
1453 }
1454 break;
1455 case '?':
1456 if (TerminalDevice->TerminalType == VT100TYPE) {
1457 Key.ScanCode = SCAN_PAGE_UP;
1458 }
1459 break;
1460 case 'G':
1461 if (TerminalDevice->TerminalType == PCANSITYPE) {
1462 Key.ScanCode = SCAN_PAGE_DOWN;
1463 }
1464 break;
1465 case 'U':
1466 if (TerminalDevice->TerminalType == PCANSITYPE) {
1467 Key.ScanCode = SCAN_F9;
1468 }
1469 break;
1470 case '/':
1471 if (TerminalDevice->TerminalType == VT100TYPE) {
1472 Key.ScanCode = SCAN_PAGE_DOWN;
1473 }
1474 break;
1475 case 'M':
1476 if (TerminalDevice->TerminalType == PCANSITYPE) {
1477 Key.ScanCode = SCAN_F1;
1478 }
1479 break;
1480 case 'N':
1481 if (TerminalDevice->TerminalType == PCANSITYPE) {
1482 Key.ScanCode = SCAN_F2;
1483 }
1484 break;
1485 case 'O':
1486 if (TerminalDevice->TerminalType == PCANSITYPE) {
1487 Key.ScanCode = SCAN_F3;
1488 }
1489 break;
1490 case 'Q':
1491 if (TerminalDevice->TerminalType == PCANSITYPE) {
1492 Key.ScanCode = SCAN_F5;
1493 }
1494 break;
1495 case 'R':
1496 if (TerminalDevice->TerminalType == PCANSITYPE) {
1497 Key.ScanCode = SCAN_F6;
1498 }
1499 break;
1500 case 'S':
1501 if (TerminalDevice->TerminalType == PCANSITYPE) {
1502 Key.ScanCode = SCAN_F7;
1503 }
1504 break;
1505 case 'T':
1506 if (TerminalDevice->TerminalType == PCANSITYPE) {
1507 Key.ScanCode = SCAN_F8;
1508 }
1509 break;
1510 default :
1511 break;
1512 }
1513 }
1514
1515 if (Key.ScanCode != SCAN_NULL) {
1516 Key.UnicodeChar = 0;
1517 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1518 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1519 UnicodeToEfiKeyFlushState (TerminalDevice);
1520 continue;
1521 }
1522
1523 UnicodeToEfiKeyFlushState (TerminalDevice);
1524
1525 break;
1526
1527
1528 default:
1529 //
1530 // Invalid state. This should never happen.
1531 //
1532 ASSERT (FALSE);
1533
1534 UnicodeToEfiKeyFlushState (TerminalDevice);
1535
1536 break;
1537 }
1538
1539 if (UnicodeChar == ESC) {
1540 TerminalDevice->InputState = INPUT_STATE_ESC;
1541 }
1542
1543 if (UnicodeChar == CSI) {
1544 TerminalDevice->InputState = INPUT_STATE_CSI;
1545 }
1546
1547 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1548 Status = gBS->SetTimer(
1549 TerminalDevice->TwoSecondTimeOut,
1550 TimerRelative,
1551 (UINT64)20000000
1552 );
1553 ASSERT_EFI_ERROR (Status);
1554 continue;
1555 }
1556
1557 if (SetDefaultResetState) {
1558 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1559 }
1560
1561 if (UnicodeChar == DEL) {
1562 Key.ScanCode = SCAN_DELETE;
1563 Key.UnicodeChar = 0;
1564 } else {
1565 Key.ScanCode = SCAN_NULL;
1566 Key.UnicodeChar = UnicodeChar;
1567 }
1568
1569 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1570 }
1571 }