2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
15 Reads the next keystroke from the input device. The WaitForKey Event can
16 be used to test for existence of a keystroke via WaitForEvent () call.
18 @param TerminalDevice Terminal driver private structure
19 @param KeyData A pointer to a buffer that is filled in with the
20 keystroke state data for the key that was
23 @retval EFI_SUCCESS The keystroke information was returned.
24 @retval EFI_NOT_READY There was no keystroke data available.
25 @retval EFI_INVALID_PARAMETER KeyData is NULL.
30 IN TERMINAL_DEV
*TerminalDevice
,
31 OUT EFI_KEY_DATA
*KeyData
34 if (KeyData
== NULL
) {
35 return EFI_INVALID_PARAMETER
;
38 KeyData
->KeyState
.KeyShiftState
= 0;
39 KeyData
->KeyState
.KeyToggleState
= 0;
41 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
50 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
51 This driver only perform dependent serial device reset regardless of
52 the value of ExtendeVerification
54 @param This Indicates the calling context.
55 @param ExtendedVerification Skip by this driver.
57 @retval EFI_SUCCESS The reset operation succeeds.
58 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
64 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
65 IN BOOLEAN ExtendedVerification
69 TERMINAL_DEV
*TerminalDevice
;
71 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
74 // Report progress code here
76 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
78 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
79 TerminalDevice
->DevicePath
82 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
85 // Make all the internal buffer empty for keys
87 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
88 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
89 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
90 TerminalDevice
->EfiKeyFiFoForNotify
->Head
= TerminalDevice
->EfiKeyFiFoForNotify
->Tail
;
92 if (EFI_ERROR (Status
)) {
93 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
94 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
95 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
96 TerminalDevice
->DevicePath
104 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
106 @param This Indicates the calling context.
107 @param Key A pointer to a buffer that is filled in with the
108 keystroke information for the key that was sent
111 @retval EFI_SUCCESS The keystroke information is returned successfully.
112 @retval EFI_NOT_READY There is no keystroke data available.
113 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
118 TerminalConInReadKeyStroke (
119 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
120 OUT EFI_INPUT_KEY
*Key
123 TERMINAL_DEV
*TerminalDevice
;
125 EFI_KEY_DATA KeyData
;
128 // get TERMINAL_DEV from "This" parameter.
130 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
132 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
133 if (EFI_ERROR (Status
)) {
137 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
144 Check if the key already has been registered.
146 If both RegsiteredData and InputData is NULL, then ASSERT().
148 @param RegsiteredData A pointer to a buffer that is filled in with the
149 keystroke state data for the key that was
151 @param InputData A pointer to a buffer that is filled in with the
152 keystroke state data for the key that was
155 @retval TRUE Key be pressed matches a registered key.
156 @retval FALSE Match failed.
161 IN EFI_KEY_DATA
*RegsiteredData
,
162 IN EFI_KEY_DATA
*InputData
165 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
167 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
168 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
178 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
179 Signal the event if there is key available
181 @param Event Indicates the event that invoke this function.
182 @param Context Indicates the calling context.
187 TerminalConInWaitForKeyEx (
192 TerminalConInWaitForKey (Event
, Context
);
196 // Simple Text Input Ex protocol functions
200 Reset the input device and optionally run diagnostics
202 @param This Protocol instance pointer.
203 @param ExtendedVerification Driver may perform diagnostics on reset.
205 @retval EFI_SUCCESS The device was reset.
206 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
212 TerminalConInResetEx (
213 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
214 IN BOOLEAN ExtendedVerification
218 TERMINAL_DEV
*TerminalDevice
;
220 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
222 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
223 if (EFI_ERROR (Status
)) {
224 return EFI_DEVICE_ERROR
;
233 Reads the next keystroke from the input device. The WaitForKey Event can
234 be used to test for existence of a keystroke via WaitForEvent () call.
236 @param This Protocol instance pointer.
237 @param KeyData A pointer to a buffer that is filled in with the
238 keystroke state data for the key that was
241 @retval EFI_SUCCESS The keystroke information was returned.
242 @retval EFI_NOT_READY There was no keystroke data available.
243 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
245 @retval EFI_INVALID_PARAMETER KeyData is NULL.
250 TerminalConInReadKeyStrokeEx (
251 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
252 OUT EFI_KEY_DATA
*KeyData
255 TERMINAL_DEV
*TerminalDevice
;
257 if (KeyData
== NULL
) {
258 return EFI_INVALID_PARAMETER
;
261 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
263 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
269 Set certain state for the input device.
271 @param This Protocol instance pointer.
272 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
273 state for the input device.
275 @retval EFI_SUCCESS The device state was set successfully.
276 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
277 could not have the setting adjusted.
278 @retval EFI_UNSUPPORTED The device does not have the ability to set its
280 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
285 TerminalConInSetState (
286 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
287 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
290 if (KeyToggleState
== NULL
) {
291 return EFI_INVALID_PARAMETER
;
294 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
295 return EFI_UNSUPPORTED
;
303 Register a notification function for a particular keystroke for the input device.
305 @param This Protocol instance pointer.
306 @param KeyData A pointer to a buffer that is filled in with
307 the keystroke information for the key that was
308 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
309 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
310 keystroke will trigger a notification of the KeyNotificationFunction.
311 @param KeyNotificationFunction Points to the function to be called when the key
312 sequence is typed specified by KeyData. This notification function
313 should be called at <=TPL_CALLBACK.
314 @param NotifyHandle Points to the unique handle assigned to the
315 registered notification.
317 @retval EFI_SUCCESS The notification function was registered
319 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
321 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
326 TerminalConInRegisterKeyNotify (
327 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
328 IN EFI_KEY_DATA
*KeyData
,
329 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
330 OUT VOID
**NotifyHandle
333 TERMINAL_DEV
*TerminalDevice
;
334 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
336 LIST_ENTRY
*NotifyList
;
337 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
339 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
340 return EFI_INVALID_PARAMETER
;
343 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
346 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
348 NotifyList
= &TerminalDevice
->NotifyList
;
349 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
352 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
354 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
356 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
357 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
358 *NotifyHandle
= CurrentNotify
;
365 // Allocate resource to save the notification function
367 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
368 if (NewNotify
== NULL
) {
369 return EFI_OUT_OF_RESOURCES
;
372 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
373 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
374 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
375 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
377 *NotifyHandle
= NewNotify
;
384 Remove a registered notification function from a particular keystroke.
386 @param This Protocol instance pointer.
387 @param NotificationHandle The handle of the notification function being
390 @retval EFI_SUCCESS The notification function was unregistered
392 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
397 TerminalConInUnregisterKeyNotify (
398 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
399 IN VOID
*NotificationHandle
402 TERMINAL_DEV
*TerminalDevice
;
404 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
405 LIST_ENTRY
*NotifyList
;
407 if (NotificationHandle
== NULL
) {
408 return EFI_INVALID_PARAMETER
;
411 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
413 NotifyList
= &TerminalDevice
->NotifyList
;
414 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
417 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
419 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
421 if (CurrentNotify
== NotificationHandle
) {
423 // Remove the notification function from NotifyList and free resources
425 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
427 gBS
->FreePool (CurrentNotify
);
433 // Can not find the matching entry in database.
435 return EFI_INVALID_PARAMETER
;
439 Translate raw data into Unicode (according to different encode), and
440 translate Unicode into key information. (according to different standard).
442 @param TerminalDevice Terminal driver private structure.
446 TranslateRawDataToEfiKey (
447 IN TERMINAL_DEV
*TerminalDevice
450 switch (TerminalDevice
->TerminalType
) {
452 case TerminalTypePcAnsi
:
453 case TerminalTypeVt100
:
454 case TerminalTypeVt100Plus
:
455 case TerminalTypeTtyTerm
:
456 AnsiRawDataToUnicode (TerminalDevice
);
457 UnicodeToEfiKey (TerminalDevice
);
460 case TerminalTypeVtUtf8
:
462 // Process all the raw data in the RawFIFO,
463 // put the processed key into UnicodeFIFO.
465 VTUTF8RawDataToUnicode (TerminalDevice
);
468 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
469 // then put into EfiKeyFIFO.
471 UnicodeToEfiKey (TerminalDevice
);
478 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
479 Signal the event if there is key available
481 @param Event Indicates the event that invoke this function.
482 @param Context Indicates the calling context.
487 TerminalConInWaitForKey (
493 // Someone is waiting on the keystroke event, if there's
494 // a key pending, signal the event
496 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
498 gBS
->SignalEvent (Event
);
503 Timer handler to poll the key from serial.
505 @param Event Indicates the event that invoke this function.
506 @param Context Indicates the calling context.
510 TerminalConInTimerHandler (
516 TERMINAL_DEV
*TerminalDevice
;
519 EFI_SERIAL_IO_MODE
*Mode
;
520 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
521 UINTN SerialInTimeOut
;
523 TerminalDevice
= (TERMINAL_DEV
*) Context
;
525 SerialIo
= TerminalDevice
->SerialIo
;
526 if (SerialIo
== NULL
) {
530 // if current timeout value for serial device is not identical with
531 // the value saved in TERMINAL_DEV structure, then recalculate the
532 // timeout value again and set serial attribute according to this value.
534 Mode
= SerialIo
->Mode
;
535 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
538 if (Mode
->BaudRate
!= 0) {
540 // According to BAUD rate to calculate the timeout value.
542 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
545 Status
= SerialIo
->SetAttributes (
548 Mode
->ReceiveFifoDepth
,
549 (UINT32
) SerialInTimeOut
,
550 (EFI_PARITY_TYPE
) (Mode
->Parity
),
551 (UINT8
) Mode
->DataBits
,
552 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
555 if (EFI_ERROR (Status
)) {
556 TerminalDevice
->SerialInTimeOut
= 0;
558 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
562 // Check whether serial buffer is empty.
563 // Skip the key transfer loop only if the SerialIo protocol instance
564 // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
566 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
567 if (EFI_ERROR (Status
) || ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0)) {
569 // Fetch all the keys in the serial buffer,
570 // and insert the byte stream into RawFIFO.
572 while (!IsRawFiFoFull (TerminalDevice
)) {
574 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
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
587 RawFiFoInsertOneKey (TerminalDevice
, Input
);
592 // Translate all the raw data in RawFIFO into EFI Key,
593 // according to different terminal type supported.
595 TranslateRawDataToEfiKey (TerminalDevice
);
601 @param Event Indicates the event that invoke this function.
602 @param Context Indicates the calling context.
606 KeyNotifyProcessHandler (
612 TERMINAL_DEV
*TerminalDevice
;
614 EFI_KEY_DATA KeyData
;
616 LIST_ENTRY
*NotifyList
;
617 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
620 TerminalDevice
= (TERMINAL_DEV
*) Context
;
623 // Invoke notification functions.
625 NotifyList
= &TerminalDevice
->NotifyList
;
628 // Enter critical section
630 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
631 HasKey
= EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, &Key
);
632 CopyMem (&KeyData
.Key
, &Key
, sizeof (EFI_INPUT_KEY
));
633 KeyData
.KeyState
.KeyShiftState
= 0;
634 KeyData
.KeyState
.KeyToggleState
= 0;
636 // Leave critical section
638 gBS
->RestoreTPL (OldTpl
);
642 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
643 CurrentNotify
= CR (Link
, TERMINAL_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
644 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
645 CurrentNotify
->KeyNotificationFn (&KeyData
);
652 Get one key out of serial buffer.
654 @param SerialIo Serial I/O protocol attached to the serial device.
655 @param Output The fetched key.
657 @retval EFI_NOT_READY If serial buffer is empty.
658 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
659 @retval EFI_SUCCESS If reading serial buffer successfully, put
660 the fetched key to the parameter output.
664 GetOneKeyFromSerial (
665 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
676 // Read one key from serial I/O device.
678 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
680 if (EFI_ERROR (Status
)) {
682 if (Status
== EFI_TIMEOUT
) {
683 return EFI_NOT_READY
;
686 return EFI_DEVICE_ERROR
;
691 return EFI_NOT_READY
;
698 Insert one byte raw data into the Raw Data FIFO.
700 @param TerminalDevice Terminal driver private structure.
701 @param Input The key will be input.
703 @retval TRUE If insert successfully.
704 @retval FALSE If Raw Data buffer is full before key insertion,
709 RawFiFoInsertOneKey (
710 TERMINAL_DEV
*TerminalDevice
,
716 Tail
= TerminalDevice
->RawFiFo
->Tail
;
718 if (IsRawFiFoFull (TerminalDevice
)) {
725 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
727 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
733 Remove one pre-fetched key out of the Raw Data FIFO.
735 @param TerminalDevice Terminal driver private structure.
736 @param Output The key will be removed.
738 @retval TRUE If insert successfully.
739 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
743 RawFiFoRemoveOneKey (
744 TERMINAL_DEV
*TerminalDevice
,
750 Head
= TerminalDevice
->RawFiFo
->Head
;
752 if (IsRawFiFoEmpty (TerminalDevice
)) {
760 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
762 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
768 Clarify whether Raw Data FIFO buffer is empty.
770 @param TerminalDevice Terminal driver private structure
772 @retval TRUE If Raw Data FIFO buffer is empty.
773 @retval FALSE If Raw Data FIFO buffer is not empty.
778 TERMINAL_DEV
*TerminalDevice
781 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
789 Clarify whether Raw Data FIFO buffer is full.
791 @param TerminalDevice Terminal driver private structure
793 @retval TRUE If Raw Data FIFO buffer is full.
794 @retval FALSE If Raw Data FIFO buffer is not full.
799 TERMINAL_DEV
*TerminalDevice
805 Tail
= TerminalDevice
->RawFiFo
->Tail
;
806 Head
= TerminalDevice
->RawFiFo
->Head
;
808 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
817 Insert one pre-fetched key into the FIFO buffer.
819 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
820 @param Input The key will be input.
822 @retval TRUE If insert successfully.
823 @retval FALSE If FIFO buffer is full before key insertion,
828 EfiKeyFiFoForNotifyInsertOneKey (
829 EFI_KEY_FIFO
*EfiKeyFiFo
,
835 Tail
= EfiKeyFiFo
->Tail
;
837 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo
)) {
844 CopyMem (&EfiKeyFiFo
->Data
[Tail
], Input
, sizeof (EFI_INPUT_KEY
));
846 EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
852 Remove one pre-fetched key out of the FIFO buffer.
854 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
855 @param Output The key will be removed.
857 @retval TRUE If remove successfully.
858 @retval FALSE If FIFO buffer is empty before remove operation.
862 EfiKeyFiFoForNotifyRemoveOneKey (
863 EFI_KEY_FIFO
*EfiKeyFiFo
,
864 EFI_INPUT_KEY
*Output
869 Head
= EfiKeyFiFo
->Head
;
870 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
872 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo
)) {
876 Output
->ScanCode
= SCAN_NULL
;
877 Output
->UnicodeChar
= 0;
881 CopyMem (Output
, &EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
883 EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
889 Clarify whether FIFO buffer is empty.
891 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
893 @retval TRUE If FIFO buffer is empty.
894 @retval FALSE If FIFO buffer is not empty.
898 IsEfiKeyFiFoForNotifyEmpty (
899 EFI_KEY_FIFO
*EfiKeyFiFo
902 if (EfiKeyFiFo
->Head
== EfiKeyFiFo
->Tail
) {
910 Clarify whether FIFO buffer is full.
912 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
914 @retval TRUE If FIFO buffer is full.
915 @retval FALSE If FIFO buffer is not full.
919 IsEfiKeyFiFoForNotifyFull (
920 EFI_KEY_FIFO
*EfiKeyFiFo
926 Tail
= EfiKeyFiFo
->Tail
;
927 Head
= EfiKeyFiFo
->Head
;
929 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
937 Insert one pre-fetched key into the FIFO buffer.
939 @param TerminalDevice Terminal driver private structure.
940 @param Key The key will be input.
942 @retval TRUE If insert successfully.
943 @retval FALSE If FIFO buffer is full before key insertion,
948 EfiKeyFiFoInsertOneKey (
949 TERMINAL_DEV
*TerminalDevice
,
955 LIST_ENTRY
*NotifyList
;
956 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
957 EFI_KEY_DATA KeyData
;
959 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
961 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
962 KeyData
.KeyState
.KeyShiftState
= 0;
963 KeyData
.KeyState
.KeyToggleState
= 0;
966 // Signal KeyNotify process event if this key pressed matches any key registered.
968 NotifyList
= &TerminalDevice
->NotifyList
;
969 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
972 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
974 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
976 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
978 // The key notification function needs to run at TPL_CALLBACK
979 // while current TPL is TPL_NOTIFY. It will be invoked in
980 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
982 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, Key
);
983 gBS
->SignalEvent (TerminalDevice
->KeyNotifyProcessEvent
);
987 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
989 // Efi Key FIFO is full
994 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
996 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1002 Remove one pre-fetched key out of the FIFO buffer.
1004 @param TerminalDevice Terminal driver private structure.
1005 @param Output The key will be removed.
1007 @retval TRUE If insert successfully.
1008 @retval FALSE If FIFO buffer is empty before remove operation.
1012 EfiKeyFiFoRemoveOneKey (
1013 TERMINAL_DEV
*TerminalDevice
,
1014 EFI_INPUT_KEY
*Output
1019 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1020 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1022 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
1026 Output
->ScanCode
= SCAN_NULL
;
1027 Output
->UnicodeChar
= 0;
1031 CopyMem (Output
, &TerminalDevice
->EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
1033 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1039 Clarify whether FIFO buffer is empty.
1041 @param TerminalDevice Terminal driver private structure
1043 @retval TRUE If FIFO buffer is empty.
1044 @retval FALSE If FIFO buffer is not empty.
1049 TERMINAL_DEV
*TerminalDevice
1052 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
1060 Clarify whether FIFO buffer is full.
1062 @param TerminalDevice Terminal driver private structure
1064 @retval TRUE If FIFO buffer is full.
1065 @retval FALSE If FIFO buffer is not full.
1070 TERMINAL_DEV
*TerminalDevice
1076 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
1077 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1079 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1088 Insert one pre-fetched key into the Unicode FIFO buffer.
1090 @param TerminalDevice Terminal driver private structure.
1091 @param Input The key will be input.
1093 @retval TRUE If insert successfully.
1094 @retval FALSE If Unicode FIFO buffer is full before key insertion,
1095 and the key is lost.
1099 UnicodeFiFoInsertOneKey (
1100 TERMINAL_DEV
*TerminalDevice
,
1106 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1107 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
1110 if (IsUnicodeFiFoFull (TerminalDevice
)) {
1112 // Unicode FIFO is full
1117 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1119 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1125 Remove one pre-fetched key out of the Unicode FIFO buffer.
1126 The caller should guarantee that Unicode FIFO buffer is not empty
1127 by IsUnicodeFiFoEmpty ().
1129 @param TerminalDevice Terminal driver private structure.
1130 @param Output The key will be removed.
1134 UnicodeFiFoRemoveOneKey (
1135 TERMINAL_DEV
*TerminalDevice
,
1141 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1142 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1144 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1146 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1150 Clarify whether Unicode FIFO buffer is empty.
1152 @param TerminalDevice Terminal driver private structure
1154 @retval TRUE If Unicode FIFO buffer is empty.
1155 @retval FALSE If Unicode FIFO buffer is not empty.
1159 IsUnicodeFiFoEmpty (
1160 TERMINAL_DEV
*TerminalDevice
1163 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1171 Clarify whether Unicode FIFO buffer is full.
1173 @param TerminalDevice Terminal driver private structure
1175 @retval TRUE If Unicode FIFO buffer is full.
1176 @retval FALSE If Unicode FIFO buffer is not full.
1181 TERMINAL_DEV
*TerminalDevice
1187 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1188 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1190 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1200 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1202 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1206 UnicodeToEfiKeyFlushState (
1207 IN TERMINAL_DEV
*TerminalDevice
1213 InputState
= TerminalDevice
->InputState
;
1215 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1219 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1220 Key
.ScanCode
= SCAN_ESC
;
1221 Key
.UnicodeChar
= 0;
1222 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1225 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1226 Key
.ScanCode
= SCAN_NULL
;
1227 Key
.UnicodeChar
= CSI
;
1228 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1231 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1232 Key
.ScanCode
= SCAN_NULL
;
1233 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1234 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1237 if ((InputState
& INPUT_STATE_O
) != 0) {
1238 Key
.ScanCode
= SCAN_NULL
;
1239 Key
.UnicodeChar
= 'O';
1240 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1243 if ((InputState
& INPUT_STATE_2
) != 0) {
1244 Key
.ScanCode
= SCAN_NULL
;
1245 Key
.UnicodeChar
= '2';
1246 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1250 // Cancel the timer.
1253 TerminalDevice
->TwoSecondTimeOut
,
1258 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1263 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1264 can be read through the Simple Input Protocol.
1266 The table below shows the keyboard input mappings that this function supports.
1267 If the ESC sequence listed in one of the columns is presented, then it is translated
1268 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1269 key strokes are converted into EFI Keys.
1271 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1272 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1273 converted into EFI Keys.
1274 There is one special input sequence that will force the system to reset.
1275 This is ESC R ESC r ESC R.
1277 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1278 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1279 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1281 Symbols used in table below
1282 ===========================
1288 +=========+======+===========+==========+==========+
1289 | | EFI | UEFI 2.0 | | |
1290 | | Scan | | VT100+ | |
1291 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1292 +=========+======+===========+==========+==========+
1293 | NULL | 0x00 | | | |
1294 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1295 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1296 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1297 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1298 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1299 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1300 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1301 | | | ESC [ L | | ESC [ L |
1302 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1303 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1305 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1307 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1308 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1309 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1310 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1311 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1312 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1313 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1314 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1315 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1316 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1317 | Escape | 0x17 | ESC | ESC | ESC |
1318 | F11 | 0x15 | | ESC ! | |
1319 | F12 | 0x16 | | ESC @ | |
1320 +=========+======+===========+==========+==========+
1324 ESC R ESC r ESC R = Reset System
1326 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1331 IN TERMINAL_DEV
*TerminalDevice
1335 EFI_STATUS TimerStatus
;
1338 BOOLEAN SetDefaultResetState
;
1340 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1342 if (!EFI_ERROR (TimerStatus
)) {
1343 UnicodeToEfiKeyFlushState (TerminalDevice
);
1344 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1347 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1349 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1351 // Check to see if the 2 seconds timer has expired
1353 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1354 if (!EFI_ERROR (TimerStatus
)) {
1355 UnicodeToEfiKeyFlushState (TerminalDevice
);
1356 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1361 // Fetch one Unicode character from the Unicode FIFO
1363 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1365 SetDefaultResetState
= TRUE
;
1367 switch (TerminalDevice
->InputState
) {
1368 case INPUT_STATE_DEFAULT
:
1372 case INPUT_STATE_ESC
:
1374 if (UnicodeChar
== LEFTOPENBRACKET
) {
1375 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1376 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1380 if (UnicodeChar
== 'O' && (TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1381 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
)) {
1382 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1383 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1387 Key
.ScanCode
= SCAN_NULL
;
1389 if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1390 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
) {
1391 switch (UnicodeChar
) {
1393 Key
.ScanCode
= SCAN_F1
;
1396 Key
.ScanCode
= SCAN_F2
;
1399 Key
.ScanCode
= SCAN_F3
;
1402 Key
.ScanCode
= SCAN_F4
;
1405 Key
.ScanCode
= SCAN_F5
;
1408 Key
.ScanCode
= SCAN_F6
;
1411 Key
.ScanCode
= SCAN_F7
;
1414 Key
.ScanCode
= SCAN_F8
;
1417 Key
.ScanCode
= SCAN_F9
;
1420 Key
.ScanCode
= SCAN_F10
;
1423 Key
.ScanCode
= SCAN_F11
;
1426 Key
.ScanCode
= SCAN_F12
;
1429 Key
.ScanCode
= SCAN_HOME
;
1432 Key
.ScanCode
= SCAN_END
;
1435 Key
.ScanCode
= SCAN_INSERT
;
1438 Key
.ScanCode
= SCAN_DELETE
;
1441 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1444 Key
.ScanCode
= SCAN_PAGE_UP
;
1451 switch (UnicodeChar
) {
1453 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1454 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1455 SetDefaultResetState
= FALSE
;
1456 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1457 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1459 Key
.ScanCode
= SCAN_NULL
;
1462 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1463 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1464 SetDefaultResetState
= FALSE
;
1466 Key
.ScanCode
= SCAN_NULL
;
1472 if (SetDefaultResetState
) {
1473 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1476 if (Key
.ScanCode
!= SCAN_NULL
) {
1477 Key
.UnicodeChar
= 0;
1478 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1479 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1480 UnicodeToEfiKeyFlushState (TerminalDevice
);
1484 UnicodeToEfiKeyFlushState (TerminalDevice
);
1488 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1490 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1492 Key
.ScanCode
= SCAN_NULL
;
1494 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1495 switch (UnicodeChar
) {
1497 Key
.ScanCode
= SCAN_F1
;
1500 Key
.ScanCode
= SCAN_F2
;
1503 Key
.ScanCode
= SCAN_F3
;
1506 Key
.ScanCode
= SCAN_F4
;
1509 Key
.ScanCode
= SCAN_F5
;
1512 Key
.ScanCode
= SCAN_F6
;
1515 Key
.ScanCode
= SCAN_F7
;
1518 Key
.ScanCode
= SCAN_F8
;
1521 Key
.ScanCode
= SCAN_F9
;
1524 Key
.ScanCode
= SCAN_F10
;
1529 } else if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1530 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1531 switch (UnicodeChar
) {
1533 Key
.ScanCode
= SCAN_F1
;
1536 Key
.ScanCode
= SCAN_F2
;
1539 Key
.ScanCode
= SCAN_F3
;
1542 Key
.ScanCode
= SCAN_F4
;
1545 Key
.ScanCode
= SCAN_HOME
;
1548 Key
.ScanCode
= SCAN_END
;
1553 if (Key
.ScanCode
!= SCAN_NULL
) {
1554 Key
.UnicodeChar
= 0;
1555 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1556 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1557 UnicodeToEfiKeyFlushState (TerminalDevice
);
1561 UnicodeToEfiKeyFlushState (TerminalDevice
);
1565 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1567 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1569 Key
.ScanCode
= SCAN_NULL
;
1571 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1572 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1573 TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1574 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
||
1575 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1576 switch (UnicodeChar
) {
1578 Key
.ScanCode
= SCAN_UP
;
1581 Key
.ScanCode
= SCAN_DOWN
;
1584 Key
.ScanCode
= SCAN_RIGHT
;
1587 Key
.ScanCode
= SCAN_LEFT
;
1590 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1591 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1592 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1593 Key
.ScanCode
= SCAN_HOME
;
1597 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1598 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1599 Key
.ScanCode
= SCAN_END
;
1603 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1604 Key
.ScanCode
= SCAN_END
;
1609 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1610 TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1611 Key
.ScanCode
= SCAN_INSERT
;
1615 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1616 Key
.ScanCode
= SCAN_DELETE
;
1620 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1621 Key
.ScanCode
= SCAN_DELETE
;
1622 } else if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1623 Key
.ScanCode
= SCAN_F4
;
1627 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1628 Key
.ScanCode
= SCAN_PAGE_UP
;
1632 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1633 Key
.ScanCode
= SCAN_F10
;
1637 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1638 Key
.ScanCode
= SCAN_PAGE_UP
;
1642 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1643 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1647 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1648 Key
.ScanCode
= SCAN_F9
;
1652 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1653 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1657 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1658 Key
.ScanCode
= SCAN_F1
;
1662 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1663 Key
.ScanCode
= SCAN_F2
;
1667 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1668 Key
.ScanCode
= SCAN_F3
;
1672 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1673 Key
.ScanCode
= SCAN_F5
;
1677 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1678 Key
.ScanCode
= SCAN_F6
;
1682 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1683 Key
.ScanCode
= SCAN_F7
;
1687 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1688 Key
.ScanCode
= SCAN_F8
;
1697 * The VT220 escape codes that the TTY terminal accepts all have
1698 * numeric codes, and there are no ambiguous prefixes shared with
1699 * other terminal types.
1701 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
&&
1702 Key
.ScanCode
== SCAN_NULL
&&
1703 UnicodeChar
>= '0' &&
1704 UnicodeChar
<= '9') {
1705 TerminalDevice
->TtyEscapeStr
[0] = UnicodeChar
;
1706 TerminalDevice
->TtyEscapeIndex
= 1;
1707 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_2
;
1711 if (Key
.ScanCode
!= SCAN_NULL
) {
1712 Key
.UnicodeChar
= 0;
1713 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1714 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1715 UnicodeToEfiKeyFlushState (TerminalDevice
);
1719 UnicodeToEfiKeyFlushState (TerminalDevice
);
1724 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_2
:
1726 * Here we handle the VT220 escape codes that we accept. This
1727 * state is only used by the TTY terminal type.
1729 Key
.ScanCode
= SCAN_NULL
;
1730 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1732 if (UnicodeChar
== '~' && TerminalDevice
->TtyEscapeIndex
<= 2) {
1734 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
] = 0; /* Terminate string */
1735 EscCode
= (UINT16
) StrDecimalToUintn(TerminalDevice
->TtyEscapeStr
);
1738 Key
.ScanCode
= SCAN_INSERT
;
1741 Key
.ScanCode
= SCAN_DELETE
;
1744 Key
.ScanCode
= SCAN_PAGE_UP
;
1747 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1754 Key
.ScanCode
= SCAN_F1
+ EscCode
- 11;
1761 Key
.ScanCode
= SCAN_F6
+ EscCode
- 17;
1765 Key
.ScanCode
= SCAN_F11
+ EscCode
- 23;
1770 } else if (TerminalDevice
->TtyEscapeIndex
== 1){
1771 /* 2 character escape code */
1772 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
++] = UnicodeChar
;
1776 DEBUG ((EFI_D_ERROR
, "Unexpected state in escape2\n"));
1779 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1781 if (Key
.ScanCode
!= SCAN_NULL
) {
1782 Key
.UnicodeChar
= 0;
1783 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1784 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1785 UnicodeToEfiKeyFlushState (TerminalDevice
);
1789 UnicodeToEfiKeyFlushState (TerminalDevice
);
1794 // Invalid state. This should never happen.
1798 UnicodeToEfiKeyFlushState (TerminalDevice
);
1803 if (UnicodeChar
== ESC
) {
1804 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1807 if (UnicodeChar
== CSI
) {
1808 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1811 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1812 Status
= gBS
->SetTimer(
1813 TerminalDevice
->TwoSecondTimeOut
,
1817 ASSERT_EFI_ERROR (Status
);
1821 if (SetDefaultResetState
) {
1822 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1825 if (UnicodeChar
== DEL
) {
1826 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1827 Key
.ScanCode
= SCAN_NULL
;
1828 Key
.UnicodeChar
= CHAR_BACKSPACE
;
1831 Key
.ScanCode
= SCAN_DELETE
;
1832 Key
.UnicodeChar
= 0;
1835 Key
.ScanCode
= SCAN_NULL
;
1836 Key
.UnicodeChar
= UnicodeChar
;
1839 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);