2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Reads the next keystroke from the input device. The WaitForKey Event can
20 be used to test for existence of a keystroke via WaitForEvent () call.
22 @param TerminalDevice Terminal driver private structure
23 @param KeyData A pointer to a buffer that is filled in with the
24 keystroke state data for the key that was
27 @retval EFI_SUCCESS The keystroke information was returned.
28 @retval EFI_NOT_READY There was no keystroke data available.
29 @retval EFI_INVALID_PARAMETER KeyData is NULL.
34 IN TERMINAL_DEV
*TerminalDevice
,
35 OUT EFI_KEY_DATA
*KeyData
38 if (KeyData
== NULL
) {
39 return EFI_INVALID_PARAMETER
;
42 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
46 KeyData
->KeyState
.KeyShiftState
= 0;
47 KeyData
->KeyState
.KeyToggleState
= 0;
55 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
56 This driver only perform dependent serial device reset regardless of
57 the value of ExtendeVerification
59 @param This Indicates the calling context.
60 @param ExtendedVerification Skip by this driver.
62 @retval EFI_SUCCESS The reset operation succeeds.
63 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
69 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
70 IN BOOLEAN ExtendedVerification
74 TERMINAL_DEV
*TerminalDevice
;
76 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
79 // Report progress code here
81 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
83 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
84 TerminalDevice
->DevicePath
87 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
90 // Make all the internal buffer empty for keys
92 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
93 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
94 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
96 if (EFI_ERROR (Status
)) {
97 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
98 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
99 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
100 TerminalDevice
->DevicePath
108 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
110 @param This Indicates the calling context.
111 @param Key A pointer to a buffer that is filled in with the
112 keystroke information for the key that was sent
115 @retval EFI_SUCCESS The keystroke information is returned successfully.
116 @retval EFI_NOT_READY There is no keystroke data available.
117 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
122 TerminalConInReadKeyStroke (
123 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
124 OUT EFI_INPUT_KEY
*Key
127 TERMINAL_DEV
*TerminalDevice
;
129 EFI_KEY_DATA KeyData
;
132 // get TERMINAL_DEV from "This" parameter.
134 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
136 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
137 if (EFI_ERROR (Status
)) {
141 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
148 Check if the key already has been registered.
150 If both RegsiteredData and InputData is NULL, then ASSERT().
152 @param RegsiteredData A pointer to a buffer that is filled in with the
153 keystroke state data for the key that was
155 @param InputData A pointer to a buffer that is filled in with the
156 keystroke state data for the key that was
159 @retval TRUE Key be pressed matches a registered key.
160 @retval FLASE Match failed.
165 IN EFI_KEY_DATA
*RegsiteredData
,
166 IN EFI_KEY_DATA
*InputData
169 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
171 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
172 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
182 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
183 Signal the event if there is key available
185 @param Event Indicates the event that invoke this function.
186 @param Context Indicates the calling context.
191 TerminalConInWaitForKeyEx (
196 TerminalConInWaitForKey (Event
, Context
);
200 // Simple Text Input Ex protocol functions
204 Reset the input device and optionally run diagnostics
206 @param This Protocol instance pointer.
207 @param ExtendedVerification Driver may perform diagnostics on reset.
209 @retval EFI_SUCCESS The device was reset.
210 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
216 TerminalConInResetEx (
217 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
218 IN BOOLEAN ExtendedVerification
222 TERMINAL_DEV
*TerminalDevice
;
224 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
226 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
227 if (EFI_ERROR (Status
)) {
228 return EFI_DEVICE_ERROR
;
237 Reads the next keystroke from the input device. The WaitForKey Event can
238 be used to test for existence of a keystroke via WaitForEvent () call.
240 @param This Protocol instance pointer.
241 @param KeyData A pointer to a buffer that is filled in with the
242 keystroke state data for the key that was
245 @retval EFI_SUCCESS The keystroke information was returned.
246 @retval EFI_NOT_READY There was no keystroke data available.
247 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
249 @retval EFI_INVALID_PARAMETER KeyData is NULL.
254 TerminalConInReadKeyStrokeEx (
255 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
256 OUT EFI_KEY_DATA
*KeyData
259 TERMINAL_DEV
*TerminalDevice
;
261 if (KeyData
== NULL
) {
262 return EFI_INVALID_PARAMETER
;
265 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
267 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
273 Set certain state for the input device.
275 @param This Protocol instance pointer.
276 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
277 state for the input device.
279 @retval EFI_SUCCESS The device state was set successfully.
280 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
281 could not have the setting adjusted.
282 @retval EFI_UNSUPPORTED The device does not have the ability to set its
284 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
289 TerminalConInSetState (
290 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
291 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
294 if (KeyToggleState
== NULL
) {
295 return EFI_INVALID_PARAMETER
;
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 the
307 keystroke information data for the key that was
309 @param KeyNotificationFunction Points to the function to be called when the key
310 sequence is typed specified by KeyData.
311 @param NotifyHandle Points to the unique handle assigned to the
312 registered notification.
314 @retval EFI_SUCCESS The notification function was registered
316 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
318 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
323 TerminalConInRegisterKeyNotify (
324 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
325 IN EFI_KEY_DATA
*KeyData
,
326 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
327 OUT VOID
**NotifyHandle
330 TERMINAL_DEV
*TerminalDevice
;
331 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
333 LIST_ENTRY
*NotifyList
;
334 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
336 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
337 return EFI_INVALID_PARAMETER
;
340 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
343 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
345 NotifyList
= &TerminalDevice
->NotifyList
;
346 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
349 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
351 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
353 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
354 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
355 *NotifyHandle
= CurrentNotify
;
362 // Allocate resource to save the notification function
364 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
365 if (NewNotify
== NULL
) {
366 return EFI_OUT_OF_RESOURCES
;
369 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
370 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
371 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
372 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
374 *NotifyHandle
= NewNotify
;
381 Remove a registered notification function from a particular keystroke.
383 @param This Protocol instance pointer.
384 @param NotificationHandle The handle of the notification function being
387 @retval EFI_SUCCESS The notification function was unregistered
389 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
394 TerminalConInUnregisterKeyNotify (
395 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
396 IN VOID
*NotificationHandle
399 TERMINAL_DEV
*TerminalDevice
;
401 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
402 LIST_ENTRY
*NotifyList
;
404 if (NotificationHandle
== NULL
) {
405 return EFI_INVALID_PARAMETER
;
408 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
410 NotifyList
= &TerminalDevice
->NotifyList
;
411 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
414 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
416 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
418 if (CurrentNotify
== NotificationHandle
) {
420 // Remove the notification function from NotifyList and free resources
422 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
424 gBS
->FreePool (CurrentNotify
);
430 // Can not find the matching entry in database.
432 return EFI_INVALID_PARAMETER
;
436 Translate raw data into Unicode (according to different encode), and
437 translate Unicode into key information. (according to different standard).
439 @param TerminalDevice Terminal driver private structure.
443 TranslateRawDataToEfiKey (
444 IN TERMINAL_DEV
*TerminalDevice
447 switch (TerminalDevice
->TerminalType
) {
452 AnsiRawDataToUnicode (TerminalDevice
);
453 UnicodeToEfiKey (TerminalDevice
);
458 // Process all the raw data in the RawFIFO,
459 // put the processed key into UnicodeFIFO.
461 VTUTF8RawDataToUnicode (TerminalDevice
);
464 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
465 // then put into EfiKeyFIFO.
467 UnicodeToEfiKey (TerminalDevice
);
474 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
475 Signal the event if there is key available
477 @param Event Indicates the event that invoke this function.
478 @param Context Indicates the calling context.
483 TerminalConInWaitForKey (
489 // Someone is waiting on the keystroke event, if there's
490 // a key pending, signal the event
492 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
494 gBS
->SignalEvent (Event
);
499 Timer handler to poll the key from serial.
501 @param Event Indicates the event that invoke this function.
502 @param Context Indicates the calling context.
506 TerminalConInTimerHandler (
512 TERMINAL_DEV
*TerminalDevice
;
515 EFI_SERIAL_IO_MODE
*Mode
;
516 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
517 UINTN SerialInTimeOut
;
519 TerminalDevice
= (TERMINAL_DEV
*) Context
;
521 SerialIo
= TerminalDevice
->SerialIo
;
522 if (SerialIo
== NULL
) {
526 // if current timeout value for serial device is not identical with
527 // the value saved in TERMINAL_DEV structure, then recalculate the
528 // timeout value again and set serial attribute according to this value.
530 Mode
= SerialIo
->Mode
;
531 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
534 if (Mode
->BaudRate
!= 0) {
536 // According to BAUD rate to calculate the timeout value.
538 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
541 Status
= SerialIo
->SetAttributes (
544 Mode
->ReceiveFifoDepth
,
545 (UINT32
) SerialInTimeOut
,
546 (EFI_PARITY_TYPE
) (Mode
->Parity
),
547 (UINT8
) Mode
->DataBits
,
548 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
551 if (EFI_ERROR (Status
)) {
552 TerminalDevice
->SerialInTimeOut
= 0;
554 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
558 // Check whether serial buffer is empty.
560 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
562 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0) {
564 // Fetch all the keys in the serial buffer,
565 // and insert the byte stream into RawFIFO.
567 while (!IsRawFiFoFull (TerminalDevice
)) {
569 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
571 if (EFI_ERROR (Status
)) {
572 if (Status
== EFI_DEVICE_ERROR
) {
573 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
574 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
575 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
576 TerminalDevice
->DevicePath
582 RawFiFoInsertOneKey (TerminalDevice
, Input
);
587 // Translate all the raw data in RawFIFO into EFI Key,
588 // according to different terminal type supported.
590 TranslateRawDataToEfiKey (TerminalDevice
);
594 Get one key out of serial buffer.
596 @param SerialIo Serial I/O protocol attached to the serial device.
597 @param Output The fetched key.
599 @retval EFI_NOT_READY If serial buffer is empty.
600 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
601 @retval EFI_SUCCESS If reading serial buffer successfully, put
602 the fetched key to the parameter output.
606 GetOneKeyFromSerial (
607 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
618 // Read one key from serial I/O device.
620 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
622 if (EFI_ERROR (Status
)) {
624 if (Status
== EFI_TIMEOUT
) {
625 return EFI_NOT_READY
;
628 return EFI_DEVICE_ERROR
;
633 return EFI_NOT_READY
;
640 Insert one byte raw data into the Raw Data FIFO.
642 @param TerminalDevice Terminal driver private structure.
643 @param Input The key will be input.
645 @retval TRUE If insert successfully.
646 @retval FLASE If Raw Data buffer is full before key insertion,
651 RawFiFoInsertOneKey (
652 TERMINAL_DEV
*TerminalDevice
,
658 Tail
= TerminalDevice
->RawFiFo
->Tail
;
660 if (IsRawFiFoFull (TerminalDevice
)) {
667 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
669 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
675 Remove one pre-fetched key out of the Raw Data FIFO.
677 @param TerminalDevice Terminal driver private structure.
678 @param Output The key will be removed.
680 @retval TRUE If insert successfully.
681 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
685 RawFiFoRemoveOneKey (
686 TERMINAL_DEV
*TerminalDevice
,
692 Head
= TerminalDevice
->RawFiFo
->Head
;
694 if (IsRawFiFoEmpty (TerminalDevice
)) {
702 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
704 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
710 Clarify whether Raw Data FIFO buffer is empty.
712 @param TerminalDevice Terminal driver private structure
714 @retval TRUE If Raw Data FIFO buffer is empty.
715 @retval FLASE If Raw Data FIFO buffer is not empty.
720 TERMINAL_DEV
*TerminalDevice
723 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
731 Clarify whether Raw Data FIFO buffer is full.
733 @param TerminalDevice Terminal driver private structure
735 @retval TRUE If Raw Data FIFO buffer is full.
736 @retval FLASE If Raw Data FIFO buffer is not full.
741 TERMINAL_DEV
*TerminalDevice
747 Tail
= TerminalDevice
->RawFiFo
->Tail
;
748 Head
= TerminalDevice
->RawFiFo
->Head
;
750 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
759 Insert one pre-fetched key into the FIFO buffer.
761 @param TerminalDevice Terminal driver private structure.
762 @param Key The key will be input.
764 @retval TRUE If insert successfully.
765 @retval FLASE If FIFO buffer is full before key insertion,
770 EfiKeyFiFoInsertOneKey (
771 TERMINAL_DEV
*TerminalDevice
,
777 LIST_ENTRY
*NotifyList
;
778 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
779 EFI_KEY_DATA KeyData
;
781 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
783 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
784 KeyData
.KeyState
.KeyShiftState
= 0;
785 KeyData
.KeyState
.KeyToggleState
= 0;
788 // Invoke notification functions if exist
790 NotifyList
= &TerminalDevice
->NotifyList
;
791 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
794 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
796 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
798 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
799 CurrentNotify
->KeyNotificationFn (&KeyData
);
802 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
804 // Efi Key FIFO is full
809 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
811 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
817 Remove one pre-fetched key out of the FIFO buffer.
819 @param TerminalDevice Terminal driver private structure.
820 @param Output The key will be removed.
822 @retval TRUE If insert successfully.
823 @retval FLASE If FIFO buffer is empty before remove operation.
827 EfiKeyFiFoRemoveOneKey (
828 TERMINAL_DEV
*TerminalDevice
,
829 EFI_INPUT_KEY
*Output
834 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
835 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
837 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
841 Output
->ScanCode
= SCAN_NULL
;
842 Output
->UnicodeChar
= 0;
846 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
848 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
854 Clarify whether FIFO buffer is empty.
856 @param TerminalDevice Terminal driver private structure
858 @retval TRUE If FIFO buffer is empty.
859 @retval FLASE If FIFO buffer is not empty.
864 TERMINAL_DEV
*TerminalDevice
867 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
875 Clarify whether FIFO buffer is full.
877 @param TerminalDevice Terminal driver private structure
879 @retval TRUE If FIFO buffer is full.
880 @retval FLASE If FIFO buffer is not full.
885 TERMINAL_DEV
*TerminalDevice
891 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
892 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
894 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
903 Insert one pre-fetched key into the Unicode FIFO buffer.
905 @param TerminalDevice Terminal driver private structure.
906 @param Input The key will be input.
908 @retval TRUE If insert successfully.
909 @retval FLASE If Unicode FIFO buffer is full before key insertion,
914 UnicodeFiFoInsertOneKey (
915 TERMINAL_DEV
*TerminalDevice
,
921 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
922 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
925 if (IsUnicodeFiFoFull (TerminalDevice
)) {
927 // Unicode FIFO is full
932 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
934 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
940 Remove one pre-fetched key out of the Unicode FIFO buffer.
942 @param TerminalDevice Terminal driver private structure.
943 @param Output The key will be removed.
945 @retval TRUE If insert successfully.
946 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
950 UnicodeFiFoRemoveOneKey (
951 TERMINAL_DEV
*TerminalDevice
,
957 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
958 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
960 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
968 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
970 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
976 Clarify whether Unicode FIFO buffer is empty.
978 @param TerminalDevice Terminal driver private structure
980 @retval TRUE If Unicode FIFO buffer is empty.
981 @retval FLASE If Unicode FIFO buffer is not empty.
986 TERMINAL_DEV
*TerminalDevice
989 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
997 Clarify whether Unicode FIFO buffer is full.
999 @param TerminalDevice Terminal driver private structure
1001 @retval TRUE If Unicode FIFO buffer is full.
1002 @retval FLASE If Unicode FIFO buffer is not full.
1007 TERMINAL_DEV
*TerminalDevice
1013 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1014 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1016 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1025 Count Unicode FIFO buffer.
1027 @param TerminalDevice Terminal driver private structure
1029 @return The count in bytes of Unicode FIFO.
1033 UnicodeFiFoGetKeyCount (
1034 TERMINAL_DEV
*TerminalDevice
1040 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1041 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1044 return (UINT8
) (Tail
- Head
);
1046 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1051 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1053 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1057 UnicodeToEfiKeyFlushState (
1058 IN TERMINAL_DEV
*TerminalDevice
1064 InputState
= TerminalDevice
->InputState
;
1066 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1070 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1071 Key
.ScanCode
= SCAN_ESC
;
1072 Key
.UnicodeChar
= 0;
1073 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1076 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1077 Key
.ScanCode
= SCAN_NULL
;
1078 Key
.UnicodeChar
= CSI
;
1079 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1082 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1083 Key
.ScanCode
= SCAN_NULL
;
1084 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1085 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1088 if ((InputState
& INPUT_STATE_O
) != 0) {
1089 Key
.ScanCode
= SCAN_NULL
;
1090 Key
.UnicodeChar
= 'O';
1091 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1094 if ((InputState
& INPUT_STATE_2
) != 0) {
1095 Key
.ScanCode
= SCAN_NULL
;
1096 Key
.UnicodeChar
= '2';
1097 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1101 // Cancel the timer.
1104 TerminalDevice
->TwoSecondTimeOut
,
1109 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1114 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1115 can be read through the Simple Input Protocol.
1117 The table below shows the keyboard input mappings that this function supports.
1118 If the ESC sequence listed in one of the columns is presented, then it is translated
1119 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1120 key strokes are converted into EFI Keys.
1122 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1123 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1124 converted into EFI Keys.
1125 There is one special input sequence that will force the system to reset.
1126 This is ESC R ESC r ESC R.
1128 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1129 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1130 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1132 Symbols used in table below
1133 ===========================
1139 +=========+======+===========+==========+==========+
1140 | | EFI | UEFI 2.0 | | |
1141 | | Scan | | VT100+ | |
1142 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1143 +=========+======+===========+==========+==========+
1144 | NULL | 0x00 | | | |
1145 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1146 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1147 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1148 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1149 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1150 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1151 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1152 | | | ESC [ L | | ESC [ L |
1153 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1154 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1156 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1158 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1159 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1160 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1161 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1162 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1163 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1164 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1165 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1166 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1167 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1168 | Escape | 0x17 | ESC | ESC | ESC |
1169 | F11 | 0x15 | | ESC ! | |
1170 | F12 | 0x16 | | ESC @ | |
1171 +=========+======+===========+==========+==========+
1175 ESC R ESC r ESC R = Reset System
1177 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1182 IN TERMINAL_DEV
*TerminalDevice
1186 EFI_STATUS TimerStatus
;
1189 BOOLEAN SetDefaultResetState
;
1191 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1193 if (!EFI_ERROR (TimerStatus
)) {
1194 UnicodeToEfiKeyFlushState (TerminalDevice
);
1195 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1198 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1200 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1202 // Check to see if the 2 seconds timer has expired
1204 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1205 if (!EFI_ERROR (TimerStatus
)) {
1206 UnicodeToEfiKeyFlushState (TerminalDevice
);
1207 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1212 // Fetch one Unicode character from the Unicode FIFO
1214 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1216 SetDefaultResetState
= TRUE
;
1218 switch (TerminalDevice
->InputState
) {
1219 case INPUT_STATE_DEFAULT
:
1223 case INPUT_STATE_ESC
:
1225 if (UnicodeChar
== LEFTOPENBRACKET
) {
1226 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1227 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1231 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1232 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1233 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1237 Key
.ScanCode
= SCAN_NULL
;
1239 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1240 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1241 switch (UnicodeChar
) {
1243 Key
.ScanCode
= SCAN_F1
;
1246 Key
.ScanCode
= SCAN_F2
;
1249 Key
.ScanCode
= SCAN_F3
;
1252 Key
.ScanCode
= SCAN_F4
;
1255 Key
.ScanCode
= SCAN_F5
;
1258 Key
.ScanCode
= SCAN_F6
;
1261 Key
.ScanCode
= SCAN_F7
;
1264 Key
.ScanCode
= SCAN_F8
;
1267 Key
.ScanCode
= SCAN_F9
;
1270 Key
.ScanCode
= SCAN_F10
;
1273 Key
.ScanCode
= SCAN_F11
;
1276 Key
.ScanCode
= SCAN_F12
;
1279 Key
.ScanCode
= SCAN_HOME
;
1282 Key
.ScanCode
= SCAN_END
;
1285 Key
.ScanCode
= SCAN_INSERT
;
1288 Key
.ScanCode
= SCAN_DELETE
;
1291 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1294 Key
.ScanCode
= SCAN_PAGE_UP
;
1301 switch (UnicodeChar
) {
1303 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1304 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1305 SetDefaultResetState
= FALSE
;
1306 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1307 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1309 Key
.ScanCode
= SCAN_NULL
;
1312 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1313 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1314 SetDefaultResetState
= FALSE
;
1316 Key
.ScanCode
= SCAN_NULL
;
1322 if (SetDefaultResetState
) {
1323 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1326 if (Key
.ScanCode
!= SCAN_NULL
) {
1327 Key
.UnicodeChar
= 0;
1328 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1329 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1330 UnicodeToEfiKeyFlushState (TerminalDevice
);
1334 UnicodeToEfiKeyFlushState (TerminalDevice
);
1338 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1340 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1342 Key
.ScanCode
= SCAN_NULL
;
1344 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1345 switch (UnicodeChar
) {
1347 Key
.ScanCode
= SCAN_F1
;
1350 Key
.ScanCode
= SCAN_F2
;
1353 Key
.ScanCode
= SCAN_F3
;
1356 Key
.ScanCode
= SCAN_F4
;
1359 Key
.ScanCode
= SCAN_F5
;
1362 Key
.ScanCode
= SCAN_F6
;
1365 Key
.ScanCode
= SCAN_F7
;
1368 Key
.ScanCode
= SCAN_F8
;
1371 Key
.ScanCode
= SCAN_F9
;
1374 Key
.ScanCode
= SCAN_F10
;
1381 if (Key
.ScanCode
!= SCAN_NULL
) {
1382 Key
.UnicodeChar
= 0;
1383 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1384 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1385 UnicodeToEfiKeyFlushState (TerminalDevice
);
1389 UnicodeToEfiKeyFlushState (TerminalDevice
);
1393 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1395 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1397 Key
.ScanCode
= SCAN_NULL
;
1399 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1400 TerminalDevice
->TerminalType
== VT100TYPE
||
1401 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1402 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1403 switch (UnicodeChar
) {
1405 Key
.ScanCode
= SCAN_UP
;
1408 Key
.ScanCode
= SCAN_DOWN
;
1411 Key
.ScanCode
= SCAN_RIGHT
;
1414 Key
.ScanCode
= SCAN_LEFT
;
1417 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1418 TerminalDevice
->TerminalType
== VT100TYPE
) {
1419 Key
.ScanCode
= SCAN_HOME
;
1423 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1424 Key
.ScanCode
= SCAN_END
;
1428 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1429 Key
.ScanCode
= SCAN_END
;
1434 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1435 TerminalDevice
->TerminalType
== VT100TYPE
) {
1436 Key
.ScanCode
= SCAN_INSERT
;
1440 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1441 Key
.ScanCode
= SCAN_DELETE
;
1445 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1446 Key
.ScanCode
= SCAN_DELETE
;
1447 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1448 Key
.ScanCode
= SCAN_F4
;
1452 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1453 Key
.ScanCode
= SCAN_PAGE_UP
;
1457 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1458 Key
.ScanCode
= SCAN_F10
;
1461 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1462 Key
.ScanCode
= SCAN_PAGE_UP
;
1466 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1467 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1471 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1472 Key
.ScanCode
= SCAN_F9
;
1475 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1476 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1480 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1481 Key
.ScanCode
= SCAN_F1
;
1485 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1486 Key
.ScanCode
= SCAN_F2
;
1490 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1491 Key
.ScanCode
= SCAN_F3
;
1495 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1496 Key
.ScanCode
= SCAN_F5
;
1500 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1501 Key
.ScanCode
= SCAN_F6
;
1505 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1506 Key
.ScanCode
= SCAN_F7
;
1510 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1511 Key
.ScanCode
= SCAN_F8
;
1519 if (Key
.ScanCode
!= SCAN_NULL
) {
1520 Key
.UnicodeChar
= 0;
1521 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1522 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1523 UnicodeToEfiKeyFlushState (TerminalDevice
);
1527 UnicodeToEfiKeyFlushState (TerminalDevice
);
1534 // Invalid state. This should never happen.
1538 UnicodeToEfiKeyFlushState (TerminalDevice
);
1543 if (UnicodeChar
== ESC
) {
1544 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1547 if (UnicodeChar
== CSI
) {
1548 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1551 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1552 Status
= gBS
->SetTimer(
1553 TerminalDevice
->TwoSecondTimeOut
,
1557 ASSERT_EFI_ERROR (Status
);
1561 if (SetDefaultResetState
) {
1562 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1565 if (UnicodeChar
== DEL
) {
1566 Key
.ScanCode
= SCAN_DELETE
;
1567 Key
.UnicodeChar
= 0;
1569 Key
.ScanCode
= SCAN_NULL
;
1570 Key
.UnicodeChar
= UnicodeChar
;
1573 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);