2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2017, 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 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
48 KeyData
->KeyState
.KeyShiftState
= 0;
49 KeyData
->KeyState
.KeyToggleState
= 0;
57 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
58 This driver only perform dependent serial device reset regardless of
59 the value of ExtendeVerification
61 @param This Indicates the calling context.
62 @param ExtendedVerification Skip by this driver.
64 @retval EFI_SUCCESS The reset operation succeeds.
65 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
71 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
72 IN BOOLEAN ExtendedVerification
76 TERMINAL_DEV
*TerminalDevice
;
78 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
81 // Report progress code here
83 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
85 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
86 TerminalDevice
->DevicePath
89 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
92 // Make all the internal buffer empty for keys
94 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
95 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
96 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
97 TerminalDevice
->EfiKeyFiFoForNotify
->Head
= TerminalDevice
->EfiKeyFiFoForNotify
->Tail
;
99 if (EFI_ERROR (Status
)) {
100 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
101 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
102 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
103 TerminalDevice
->DevicePath
111 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
113 @param This Indicates the calling context.
114 @param Key A pointer to a buffer that is filled in with the
115 keystroke information for the key that was sent
118 @retval EFI_SUCCESS The keystroke information is returned successfully.
119 @retval EFI_NOT_READY There is no keystroke data available.
120 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
125 TerminalConInReadKeyStroke (
126 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
127 OUT EFI_INPUT_KEY
*Key
130 TERMINAL_DEV
*TerminalDevice
;
132 EFI_KEY_DATA KeyData
;
135 // get TERMINAL_DEV from "This" parameter.
137 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
139 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
140 if (EFI_ERROR (Status
)) {
144 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
151 Check if the key already has been registered.
153 If both RegsiteredData and InputData is NULL, then ASSERT().
155 @param RegsiteredData A pointer to a buffer that is filled in with the
156 keystroke state data for the key that was
158 @param InputData A pointer to a buffer that is filled in with the
159 keystroke state data for the key that was
162 @retval TRUE Key be pressed matches a registered key.
163 @retval FALSE Match failed.
168 IN EFI_KEY_DATA
*RegsiteredData
,
169 IN EFI_KEY_DATA
*InputData
172 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
174 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
175 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
185 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
186 Signal the event if there is key available
188 @param Event Indicates the event that invoke this function.
189 @param Context Indicates the calling context.
194 TerminalConInWaitForKeyEx (
199 TerminalConInWaitForKey (Event
, Context
);
203 // Simple Text Input Ex protocol functions
207 Reset the input device and optionally run diagnostics
209 @param This Protocol instance pointer.
210 @param ExtendedVerification Driver may perform diagnostics on reset.
212 @retval EFI_SUCCESS The device was reset.
213 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
219 TerminalConInResetEx (
220 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
221 IN BOOLEAN ExtendedVerification
225 TERMINAL_DEV
*TerminalDevice
;
227 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
229 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
230 if (EFI_ERROR (Status
)) {
231 return EFI_DEVICE_ERROR
;
240 Reads the next keystroke from the input device. The WaitForKey Event can
241 be used to test for existence of a keystroke via WaitForEvent () call.
243 @param This Protocol instance pointer.
244 @param KeyData A pointer to a buffer that is filled in with the
245 keystroke state data for the key that was
248 @retval EFI_SUCCESS The keystroke information was returned.
249 @retval EFI_NOT_READY There was no keystroke data available.
250 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
252 @retval EFI_INVALID_PARAMETER KeyData is NULL.
257 TerminalConInReadKeyStrokeEx (
258 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
259 OUT EFI_KEY_DATA
*KeyData
262 TERMINAL_DEV
*TerminalDevice
;
264 if (KeyData
== NULL
) {
265 return EFI_INVALID_PARAMETER
;
268 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
270 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
276 Set certain state for the input device.
278 @param This Protocol instance pointer.
279 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
280 state for the input device.
282 @retval EFI_SUCCESS The device state was set successfully.
283 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
284 could not have the setting adjusted.
285 @retval EFI_UNSUPPORTED The device does not have the ability to set its
287 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
292 TerminalConInSetState (
293 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
294 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
297 if (KeyToggleState
== NULL
) {
298 return EFI_INVALID_PARAMETER
;
301 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
302 return EFI_UNSUPPORTED
;
310 Register a notification function for a particular keystroke for the input device.
312 @param This Protocol instance pointer.
313 @param KeyData A pointer to a buffer that is filled in with
314 the keystroke information for the key that was
315 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
316 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
317 keystroke will trigger a notification of the KeyNotificationFunction.
318 @param KeyNotificationFunction Points to the function to be called when the key
319 sequence is typed specified by KeyData. This notification function
320 should be called at <=TPL_CALLBACK.
321 @param NotifyHandle Points to the unique handle assigned to the
322 registered notification.
324 @retval EFI_SUCCESS The notification function was registered
326 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
328 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
333 TerminalConInRegisterKeyNotify (
334 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
335 IN EFI_KEY_DATA
*KeyData
,
336 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
337 OUT VOID
**NotifyHandle
340 TERMINAL_DEV
*TerminalDevice
;
341 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
343 LIST_ENTRY
*NotifyList
;
344 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
346 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
347 return EFI_INVALID_PARAMETER
;
350 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
353 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
355 NotifyList
= &TerminalDevice
->NotifyList
;
356 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
359 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
361 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
363 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
364 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
365 *NotifyHandle
= CurrentNotify
;
372 // Allocate resource to save the notification function
374 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
375 if (NewNotify
== NULL
) {
376 return EFI_OUT_OF_RESOURCES
;
379 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
380 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
381 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
382 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
384 *NotifyHandle
= NewNotify
;
391 Remove a registered notification function from a particular keystroke.
393 @param This Protocol instance pointer.
394 @param NotificationHandle The handle of the notification function being
397 @retval EFI_SUCCESS The notification function was unregistered
399 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
404 TerminalConInUnregisterKeyNotify (
405 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
406 IN VOID
*NotificationHandle
409 TERMINAL_DEV
*TerminalDevice
;
411 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
412 LIST_ENTRY
*NotifyList
;
414 if (NotificationHandle
== NULL
) {
415 return EFI_INVALID_PARAMETER
;
418 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
420 NotifyList
= &TerminalDevice
->NotifyList
;
421 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
424 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
426 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
428 if (CurrentNotify
== NotificationHandle
) {
430 // Remove the notification function from NotifyList and free resources
432 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
434 gBS
->FreePool (CurrentNotify
);
440 // Can not find the matching entry in database.
442 return EFI_INVALID_PARAMETER
;
446 Translate raw data into Unicode (according to different encode), and
447 translate Unicode into key information. (according to different standard).
449 @param TerminalDevice Terminal driver private structure.
453 TranslateRawDataToEfiKey (
454 IN TERMINAL_DEV
*TerminalDevice
457 switch (TerminalDevice
->TerminalType
) {
459 case TerminalTypePcAnsi
:
460 case TerminalTypeVt100
:
461 case TerminalTypeVt100Plus
:
462 case TerminalTypeTtyTerm
:
463 AnsiRawDataToUnicode (TerminalDevice
);
464 UnicodeToEfiKey (TerminalDevice
);
467 case TerminalTypeVtUtf8
:
469 // Process all the raw data in the RawFIFO,
470 // put the processed key into UnicodeFIFO.
472 VTUTF8RawDataToUnicode (TerminalDevice
);
475 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
476 // then put into EfiKeyFIFO.
478 UnicodeToEfiKey (TerminalDevice
);
485 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
486 Signal the event if there is key available
488 @param Event Indicates the event that invoke this function.
489 @param Context Indicates the calling context.
494 TerminalConInWaitForKey (
500 // Someone is waiting on the keystroke event, if there's
501 // a key pending, signal the event
503 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
505 gBS
->SignalEvent (Event
);
510 Timer handler to poll the key from serial.
512 @param Event Indicates the event that invoke this function.
513 @param Context Indicates the calling context.
517 TerminalConInTimerHandler (
523 TERMINAL_DEV
*TerminalDevice
;
526 EFI_SERIAL_IO_MODE
*Mode
;
527 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
528 UINTN SerialInTimeOut
;
530 TerminalDevice
= (TERMINAL_DEV
*) Context
;
532 SerialIo
= TerminalDevice
->SerialIo
;
533 if (SerialIo
== NULL
) {
537 // if current timeout value for serial device is not identical with
538 // the value saved in TERMINAL_DEV structure, then recalculate the
539 // timeout value again and set serial attribute according to this value.
541 Mode
= SerialIo
->Mode
;
542 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
545 if (Mode
->BaudRate
!= 0) {
547 // According to BAUD rate to calculate the timeout value.
549 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
552 Status
= SerialIo
->SetAttributes (
555 Mode
->ReceiveFifoDepth
,
556 (UINT32
) SerialInTimeOut
,
557 (EFI_PARITY_TYPE
) (Mode
->Parity
),
558 (UINT8
) Mode
->DataBits
,
559 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
562 if (EFI_ERROR (Status
)) {
563 TerminalDevice
->SerialInTimeOut
= 0;
565 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
569 // Check whether serial buffer is empty.
570 // Skip the key transfer loop only if the SerialIo protocol instance
571 // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
573 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
574 if (EFI_ERROR (Status
) || ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0)) {
576 // Fetch all the keys in the serial buffer,
577 // and insert the byte stream into RawFIFO.
579 while (!IsRawFiFoFull (TerminalDevice
)) {
581 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
583 if (EFI_ERROR (Status
)) {
584 if (Status
== EFI_DEVICE_ERROR
) {
585 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
586 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
587 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
588 TerminalDevice
->DevicePath
594 RawFiFoInsertOneKey (TerminalDevice
, Input
);
599 // Translate all the raw data in RawFIFO into EFI Key,
600 // according to different terminal type supported.
602 TranslateRawDataToEfiKey (TerminalDevice
);
608 @param Event Indicates the event that invoke this function.
609 @param Context Indicates the calling context.
613 KeyNotifyProcessHandler (
619 TERMINAL_DEV
*TerminalDevice
;
621 EFI_KEY_DATA KeyData
;
623 LIST_ENTRY
*NotifyList
;
624 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
627 TerminalDevice
= (TERMINAL_DEV
*) Context
;
630 // Invoke notification functions.
632 NotifyList
= &TerminalDevice
->NotifyList
;
635 // Enter critical section
637 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
638 HasKey
= EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, &Key
);
639 CopyMem (&KeyData
.Key
, &Key
, sizeof (EFI_INPUT_KEY
));
640 KeyData
.KeyState
.KeyShiftState
= 0;
641 KeyData
.KeyState
.KeyToggleState
= 0;
643 // Leave critical section
645 gBS
->RestoreTPL (OldTpl
);
649 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
650 CurrentNotify
= CR (Link
, TERMINAL_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
651 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
652 CurrentNotify
->KeyNotificationFn (&KeyData
);
659 Get one key out of serial buffer.
661 @param SerialIo Serial I/O protocol attached to the serial device.
662 @param Output The fetched key.
664 @retval EFI_NOT_READY If serial buffer is empty.
665 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
666 @retval EFI_SUCCESS If reading serial buffer successfully, put
667 the fetched key to the parameter output.
671 GetOneKeyFromSerial (
672 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
683 // Read one key from serial I/O device.
685 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
687 if (EFI_ERROR (Status
)) {
689 if (Status
== EFI_TIMEOUT
) {
690 return EFI_NOT_READY
;
693 return EFI_DEVICE_ERROR
;
698 return EFI_NOT_READY
;
705 Insert one byte raw data into the Raw Data FIFO.
707 @param TerminalDevice Terminal driver private structure.
708 @param Input The key will be input.
710 @retval TRUE If insert successfully.
711 @retval FALSE If Raw Data buffer is full before key insertion,
716 RawFiFoInsertOneKey (
717 TERMINAL_DEV
*TerminalDevice
,
723 Tail
= TerminalDevice
->RawFiFo
->Tail
;
725 if (IsRawFiFoFull (TerminalDevice
)) {
732 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
734 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
740 Remove one pre-fetched key out of the Raw Data FIFO.
742 @param TerminalDevice Terminal driver private structure.
743 @param Output The key will be removed.
745 @retval TRUE If insert successfully.
746 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
750 RawFiFoRemoveOneKey (
751 TERMINAL_DEV
*TerminalDevice
,
757 Head
= TerminalDevice
->RawFiFo
->Head
;
759 if (IsRawFiFoEmpty (TerminalDevice
)) {
767 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
769 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
775 Clarify whether Raw Data FIFO buffer is empty.
777 @param TerminalDevice Terminal driver private structure
779 @retval TRUE If Raw Data FIFO buffer is empty.
780 @retval FALSE If Raw Data FIFO buffer is not empty.
785 TERMINAL_DEV
*TerminalDevice
788 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
796 Clarify whether Raw Data FIFO buffer is full.
798 @param TerminalDevice Terminal driver private structure
800 @retval TRUE If Raw Data FIFO buffer is full.
801 @retval FALSE If Raw Data FIFO buffer is not full.
806 TERMINAL_DEV
*TerminalDevice
812 Tail
= TerminalDevice
->RawFiFo
->Tail
;
813 Head
= TerminalDevice
->RawFiFo
->Head
;
815 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
824 Insert one pre-fetched key into the FIFO buffer.
826 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
827 @param Input The key will be input.
829 @retval TRUE If insert successfully.
830 @retval FALSE If FIFO buffer is full before key insertion,
835 EfiKeyFiFoForNotifyInsertOneKey (
836 EFI_KEY_FIFO
*EfiKeyFiFo
,
842 Tail
= EfiKeyFiFo
->Tail
;
844 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo
)) {
851 CopyMem (&EfiKeyFiFo
->Data
[Tail
], Input
, sizeof (EFI_INPUT_KEY
));
853 EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
859 Remove one pre-fetched key out of the FIFO buffer.
861 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
862 @param Output The key will be removed.
864 @retval TRUE If remove successfully.
865 @retval FALSE If FIFO buffer is empty before remove operation.
869 EfiKeyFiFoForNotifyRemoveOneKey (
870 EFI_KEY_FIFO
*EfiKeyFiFo
,
871 EFI_INPUT_KEY
*Output
876 Head
= EfiKeyFiFo
->Head
;
877 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
879 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo
)) {
883 Output
->ScanCode
= SCAN_NULL
;
884 Output
->UnicodeChar
= 0;
888 CopyMem (Output
, &EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
890 EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
896 Clarify whether FIFO buffer is empty.
898 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
900 @retval TRUE If FIFO buffer is empty.
901 @retval FALSE If FIFO buffer is not empty.
905 IsEfiKeyFiFoForNotifyEmpty (
906 EFI_KEY_FIFO
*EfiKeyFiFo
909 if (EfiKeyFiFo
->Head
== EfiKeyFiFo
->Tail
) {
917 Clarify whether FIFO buffer is full.
919 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
921 @retval TRUE If FIFO buffer is full.
922 @retval FALSE If FIFO buffer is not full.
926 IsEfiKeyFiFoForNotifyFull (
927 EFI_KEY_FIFO
*EfiKeyFiFo
933 Tail
= EfiKeyFiFo
->Tail
;
934 Head
= EfiKeyFiFo
->Head
;
936 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
944 Insert one pre-fetched key into the FIFO buffer.
946 @param TerminalDevice Terminal driver private structure.
947 @param Key The key will be input.
949 @retval TRUE If insert successfully.
950 @retval FALSE If FIFO buffer is full before key insertion,
955 EfiKeyFiFoInsertOneKey (
956 TERMINAL_DEV
*TerminalDevice
,
962 LIST_ENTRY
*NotifyList
;
963 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
964 EFI_KEY_DATA KeyData
;
966 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
968 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
969 KeyData
.KeyState
.KeyShiftState
= 0;
970 KeyData
.KeyState
.KeyToggleState
= 0;
973 // Signal KeyNotify process event if this key pressed matches any key registered.
975 NotifyList
= &TerminalDevice
->NotifyList
;
976 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
979 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
981 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
983 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
985 // The key notification function needs to run at TPL_CALLBACK
986 // while current TPL is TPL_NOTIFY. It will be invoked in
987 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
989 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, Key
);
990 gBS
->SignalEvent (TerminalDevice
->KeyNotifyProcessEvent
);
993 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
995 // Efi Key FIFO is full
1000 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
1002 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1008 Remove one pre-fetched key out of the FIFO buffer.
1010 @param TerminalDevice Terminal driver private structure.
1011 @param Output The key will be removed.
1013 @retval TRUE If insert successfully.
1014 @retval FALSE If FIFO buffer is empty before remove operation.
1018 EfiKeyFiFoRemoveOneKey (
1019 TERMINAL_DEV
*TerminalDevice
,
1020 EFI_INPUT_KEY
*Output
1025 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1026 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1028 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
1032 Output
->ScanCode
= SCAN_NULL
;
1033 Output
->UnicodeChar
= 0;
1037 CopyMem (Output
, &TerminalDevice
->EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
1039 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1045 Clarify whether FIFO buffer is empty.
1047 @param TerminalDevice Terminal driver private structure
1049 @retval TRUE If FIFO buffer is empty.
1050 @retval FALSE If FIFO buffer is not empty.
1055 TERMINAL_DEV
*TerminalDevice
1058 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
1066 Clarify whether FIFO buffer is full.
1068 @param TerminalDevice Terminal driver private structure
1070 @retval TRUE If FIFO buffer is full.
1071 @retval FALSE If FIFO buffer is not full.
1076 TERMINAL_DEV
*TerminalDevice
1082 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
1083 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1085 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1094 Insert one pre-fetched key into the Unicode FIFO buffer.
1096 @param TerminalDevice Terminal driver private structure.
1097 @param Input The key will be input.
1099 @retval TRUE If insert successfully.
1100 @retval FALSE If Unicode FIFO buffer is full before key insertion,
1101 and the key is lost.
1105 UnicodeFiFoInsertOneKey (
1106 TERMINAL_DEV
*TerminalDevice
,
1112 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1113 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
1116 if (IsUnicodeFiFoFull (TerminalDevice
)) {
1118 // Unicode FIFO is full
1123 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1125 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1131 Remove one pre-fetched key out of the Unicode FIFO buffer.
1132 The caller should guarantee that Unicode FIFO buffer is not empty
1133 by IsUnicodeFiFoEmpty ().
1135 @param TerminalDevice Terminal driver private structure.
1136 @param Output The key will be removed.
1140 UnicodeFiFoRemoveOneKey (
1141 TERMINAL_DEV
*TerminalDevice
,
1147 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1148 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1150 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1152 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1156 Clarify whether Unicode FIFO buffer is empty.
1158 @param TerminalDevice Terminal driver private structure
1160 @retval TRUE If Unicode FIFO buffer is empty.
1161 @retval FALSE If Unicode FIFO buffer is not empty.
1165 IsUnicodeFiFoEmpty (
1166 TERMINAL_DEV
*TerminalDevice
1169 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1177 Clarify whether Unicode FIFO buffer is full.
1179 @param TerminalDevice Terminal driver private structure
1181 @retval TRUE If Unicode FIFO buffer is full.
1182 @retval FALSE If Unicode FIFO buffer is not full.
1187 TERMINAL_DEV
*TerminalDevice
1193 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1194 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1196 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1205 Count Unicode FIFO buffer.
1207 @param TerminalDevice Terminal driver private structure
1209 @return The count in bytes of Unicode FIFO.
1213 UnicodeFiFoGetKeyCount (
1214 TERMINAL_DEV
*TerminalDevice
1220 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1221 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1224 return (UINT8
) (Tail
- Head
);
1226 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1231 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1233 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1237 UnicodeToEfiKeyFlushState (
1238 IN TERMINAL_DEV
*TerminalDevice
1244 InputState
= TerminalDevice
->InputState
;
1246 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1250 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1251 Key
.ScanCode
= SCAN_ESC
;
1252 Key
.UnicodeChar
= 0;
1253 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1256 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1257 Key
.ScanCode
= SCAN_NULL
;
1258 Key
.UnicodeChar
= CSI
;
1259 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1262 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1263 Key
.ScanCode
= SCAN_NULL
;
1264 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1265 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1268 if ((InputState
& INPUT_STATE_O
) != 0) {
1269 Key
.ScanCode
= SCAN_NULL
;
1270 Key
.UnicodeChar
= 'O';
1271 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1274 if ((InputState
& INPUT_STATE_2
) != 0) {
1275 Key
.ScanCode
= SCAN_NULL
;
1276 Key
.UnicodeChar
= '2';
1277 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1281 // Cancel the timer.
1284 TerminalDevice
->TwoSecondTimeOut
,
1289 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1294 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1295 can be read through the Simple Input Protocol.
1297 The table below shows the keyboard input mappings that this function supports.
1298 If the ESC sequence listed in one of the columns is presented, then it is translated
1299 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1300 key strokes are converted into EFI Keys.
1302 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1303 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1304 converted into EFI Keys.
1305 There is one special input sequence that will force the system to reset.
1306 This is ESC R ESC r ESC R.
1308 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1309 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1310 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1312 Symbols used in table below
1313 ===========================
1319 +=========+======+===========+==========+==========+
1320 | | EFI | UEFI 2.0 | | |
1321 | | Scan | | VT100+ | |
1322 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1323 +=========+======+===========+==========+==========+
1324 | NULL | 0x00 | | | |
1325 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1326 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1327 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1328 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1329 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1330 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1331 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1332 | | | ESC [ L | | ESC [ L |
1333 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1334 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1336 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1338 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1339 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1340 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1341 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1342 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1343 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1344 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1345 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1346 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1347 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1348 | Escape | 0x17 | ESC | ESC | ESC |
1349 | F11 | 0x15 | | ESC ! | |
1350 | F12 | 0x16 | | ESC @ | |
1351 +=========+======+===========+==========+==========+
1355 ESC R ESC r ESC R = Reset System
1357 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1362 IN TERMINAL_DEV
*TerminalDevice
1366 EFI_STATUS TimerStatus
;
1369 BOOLEAN SetDefaultResetState
;
1371 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1373 if (!EFI_ERROR (TimerStatus
)) {
1374 UnicodeToEfiKeyFlushState (TerminalDevice
);
1375 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1378 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1380 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1382 // Check to see if the 2 seconds timer has expired
1384 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1385 if (!EFI_ERROR (TimerStatus
)) {
1386 UnicodeToEfiKeyFlushState (TerminalDevice
);
1387 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1392 // Fetch one Unicode character from the Unicode FIFO
1394 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1396 SetDefaultResetState
= TRUE
;
1398 switch (TerminalDevice
->InputState
) {
1399 case INPUT_STATE_DEFAULT
:
1403 case INPUT_STATE_ESC
:
1405 if (UnicodeChar
== LEFTOPENBRACKET
) {
1406 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1407 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1411 if (UnicodeChar
== 'O' && (TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1412 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
)) {
1413 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1414 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1418 Key
.ScanCode
= SCAN_NULL
;
1420 if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1421 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
) {
1422 switch (UnicodeChar
) {
1424 Key
.ScanCode
= SCAN_F1
;
1427 Key
.ScanCode
= SCAN_F2
;
1430 Key
.ScanCode
= SCAN_F3
;
1433 Key
.ScanCode
= SCAN_F4
;
1436 Key
.ScanCode
= SCAN_F5
;
1439 Key
.ScanCode
= SCAN_F6
;
1442 Key
.ScanCode
= SCAN_F7
;
1445 Key
.ScanCode
= SCAN_F8
;
1448 Key
.ScanCode
= SCAN_F9
;
1451 Key
.ScanCode
= SCAN_F10
;
1454 Key
.ScanCode
= SCAN_F11
;
1457 Key
.ScanCode
= SCAN_F12
;
1460 Key
.ScanCode
= SCAN_HOME
;
1463 Key
.ScanCode
= SCAN_END
;
1466 Key
.ScanCode
= SCAN_INSERT
;
1469 Key
.ScanCode
= SCAN_DELETE
;
1472 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1475 Key
.ScanCode
= SCAN_PAGE_UP
;
1482 switch (UnicodeChar
) {
1484 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1485 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1486 SetDefaultResetState
= FALSE
;
1487 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1488 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1490 Key
.ScanCode
= SCAN_NULL
;
1493 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1494 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1495 SetDefaultResetState
= FALSE
;
1497 Key
.ScanCode
= SCAN_NULL
;
1503 if (SetDefaultResetState
) {
1504 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1507 if (Key
.ScanCode
!= SCAN_NULL
) {
1508 Key
.UnicodeChar
= 0;
1509 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1510 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1511 UnicodeToEfiKeyFlushState (TerminalDevice
);
1515 UnicodeToEfiKeyFlushState (TerminalDevice
);
1519 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1521 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1523 Key
.ScanCode
= SCAN_NULL
;
1525 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1526 switch (UnicodeChar
) {
1528 Key
.ScanCode
= SCAN_F1
;
1531 Key
.ScanCode
= SCAN_F2
;
1534 Key
.ScanCode
= SCAN_F3
;
1537 Key
.ScanCode
= SCAN_F4
;
1540 Key
.ScanCode
= SCAN_F5
;
1543 Key
.ScanCode
= SCAN_F6
;
1546 Key
.ScanCode
= SCAN_F7
;
1549 Key
.ScanCode
= SCAN_F8
;
1552 Key
.ScanCode
= SCAN_F9
;
1555 Key
.ScanCode
= SCAN_F10
;
1560 } else if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1561 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1562 switch (UnicodeChar
) {
1564 Key
.ScanCode
= SCAN_F1
;
1567 Key
.ScanCode
= SCAN_F2
;
1570 Key
.ScanCode
= SCAN_F3
;
1573 Key
.ScanCode
= SCAN_F4
;
1576 Key
.ScanCode
= SCAN_HOME
;
1579 Key
.ScanCode
= SCAN_END
;
1584 if (Key
.ScanCode
!= SCAN_NULL
) {
1585 Key
.UnicodeChar
= 0;
1586 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1587 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1588 UnicodeToEfiKeyFlushState (TerminalDevice
);
1592 UnicodeToEfiKeyFlushState (TerminalDevice
);
1596 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1598 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1600 Key
.ScanCode
= SCAN_NULL
;
1602 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1603 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1604 TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1605 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
||
1606 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1607 switch (UnicodeChar
) {
1609 Key
.ScanCode
= SCAN_UP
;
1612 Key
.ScanCode
= SCAN_DOWN
;
1615 Key
.ScanCode
= SCAN_RIGHT
;
1618 Key
.ScanCode
= SCAN_LEFT
;
1621 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1622 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1623 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1624 Key
.ScanCode
= SCAN_HOME
;
1628 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1629 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1630 Key
.ScanCode
= SCAN_END
;
1634 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1635 Key
.ScanCode
= SCAN_END
;
1640 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1641 TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1642 Key
.ScanCode
= SCAN_INSERT
;
1646 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1647 Key
.ScanCode
= SCAN_DELETE
;
1651 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1652 Key
.ScanCode
= SCAN_DELETE
;
1653 } else if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1654 Key
.ScanCode
= SCAN_F4
;
1658 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1659 Key
.ScanCode
= SCAN_PAGE_UP
;
1663 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1664 Key
.ScanCode
= SCAN_F10
;
1668 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1669 Key
.ScanCode
= SCAN_PAGE_UP
;
1673 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1674 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1678 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1679 Key
.ScanCode
= SCAN_F9
;
1683 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1684 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1688 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1689 Key
.ScanCode
= SCAN_F1
;
1693 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1694 Key
.ScanCode
= SCAN_F2
;
1698 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1699 Key
.ScanCode
= SCAN_F3
;
1703 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1704 Key
.ScanCode
= SCAN_F5
;
1708 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1709 Key
.ScanCode
= SCAN_F6
;
1713 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1714 Key
.ScanCode
= SCAN_F7
;
1718 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1719 Key
.ScanCode
= SCAN_F8
;
1728 * The VT220 escape codes that the TTY terminal accepts all have
1729 * numeric codes, and there are no ambiguous prefixes shared with
1730 * other terminal types.
1732 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
&&
1733 Key
.ScanCode
== SCAN_NULL
&&
1734 UnicodeChar
>= '0' &&
1735 UnicodeChar
<= '9') {
1736 TerminalDevice
->TtyEscapeStr
[0] = UnicodeChar
;
1737 TerminalDevice
->TtyEscapeIndex
= 1;
1738 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_2
;
1742 if (Key
.ScanCode
!= SCAN_NULL
) {
1743 Key
.UnicodeChar
= 0;
1744 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1745 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1746 UnicodeToEfiKeyFlushState (TerminalDevice
);
1750 UnicodeToEfiKeyFlushState (TerminalDevice
);
1755 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_2
:
1757 * Here we handle the VT220 escape codes that we accept. This
1758 * state is only used by the TTY terminal type.
1760 Key
.ScanCode
= SCAN_NULL
;
1761 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1763 if (UnicodeChar
== '~' && TerminalDevice
->TtyEscapeIndex
<= 2) {
1765 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
] = 0; /* Terminate string */
1766 EscCode
= (UINT16
) StrDecimalToUintn(TerminalDevice
->TtyEscapeStr
);
1769 Key
.ScanCode
= SCAN_INSERT
;
1772 Key
.ScanCode
= SCAN_DELETE
;
1775 Key
.ScanCode
= SCAN_PAGE_UP
;
1778 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1785 Key
.ScanCode
= SCAN_F1
+ EscCode
- 11;
1792 Key
.ScanCode
= SCAN_F6
+ EscCode
- 17;
1796 Key
.ScanCode
= SCAN_F11
+ EscCode
- 23;
1801 } else if (TerminalDevice
->TtyEscapeIndex
== 1){
1802 /* 2 character escape code */
1803 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
++] = UnicodeChar
;
1807 DEBUG ((EFI_D_ERROR
, "Unexpected state in escape2\n"));
1810 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1812 if (Key
.ScanCode
!= SCAN_NULL
) {
1813 Key
.UnicodeChar
= 0;
1814 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1815 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1816 UnicodeToEfiKeyFlushState (TerminalDevice
);
1820 UnicodeToEfiKeyFlushState (TerminalDevice
);
1825 // Invalid state. This should never happen.
1829 UnicodeToEfiKeyFlushState (TerminalDevice
);
1834 if (UnicodeChar
== ESC
) {
1835 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1838 if (UnicodeChar
== CSI
) {
1839 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1842 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1843 Status
= gBS
->SetTimer(
1844 TerminalDevice
->TwoSecondTimeOut
,
1848 ASSERT_EFI_ERROR (Status
);
1852 if (SetDefaultResetState
) {
1853 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1856 if (UnicodeChar
== DEL
) {
1857 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1858 Key
.ScanCode
= SCAN_NULL
;
1859 Key
.UnicodeChar
= CHAR_BACKSPACE
;
1862 Key
.ScanCode
= SCAN_DELETE
;
1863 Key
.UnicodeChar
= 0;
1866 Key
.ScanCode
= SCAN_NULL
;
1867 Key
.UnicodeChar
= UnicodeChar
;
1870 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);