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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 Reads the next keystroke from the input device. The WaitForKey Event can
22 be used to test for existence of a keystroke via WaitForEvent () call.
24 @param TerminalDevice Terminal driver private structure
25 @param KeyData A pointer to a buffer that is filled in with the
26 keystroke state data for the key that was
29 @retval EFI_SUCCESS The keystroke information was returned.
30 @retval EFI_NOT_READY There was no keystroke data available.
31 @retval EFI_INVALID_PARAMETER KeyData is NULL.
36 IN TERMINAL_DEV
*TerminalDevice
,
37 OUT EFI_KEY_DATA
*KeyData
40 if (KeyData
== NULL
) {
41 return EFI_INVALID_PARAMETER
;
44 KeyData
->KeyState
.KeyShiftState
= 0;
45 KeyData
->KeyState
.KeyToggleState
= 0;
47 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
56 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
57 This driver only perform dependent serial device reset regardless of
58 the value of ExtendeVerification
60 @param This Indicates the calling context.
61 @param ExtendedVerification Skip by this driver.
63 @retval EFI_SUCCESS The reset operation succeeds.
64 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
70 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
71 IN BOOLEAN ExtendedVerification
75 TERMINAL_DEV
*TerminalDevice
;
77 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
80 // Report progress code here
82 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
84 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
85 TerminalDevice
->DevicePath
88 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
91 // Make all the internal buffer empty for keys
93 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
94 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
95 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
96 TerminalDevice
->EfiKeyFiFoForNotify
->Head
= TerminalDevice
->EfiKeyFiFoForNotify
->Tail
;
98 if (EFI_ERROR (Status
)) {
99 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
100 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
101 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
102 TerminalDevice
->DevicePath
110 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
112 @param This Indicates the calling context.
113 @param Key A pointer to a buffer that is filled in with the
114 keystroke information for the key that was sent
117 @retval EFI_SUCCESS The keystroke information is returned successfully.
118 @retval EFI_NOT_READY There is no keystroke data available.
119 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
124 TerminalConInReadKeyStroke (
125 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
126 OUT EFI_INPUT_KEY
*Key
129 TERMINAL_DEV
*TerminalDevice
;
131 EFI_KEY_DATA KeyData
;
134 // get TERMINAL_DEV from "This" parameter.
136 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
138 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
139 if (EFI_ERROR (Status
)) {
143 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
150 Check if the key already has been registered.
152 If both RegsiteredData and InputData is NULL, then ASSERT().
154 @param RegsiteredData A pointer to a buffer that is filled in with the
155 keystroke state data for the key that was
157 @param InputData A pointer to a buffer that is filled in with the
158 keystroke state data for the key that was
161 @retval TRUE Key be pressed matches a registered key.
162 @retval FALSE Match failed.
167 IN EFI_KEY_DATA
*RegsiteredData
,
168 IN EFI_KEY_DATA
*InputData
171 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
173 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
174 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
184 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
185 Signal the event if there is key available
187 @param Event Indicates the event that invoke this function.
188 @param Context Indicates the calling context.
193 TerminalConInWaitForKeyEx (
198 TerminalConInWaitForKey (Event
, Context
);
202 // Simple Text Input Ex protocol functions
206 Reset the input device and optionally run diagnostics
208 @param This Protocol instance pointer.
209 @param ExtendedVerification Driver may perform diagnostics on reset.
211 @retval EFI_SUCCESS The device was reset.
212 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
218 TerminalConInResetEx (
219 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
220 IN BOOLEAN ExtendedVerification
224 TERMINAL_DEV
*TerminalDevice
;
226 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
228 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
229 if (EFI_ERROR (Status
)) {
230 return EFI_DEVICE_ERROR
;
239 Reads the next keystroke from the input device. The WaitForKey Event can
240 be used to test for existence of a keystroke via WaitForEvent () call.
242 @param This Protocol instance pointer.
243 @param KeyData A pointer to a buffer that is filled in with the
244 keystroke state data for the key that was
247 @retval EFI_SUCCESS The keystroke information was returned.
248 @retval EFI_NOT_READY There was no keystroke data available.
249 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
251 @retval EFI_INVALID_PARAMETER KeyData is NULL.
256 TerminalConInReadKeyStrokeEx (
257 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
258 OUT EFI_KEY_DATA
*KeyData
261 TERMINAL_DEV
*TerminalDevice
;
263 if (KeyData
== NULL
) {
264 return EFI_INVALID_PARAMETER
;
267 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
269 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
275 Set certain state for the input device.
277 @param This Protocol instance pointer.
278 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
279 state for the input device.
281 @retval EFI_SUCCESS The device state was set successfully.
282 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
283 could not have the setting adjusted.
284 @retval EFI_UNSUPPORTED The device does not have the ability to set its
286 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
291 TerminalConInSetState (
292 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
293 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
296 if (KeyToggleState
== NULL
) {
297 return EFI_INVALID_PARAMETER
;
300 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
301 return EFI_UNSUPPORTED
;
309 Register a notification function for a particular keystroke for the input device.
311 @param This Protocol instance pointer.
312 @param KeyData A pointer to a buffer that is filled in with
313 the keystroke information for the key that was
314 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
315 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
316 keystroke will trigger a notification of the KeyNotificationFunction.
317 @param KeyNotificationFunction Points to the function to be called when the key
318 sequence is typed specified by KeyData. This notification function
319 should be called at <=TPL_CALLBACK.
320 @param NotifyHandle Points to the unique handle assigned to the
321 registered notification.
323 @retval EFI_SUCCESS The notification function was registered
325 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
327 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
332 TerminalConInRegisterKeyNotify (
333 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
334 IN EFI_KEY_DATA
*KeyData
,
335 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
336 OUT VOID
**NotifyHandle
339 TERMINAL_DEV
*TerminalDevice
;
340 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
342 LIST_ENTRY
*NotifyList
;
343 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
345 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
346 return EFI_INVALID_PARAMETER
;
349 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
352 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
354 NotifyList
= &TerminalDevice
->NotifyList
;
355 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
358 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
360 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
362 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
363 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
364 *NotifyHandle
= CurrentNotify
;
371 // Allocate resource to save the notification function
373 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
374 if (NewNotify
== NULL
) {
375 return EFI_OUT_OF_RESOURCES
;
378 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
379 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
380 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
381 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
383 *NotifyHandle
= NewNotify
;
390 Remove a registered notification function from a particular keystroke.
392 @param This Protocol instance pointer.
393 @param NotificationHandle The handle of the notification function being
396 @retval EFI_SUCCESS The notification function was unregistered
398 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
403 TerminalConInUnregisterKeyNotify (
404 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
405 IN VOID
*NotificationHandle
408 TERMINAL_DEV
*TerminalDevice
;
410 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
411 LIST_ENTRY
*NotifyList
;
413 if (NotificationHandle
== NULL
) {
414 return EFI_INVALID_PARAMETER
;
417 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
419 NotifyList
= &TerminalDevice
->NotifyList
;
420 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
423 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
425 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
427 if (CurrentNotify
== NotificationHandle
) {
429 // Remove the notification function from NotifyList and free resources
431 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
433 gBS
->FreePool (CurrentNotify
);
439 // Can not find the matching entry in database.
441 return EFI_INVALID_PARAMETER
;
445 Translate raw data into Unicode (according to different encode), and
446 translate Unicode into key information. (according to different standard).
448 @param TerminalDevice Terminal driver private structure.
452 TranslateRawDataToEfiKey (
453 IN TERMINAL_DEV
*TerminalDevice
456 switch (TerminalDevice
->TerminalType
) {
458 case TerminalTypePcAnsi
:
459 case TerminalTypeVt100
:
460 case TerminalTypeVt100Plus
:
461 case TerminalTypeTtyTerm
:
462 AnsiRawDataToUnicode (TerminalDevice
);
463 UnicodeToEfiKey (TerminalDevice
);
466 case TerminalTypeVtUtf8
:
468 // Process all the raw data in the RawFIFO,
469 // put the processed key into UnicodeFIFO.
471 VTUTF8RawDataToUnicode (TerminalDevice
);
474 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
475 // then put into EfiKeyFIFO.
477 UnicodeToEfiKey (TerminalDevice
);
484 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
485 Signal the event if there is key available
487 @param Event Indicates the event that invoke this function.
488 @param Context Indicates the calling context.
493 TerminalConInWaitForKey (
499 // Someone is waiting on the keystroke event, if there's
500 // a key pending, signal the event
502 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
504 gBS
->SignalEvent (Event
);
509 Timer handler to poll the key from serial.
511 @param Event Indicates the event that invoke this function.
512 @param Context Indicates the calling context.
516 TerminalConInTimerHandler (
522 TERMINAL_DEV
*TerminalDevice
;
525 EFI_SERIAL_IO_MODE
*Mode
;
526 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
527 UINTN SerialInTimeOut
;
529 TerminalDevice
= (TERMINAL_DEV
*) Context
;
531 SerialIo
= TerminalDevice
->SerialIo
;
532 if (SerialIo
== NULL
) {
536 // if current timeout value for serial device is not identical with
537 // the value saved in TERMINAL_DEV structure, then recalculate the
538 // timeout value again and set serial attribute according to this value.
540 Mode
= SerialIo
->Mode
;
541 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
544 if (Mode
->BaudRate
!= 0) {
546 // According to BAUD rate to calculate the timeout value.
548 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
551 Status
= SerialIo
->SetAttributes (
554 Mode
->ReceiveFifoDepth
,
555 (UINT32
) SerialInTimeOut
,
556 (EFI_PARITY_TYPE
) (Mode
->Parity
),
557 (UINT8
) Mode
->DataBits
,
558 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
561 if (EFI_ERROR (Status
)) {
562 TerminalDevice
->SerialInTimeOut
= 0;
564 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
568 // Check whether serial buffer is empty.
569 // Skip the key transfer loop only if the SerialIo protocol instance
570 // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
572 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
573 if (EFI_ERROR (Status
) || ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0)) {
575 // Fetch all the keys in the serial buffer,
576 // and insert the byte stream into RawFIFO.
578 while (!IsRawFiFoFull (TerminalDevice
)) {
580 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
582 if (EFI_ERROR (Status
)) {
583 if (Status
== EFI_DEVICE_ERROR
) {
584 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
585 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
586 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
587 TerminalDevice
->DevicePath
593 RawFiFoInsertOneKey (TerminalDevice
, Input
);
598 // Translate all the raw data in RawFIFO into EFI Key,
599 // according to different terminal type supported.
601 TranslateRawDataToEfiKey (TerminalDevice
);
607 @param Event Indicates the event that invoke this function.
608 @param Context Indicates the calling context.
612 KeyNotifyProcessHandler (
618 TERMINAL_DEV
*TerminalDevice
;
620 EFI_KEY_DATA KeyData
;
622 LIST_ENTRY
*NotifyList
;
623 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
626 TerminalDevice
= (TERMINAL_DEV
*) Context
;
629 // Invoke notification functions.
631 NotifyList
= &TerminalDevice
->NotifyList
;
634 // Enter critical section
636 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
637 HasKey
= EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, &Key
);
638 CopyMem (&KeyData
.Key
, &Key
, sizeof (EFI_INPUT_KEY
));
639 KeyData
.KeyState
.KeyShiftState
= 0;
640 KeyData
.KeyState
.KeyToggleState
= 0;
642 // Leave critical section
644 gBS
->RestoreTPL (OldTpl
);
648 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
649 CurrentNotify
= CR (Link
, TERMINAL_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
650 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
651 CurrentNotify
->KeyNotificationFn (&KeyData
);
658 Get one key out of serial buffer.
660 @param SerialIo Serial I/O protocol attached to the serial device.
661 @param Output The fetched key.
663 @retval EFI_NOT_READY If serial buffer is empty.
664 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
665 @retval EFI_SUCCESS If reading serial buffer successfully, put
666 the fetched key to the parameter output.
670 GetOneKeyFromSerial (
671 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
682 // Read one key from serial I/O device.
684 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
686 if (EFI_ERROR (Status
)) {
688 if (Status
== EFI_TIMEOUT
) {
689 return EFI_NOT_READY
;
692 return EFI_DEVICE_ERROR
;
697 return EFI_NOT_READY
;
704 Insert one byte raw data into the Raw Data FIFO.
706 @param TerminalDevice Terminal driver private structure.
707 @param Input The key will be input.
709 @retval TRUE If insert successfully.
710 @retval FALSE If Raw Data buffer is full before key insertion,
715 RawFiFoInsertOneKey (
716 TERMINAL_DEV
*TerminalDevice
,
722 Tail
= TerminalDevice
->RawFiFo
->Tail
;
724 if (IsRawFiFoFull (TerminalDevice
)) {
731 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
733 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
739 Remove one pre-fetched key out of the Raw Data FIFO.
741 @param TerminalDevice Terminal driver private structure.
742 @param Output The key will be removed.
744 @retval TRUE If insert successfully.
745 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
749 RawFiFoRemoveOneKey (
750 TERMINAL_DEV
*TerminalDevice
,
756 Head
= TerminalDevice
->RawFiFo
->Head
;
758 if (IsRawFiFoEmpty (TerminalDevice
)) {
766 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
768 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
774 Clarify whether Raw Data FIFO buffer is empty.
776 @param TerminalDevice Terminal driver private structure
778 @retval TRUE If Raw Data FIFO buffer is empty.
779 @retval FALSE If Raw Data FIFO buffer is not empty.
784 TERMINAL_DEV
*TerminalDevice
787 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
795 Clarify whether Raw Data FIFO buffer is full.
797 @param TerminalDevice Terminal driver private structure
799 @retval TRUE If Raw Data FIFO buffer is full.
800 @retval FALSE If Raw Data FIFO buffer is not full.
805 TERMINAL_DEV
*TerminalDevice
811 Tail
= TerminalDevice
->RawFiFo
->Tail
;
812 Head
= TerminalDevice
->RawFiFo
->Head
;
814 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
823 Insert one pre-fetched key into the FIFO buffer.
825 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
826 @param Input The key will be input.
828 @retval TRUE If insert successfully.
829 @retval FALSE If FIFO buffer is full before key insertion,
834 EfiKeyFiFoForNotifyInsertOneKey (
835 EFI_KEY_FIFO
*EfiKeyFiFo
,
841 Tail
= EfiKeyFiFo
->Tail
;
843 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo
)) {
850 CopyMem (&EfiKeyFiFo
->Data
[Tail
], Input
, sizeof (EFI_INPUT_KEY
));
852 EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
858 Remove one pre-fetched key out of the FIFO buffer.
860 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
861 @param Output The key will be removed.
863 @retval TRUE If remove successfully.
864 @retval FALSE If FIFO buffer is empty before remove operation.
868 EfiKeyFiFoForNotifyRemoveOneKey (
869 EFI_KEY_FIFO
*EfiKeyFiFo
,
870 EFI_INPUT_KEY
*Output
875 Head
= EfiKeyFiFo
->Head
;
876 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
878 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo
)) {
882 Output
->ScanCode
= SCAN_NULL
;
883 Output
->UnicodeChar
= 0;
887 CopyMem (Output
, &EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
889 EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
895 Clarify whether FIFO buffer is empty.
897 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
899 @retval TRUE If FIFO buffer is empty.
900 @retval FALSE If FIFO buffer is not empty.
904 IsEfiKeyFiFoForNotifyEmpty (
905 EFI_KEY_FIFO
*EfiKeyFiFo
908 if (EfiKeyFiFo
->Head
== EfiKeyFiFo
->Tail
) {
916 Clarify whether FIFO buffer is full.
918 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
920 @retval TRUE If FIFO buffer is full.
921 @retval FALSE If FIFO buffer is not full.
925 IsEfiKeyFiFoForNotifyFull (
926 EFI_KEY_FIFO
*EfiKeyFiFo
932 Tail
= EfiKeyFiFo
->Tail
;
933 Head
= EfiKeyFiFo
->Head
;
935 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
943 Insert one pre-fetched key into the FIFO buffer.
945 @param TerminalDevice Terminal driver private structure.
946 @param Key The key will be input.
948 @retval TRUE If insert successfully.
949 @retval FALSE If FIFO buffer is full before key insertion,
954 EfiKeyFiFoInsertOneKey (
955 TERMINAL_DEV
*TerminalDevice
,
961 LIST_ENTRY
*NotifyList
;
962 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
963 EFI_KEY_DATA KeyData
;
965 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
967 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
968 KeyData
.KeyState
.KeyShiftState
= 0;
969 KeyData
.KeyState
.KeyToggleState
= 0;
972 // Signal KeyNotify process event if this key pressed matches any key registered.
974 NotifyList
= &TerminalDevice
->NotifyList
;
975 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
978 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
980 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
982 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
984 // The key notification function needs to run at TPL_CALLBACK
985 // while current TPL is TPL_NOTIFY. It will be invoked in
986 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
988 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, Key
);
989 gBS
->SignalEvent (TerminalDevice
->KeyNotifyProcessEvent
);
992 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
994 // Efi Key FIFO is full
999 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
1001 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1007 Remove one pre-fetched key out of the FIFO buffer.
1009 @param TerminalDevice Terminal driver private structure.
1010 @param Output The key will be removed.
1012 @retval TRUE If insert successfully.
1013 @retval FALSE If FIFO buffer is empty before remove operation.
1017 EfiKeyFiFoRemoveOneKey (
1018 TERMINAL_DEV
*TerminalDevice
,
1019 EFI_INPUT_KEY
*Output
1024 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1025 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1027 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
1031 Output
->ScanCode
= SCAN_NULL
;
1032 Output
->UnicodeChar
= 0;
1036 CopyMem (Output
, &TerminalDevice
->EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
1038 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1044 Clarify whether FIFO buffer is empty.
1046 @param TerminalDevice Terminal driver private structure
1048 @retval TRUE If FIFO buffer is empty.
1049 @retval FALSE If FIFO buffer is not empty.
1054 TERMINAL_DEV
*TerminalDevice
1057 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
1065 Clarify whether FIFO buffer is full.
1067 @param TerminalDevice Terminal driver private structure
1069 @retval TRUE If FIFO buffer is full.
1070 @retval FALSE If FIFO buffer is not full.
1075 TERMINAL_DEV
*TerminalDevice
1081 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
1082 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1084 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1093 Insert one pre-fetched key into the Unicode FIFO buffer.
1095 @param TerminalDevice Terminal driver private structure.
1096 @param Input The key will be input.
1098 @retval TRUE If insert successfully.
1099 @retval FALSE If Unicode FIFO buffer is full before key insertion,
1100 and the key is lost.
1104 UnicodeFiFoInsertOneKey (
1105 TERMINAL_DEV
*TerminalDevice
,
1111 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1112 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
1115 if (IsUnicodeFiFoFull (TerminalDevice
)) {
1117 // Unicode FIFO is full
1122 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1124 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1130 Remove one pre-fetched key out of the Unicode FIFO buffer.
1131 The caller should guarantee that Unicode FIFO buffer is not empty
1132 by IsUnicodeFiFoEmpty ().
1134 @param TerminalDevice Terminal driver private structure.
1135 @param Output The key will be removed.
1139 UnicodeFiFoRemoveOneKey (
1140 TERMINAL_DEV
*TerminalDevice
,
1146 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1147 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1149 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1151 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1155 Clarify whether Unicode FIFO buffer is empty.
1157 @param TerminalDevice Terminal driver private structure
1159 @retval TRUE If Unicode FIFO buffer is empty.
1160 @retval FALSE If Unicode FIFO buffer is not empty.
1164 IsUnicodeFiFoEmpty (
1165 TERMINAL_DEV
*TerminalDevice
1168 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1176 Clarify whether Unicode FIFO buffer is full.
1178 @param TerminalDevice Terminal driver private structure
1180 @retval TRUE If Unicode FIFO buffer is full.
1181 @retval FALSE If Unicode FIFO buffer is not full.
1186 TERMINAL_DEV
*TerminalDevice
1192 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1193 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1195 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1204 Count Unicode FIFO buffer.
1206 @param TerminalDevice Terminal driver private structure
1208 @return The count in bytes of Unicode FIFO.
1212 UnicodeFiFoGetKeyCount (
1213 TERMINAL_DEV
*TerminalDevice
1219 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1220 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1223 return (UINT8
) (Tail
- Head
);
1225 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1230 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1232 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1236 UnicodeToEfiKeyFlushState (
1237 IN TERMINAL_DEV
*TerminalDevice
1243 InputState
= TerminalDevice
->InputState
;
1245 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1249 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1250 Key
.ScanCode
= SCAN_ESC
;
1251 Key
.UnicodeChar
= 0;
1252 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1255 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1256 Key
.ScanCode
= SCAN_NULL
;
1257 Key
.UnicodeChar
= CSI
;
1258 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1261 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1262 Key
.ScanCode
= SCAN_NULL
;
1263 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1264 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1267 if ((InputState
& INPUT_STATE_O
) != 0) {
1268 Key
.ScanCode
= SCAN_NULL
;
1269 Key
.UnicodeChar
= 'O';
1270 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1273 if ((InputState
& INPUT_STATE_2
) != 0) {
1274 Key
.ScanCode
= SCAN_NULL
;
1275 Key
.UnicodeChar
= '2';
1276 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1280 // Cancel the timer.
1283 TerminalDevice
->TwoSecondTimeOut
,
1288 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1293 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1294 can be read through the Simple Input Protocol.
1296 The table below shows the keyboard input mappings that this function supports.
1297 If the ESC sequence listed in one of the columns is presented, then it is translated
1298 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1299 key strokes are converted into EFI Keys.
1301 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1302 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1303 converted into EFI Keys.
1304 There is one special input sequence that will force the system to reset.
1305 This is ESC R ESC r ESC R.
1307 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1308 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1309 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1311 Symbols used in table below
1312 ===========================
1318 +=========+======+===========+==========+==========+
1319 | | EFI | UEFI 2.0 | | |
1320 | | Scan | | VT100+ | |
1321 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1322 +=========+======+===========+==========+==========+
1323 | NULL | 0x00 | | | |
1324 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1325 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1326 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1327 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1328 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1329 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1330 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1331 | | | ESC [ L | | ESC [ L |
1332 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1333 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1335 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1337 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1338 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1339 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1340 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1341 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1342 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1343 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1344 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1345 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1346 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1347 | Escape | 0x17 | ESC | ESC | ESC |
1348 | F11 | 0x15 | | ESC ! | |
1349 | F12 | 0x16 | | ESC @ | |
1350 +=========+======+===========+==========+==========+
1354 ESC R ESC r ESC R = Reset System
1356 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1361 IN TERMINAL_DEV
*TerminalDevice
1365 EFI_STATUS TimerStatus
;
1368 BOOLEAN SetDefaultResetState
;
1370 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1372 if (!EFI_ERROR (TimerStatus
)) {
1373 UnicodeToEfiKeyFlushState (TerminalDevice
);
1374 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1377 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1379 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1381 // Check to see if the 2 seconds timer has expired
1383 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1384 if (!EFI_ERROR (TimerStatus
)) {
1385 UnicodeToEfiKeyFlushState (TerminalDevice
);
1386 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1391 // Fetch one Unicode character from the Unicode FIFO
1393 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1395 SetDefaultResetState
= TRUE
;
1397 switch (TerminalDevice
->InputState
) {
1398 case INPUT_STATE_DEFAULT
:
1402 case INPUT_STATE_ESC
:
1404 if (UnicodeChar
== LEFTOPENBRACKET
) {
1405 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1406 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1410 if (UnicodeChar
== 'O' && (TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1411 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
)) {
1412 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1413 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1417 Key
.ScanCode
= SCAN_NULL
;
1419 if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1420 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
) {
1421 switch (UnicodeChar
) {
1423 Key
.ScanCode
= SCAN_F1
;
1426 Key
.ScanCode
= SCAN_F2
;
1429 Key
.ScanCode
= SCAN_F3
;
1432 Key
.ScanCode
= SCAN_F4
;
1435 Key
.ScanCode
= SCAN_F5
;
1438 Key
.ScanCode
= SCAN_F6
;
1441 Key
.ScanCode
= SCAN_F7
;
1444 Key
.ScanCode
= SCAN_F8
;
1447 Key
.ScanCode
= SCAN_F9
;
1450 Key
.ScanCode
= SCAN_F10
;
1453 Key
.ScanCode
= SCAN_F11
;
1456 Key
.ScanCode
= SCAN_F12
;
1459 Key
.ScanCode
= SCAN_HOME
;
1462 Key
.ScanCode
= SCAN_END
;
1465 Key
.ScanCode
= SCAN_INSERT
;
1468 Key
.ScanCode
= SCAN_DELETE
;
1471 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1474 Key
.ScanCode
= SCAN_PAGE_UP
;
1481 switch (UnicodeChar
) {
1483 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1484 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1485 SetDefaultResetState
= FALSE
;
1486 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1487 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1489 Key
.ScanCode
= SCAN_NULL
;
1492 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1493 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1494 SetDefaultResetState
= FALSE
;
1496 Key
.ScanCode
= SCAN_NULL
;
1502 if (SetDefaultResetState
) {
1503 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1506 if (Key
.ScanCode
!= SCAN_NULL
) {
1507 Key
.UnicodeChar
= 0;
1508 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1509 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1510 UnicodeToEfiKeyFlushState (TerminalDevice
);
1514 UnicodeToEfiKeyFlushState (TerminalDevice
);
1518 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1520 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1522 Key
.ScanCode
= SCAN_NULL
;
1524 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1525 switch (UnicodeChar
) {
1527 Key
.ScanCode
= SCAN_F1
;
1530 Key
.ScanCode
= SCAN_F2
;
1533 Key
.ScanCode
= SCAN_F3
;
1536 Key
.ScanCode
= SCAN_F4
;
1539 Key
.ScanCode
= SCAN_F5
;
1542 Key
.ScanCode
= SCAN_F6
;
1545 Key
.ScanCode
= SCAN_F7
;
1548 Key
.ScanCode
= SCAN_F8
;
1551 Key
.ScanCode
= SCAN_F9
;
1554 Key
.ScanCode
= SCAN_F10
;
1559 } else if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1560 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1561 switch (UnicodeChar
) {
1563 Key
.ScanCode
= SCAN_F1
;
1566 Key
.ScanCode
= SCAN_F2
;
1569 Key
.ScanCode
= SCAN_F3
;
1572 Key
.ScanCode
= SCAN_F4
;
1575 Key
.ScanCode
= SCAN_HOME
;
1578 Key
.ScanCode
= SCAN_END
;
1583 if (Key
.ScanCode
!= SCAN_NULL
) {
1584 Key
.UnicodeChar
= 0;
1585 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1586 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1587 UnicodeToEfiKeyFlushState (TerminalDevice
);
1591 UnicodeToEfiKeyFlushState (TerminalDevice
);
1595 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1597 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1599 Key
.ScanCode
= SCAN_NULL
;
1601 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1602 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1603 TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1604 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
||
1605 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1606 switch (UnicodeChar
) {
1608 Key
.ScanCode
= SCAN_UP
;
1611 Key
.ScanCode
= SCAN_DOWN
;
1614 Key
.ScanCode
= SCAN_RIGHT
;
1617 Key
.ScanCode
= SCAN_LEFT
;
1620 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1621 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1622 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1623 Key
.ScanCode
= SCAN_HOME
;
1627 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1628 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1629 Key
.ScanCode
= SCAN_END
;
1633 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1634 Key
.ScanCode
= SCAN_END
;
1639 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1640 TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1641 Key
.ScanCode
= SCAN_INSERT
;
1645 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1646 Key
.ScanCode
= SCAN_DELETE
;
1650 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1651 Key
.ScanCode
= SCAN_DELETE
;
1652 } else if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1653 Key
.ScanCode
= SCAN_F4
;
1657 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1658 Key
.ScanCode
= SCAN_PAGE_UP
;
1662 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1663 Key
.ScanCode
= SCAN_F10
;
1667 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1668 Key
.ScanCode
= SCAN_PAGE_UP
;
1672 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1673 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1677 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1678 Key
.ScanCode
= SCAN_F9
;
1682 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1683 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1687 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1688 Key
.ScanCode
= SCAN_F1
;
1692 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1693 Key
.ScanCode
= SCAN_F2
;
1697 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1698 Key
.ScanCode
= SCAN_F3
;
1702 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1703 Key
.ScanCode
= SCAN_F5
;
1707 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1708 Key
.ScanCode
= SCAN_F6
;
1712 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1713 Key
.ScanCode
= SCAN_F7
;
1717 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1718 Key
.ScanCode
= SCAN_F8
;
1727 * The VT220 escape codes that the TTY terminal accepts all have
1728 * numeric codes, and there are no ambiguous prefixes shared with
1729 * other terminal types.
1731 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
&&
1732 Key
.ScanCode
== SCAN_NULL
&&
1733 UnicodeChar
>= '0' &&
1734 UnicodeChar
<= '9') {
1735 TerminalDevice
->TtyEscapeStr
[0] = UnicodeChar
;
1736 TerminalDevice
->TtyEscapeIndex
= 1;
1737 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_2
;
1741 if (Key
.ScanCode
!= SCAN_NULL
) {
1742 Key
.UnicodeChar
= 0;
1743 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1744 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1745 UnicodeToEfiKeyFlushState (TerminalDevice
);
1749 UnicodeToEfiKeyFlushState (TerminalDevice
);
1754 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_2
:
1756 * Here we handle the VT220 escape codes that we accept. This
1757 * state is only used by the TTY terminal type.
1759 Key
.ScanCode
= SCAN_NULL
;
1760 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1762 if (UnicodeChar
== '~' && TerminalDevice
->TtyEscapeIndex
<= 2) {
1764 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
] = 0; /* Terminate string */
1765 EscCode
= (UINT16
) StrDecimalToUintn(TerminalDevice
->TtyEscapeStr
);
1768 Key
.ScanCode
= SCAN_INSERT
;
1771 Key
.ScanCode
= SCAN_DELETE
;
1774 Key
.ScanCode
= SCAN_PAGE_UP
;
1777 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1784 Key
.ScanCode
= SCAN_F1
+ EscCode
- 11;
1791 Key
.ScanCode
= SCAN_F6
+ EscCode
- 17;
1795 Key
.ScanCode
= SCAN_F11
+ EscCode
- 23;
1800 } else if (TerminalDevice
->TtyEscapeIndex
== 1){
1801 /* 2 character escape code */
1802 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
++] = UnicodeChar
;
1806 DEBUG ((EFI_D_ERROR
, "Unexpected state in escape2\n"));
1809 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1811 if (Key
.ScanCode
!= SCAN_NULL
) {
1812 Key
.UnicodeChar
= 0;
1813 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1814 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1815 UnicodeToEfiKeyFlushState (TerminalDevice
);
1819 UnicodeToEfiKeyFlushState (TerminalDevice
);
1824 // Invalid state. This should never happen.
1828 UnicodeToEfiKeyFlushState (TerminalDevice
);
1833 if (UnicodeChar
== ESC
) {
1834 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1837 if (UnicodeChar
== CSI
) {
1838 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1841 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1842 Status
= gBS
->SetTimer(
1843 TerminalDevice
->TwoSecondTimeOut
,
1847 ASSERT_EFI_ERROR (Status
);
1851 if (SetDefaultResetState
) {
1852 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1855 if (UnicodeChar
== DEL
) {
1856 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1857 Key
.ScanCode
= SCAN_NULL
;
1858 Key
.UnicodeChar
= CHAR_BACKSPACE
;
1861 Key
.ScanCode
= SCAN_DELETE
;
1862 Key
.UnicodeChar
= 0;
1865 Key
.ScanCode
= SCAN_NULL
;
1866 Key
.UnicodeChar
= UnicodeChar
;
1869 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);