2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2011, 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 EFI_HANDLE
*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
->NotifyHandle
;
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 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
372 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
373 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
375 *NotifyHandle
= NewNotify
->NotifyHandle
;
382 Remove a registered notification function from a particular keystroke.
384 @param This Protocol instance pointer.
385 @param NotificationHandle The handle of the notification function being
388 @retval EFI_SUCCESS The notification function was unregistered
390 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
395 TerminalConInUnregisterKeyNotify (
396 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
397 IN EFI_HANDLE NotificationHandle
400 TERMINAL_DEV
*TerminalDevice
;
402 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
403 LIST_ENTRY
*NotifyList
;
405 if (NotificationHandle
== NULL
) {
406 return EFI_INVALID_PARAMETER
;
409 if (((TERMINAL_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
410 return EFI_INVALID_PARAMETER
;
413 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
415 NotifyList
= &TerminalDevice
->NotifyList
;
416 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
419 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
421 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
423 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
425 // Remove the notification function from NotifyList and free resources
427 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
429 gBS
->FreePool (CurrentNotify
);
435 // Can not find the matching entry in database.
437 return EFI_INVALID_PARAMETER
;
441 Translate raw data into Unicode (according to different encode), and
442 translate Unicode into key information. (according to different standard).
444 @param TerminalDevice Terminal driver private structure.
448 TranslateRawDataToEfiKey (
449 IN TERMINAL_DEV
*TerminalDevice
452 switch (TerminalDevice
->TerminalType
) {
457 AnsiRawDataToUnicode (TerminalDevice
);
458 UnicodeToEfiKey (TerminalDevice
);
463 // Process all the raw data in the RawFIFO,
464 // put the processed key into UnicodeFIFO.
466 VTUTF8RawDataToUnicode (TerminalDevice
);
469 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
470 // then put into EfiKeyFIFO.
472 UnicodeToEfiKey (TerminalDevice
);
479 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
480 Signal the event if there is key available
482 @param Event Indicates the event that invoke this function.
483 @param Context Indicates the calling context.
488 TerminalConInWaitForKey (
494 // Someone is waiting on the keystroke event, if there's
495 // a key pending, signal the event
497 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
499 gBS
->SignalEvent (Event
);
504 Timer handler to poll the key from serial.
506 @param Event Indicates the event that invoke this function.
507 @param Context Indicates the calling context.
511 TerminalConInTimerHandler (
517 TERMINAL_DEV
*TerminalDevice
;
520 EFI_SERIAL_IO_MODE
*Mode
;
521 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
522 UINTN SerialInTimeOut
;
524 TerminalDevice
= (TERMINAL_DEV
*) Context
;
526 SerialIo
= TerminalDevice
->SerialIo
;
527 if (SerialIo
== NULL
) {
531 // if current timeout value for serial device is not identical with
532 // the value saved in TERMINAL_DEV structure, then recalculate the
533 // timeout value again and set serial attribute according to this value.
535 Mode
= SerialIo
->Mode
;
536 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
539 if (Mode
->BaudRate
!= 0) {
541 // According to BAUD rate to calculate the timeout value.
543 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
546 Status
= SerialIo
->SetAttributes (
549 Mode
->ReceiveFifoDepth
,
550 (UINT32
) SerialInTimeOut
,
551 (EFI_PARITY_TYPE
) (Mode
->Parity
),
552 (UINT8
) Mode
->DataBits
,
553 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
556 if (EFI_ERROR (Status
)) {
557 TerminalDevice
->SerialInTimeOut
= 0;
559 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
563 // Check whether serial buffer is empty.
565 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
567 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0) {
569 // Fetch all the keys in the serial buffer,
570 // and insert the byte stream into RawFIFO.
572 while (!IsRawFiFoFull (TerminalDevice
)) {
574 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
576 if (EFI_ERROR (Status
)) {
577 if (Status
== EFI_DEVICE_ERROR
) {
578 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
579 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
580 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
581 TerminalDevice
->DevicePath
587 RawFiFoInsertOneKey (TerminalDevice
, Input
);
592 // Translate all the raw data in RawFIFO into EFI Key,
593 // according to different terminal type supported.
595 TranslateRawDataToEfiKey (TerminalDevice
);
599 Get one key out of serial buffer.
601 @param SerialIo Serial I/O protocol attached to the serial device.
602 @param Output The fetched key.
604 @retval EFI_NOT_READY If serial buffer is empty.
605 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
606 @retval EFI_SUCCESS If reading serial buffer successfully, put
607 the fetched key to the parameter output.
611 GetOneKeyFromSerial (
612 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
623 // Read one key from serial I/O device.
625 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
627 if (EFI_ERROR (Status
)) {
629 if (Status
== EFI_TIMEOUT
) {
630 return EFI_NOT_READY
;
633 return EFI_DEVICE_ERROR
;
638 return EFI_NOT_READY
;
645 Insert one byte raw data into the Raw Data FIFO.
647 @param TerminalDevice Terminal driver private structure.
648 @param Input The key will be input.
650 @retval TRUE If insert successfully.
651 @retval FLASE If Raw Data buffer is full before key insertion,
656 RawFiFoInsertOneKey (
657 TERMINAL_DEV
*TerminalDevice
,
663 Tail
= TerminalDevice
->RawFiFo
->Tail
;
665 if (IsRawFiFoFull (TerminalDevice
)) {
672 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
674 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
680 Remove one pre-fetched key out of the Raw Data FIFO.
682 @param TerminalDevice Terminal driver private structure.
683 @param Output The key will be removed.
685 @retval TRUE If insert successfully.
686 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
690 RawFiFoRemoveOneKey (
691 TERMINAL_DEV
*TerminalDevice
,
697 Head
= TerminalDevice
->RawFiFo
->Head
;
699 if (IsRawFiFoEmpty (TerminalDevice
)) {
707 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
709 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
715 Clarify whether Raw Data FIFO buffer is empty.
717 @param TerminalDevice Terminal driver private structure
719 @retval TRUE If Raw Data FIFO buffer is empty.
720 @retval FLASE If Raw Data FIFO buffer is not empty.
725 TERMINAL_DEV
*TerminalDevice
728 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
736 Clarify whether Raw Data FIFO buffer is full.
738 @param TerminalDevice Terminal driver private structure
740 @retval TRUE If Raw Data FIFO buffer is full.
741 @retval FLASE If Raw Data FIFO buffer is not full.
746 TERMINAL_DEV
*TerminalDevice
752 Tail
= TerminalDevice
->RawFiFo
->Tail
;
753 Head
= TerminalDevice
->RawFiFo
->Head
;
755 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
764 Insert one pre-fetched key into the FIFO buffer.
766 @param TerminalDevice Terminal driver private structure.
767 @param Key The key will be input.
769 @retval TRUE If insert successfully.
770 @retval FLASE If FIFO buffer is full before key insertion,
775 EfiKeyFiFoInsertOneKey (
776 TERMINAL_DEV
*TerminalDevice
,
782 LIST_ENTRY
*NotifyList
;
783 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
784 EFI_KEY_DATA KeyData
;
786 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
788 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
789 KeyData
.KeyState
.KeyShiftState
= 0;
790 KeyData
.KeyState
.KeyToggleState
= 0;
793 // Invoke notification functions if exist
795 NotifyList
= &TerminalDevice
->NotifyList
;
796 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
799 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
801 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
803 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
804 CurrentNotify
->KeyNotificationFn (&KeyData
);
807 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
809 // Efi Key FIFO is full
814 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
816 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
822 Remove one pre-fetched key out of the FIFO buffer.
824 @param TerminalDevice Terminal driver private structure.
825 @param Output The key will be removed.
827 @retval TRUE If insert successfully.
828 @retval FLASE If FIFO buffer is empty before remove operation.
832 EfiKeyFiFoRemoveOneKey (
833 TERMINAL_DEV
*TerminalDevice
,
834 EFI_INPUT_KEY
*Output
839 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
840 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
842 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
846 Output
->ScanCode
= SCAN_NULL
;
847 Output
->UnicodeChar
= 0;
851 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
853 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
859 Clarify whether FIFO buffer is empty.
861 @param TerminalDevice Terminal driver private structure
863 @retval TRUE If FIFO buffer is empty.
864 @retval FLASE If FIFO buffer is not empty.
869 TERMINAL_DEV
*TerminalDevice
872 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
880 Clarify whether FIFO buffer is full.
882 @param TerminalDevice Terminal driver private structure
884 @retval TRUE If FIFO buffer is full.
885 @retval FLASE If FIFO buffer is not full.
890 TERMINAL_DEV
*TerminalDevice
896 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
897 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
899 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
908 Insert one pre-fetched key into the Unicode FIFO buffer.
910 @param TerminalDevice Terminal driver private structure.
911 @param Input The key will be input.
913 @retval TRUE If insert successfully.
914 @retval FLASE If Unicode FIFO buffer is full before key insertion,
919 UnicodeFiFoInsertOneKey (
920 TERMINAL_DEV
*TerminalDevice
,
926 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
927 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
930 if (IsUnicodeFiFoFull (TerminalDevice
)) {
932 // Unicode FIFO is full
937 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
939 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
945 Remove one pre-fetched key out of the Unicode FIFO buffer.
947 @param TerminalDevice Terminal driver private structure.
948 @param Output The key will be removed.
950 @retval TRUE If insert successfully.
951 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
955 UnicodeFiFoRemoveOneKey (
956 TERMINAL_DEV
*TerminalDevice
,
962 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
963 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
965 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
973 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
975 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
981 Clarify whether Unicode FIFO buffer is empty.
983 @param TerminalDevice Terminal driver private structure
985 @retval TRUE If Unicode FIFO buffer is empty.
986 @retval FLASE If Unicode FIFO buffer is not empty.
991 TERMINAL_DEV
*TerminalDevice
994 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1002 Clarify whether Unicode FIFO buffer is full.
1004 @param TerminalDevice Terminal driver private structure
1006 @retval TRUE If Unicode FIFO buffer is full.
1007 @retval FLASE If Unicode FIFO buffer is not full.
1012 TERMINAL_DEV
*TerminalDevice
1018 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1019 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1021 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1030 Count Unicode FIFO buffer.
1032 @param TerminalDevice Terminal driver private structure
1034 @return The count in bytes of Unicode FIFO.
1038 UnicodeFiFoGetKeyCount (
1039 TERMINAL_DEV
*TerminalDevice
1045 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1046 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1049 return (UINT8
) (Tail
- Head
);
1051 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1056 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1058 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1062 UnicodeToEfiKeyFlushState (
1063 IN TERMINAL_DEV
*TerminalDevice
1069 InputState
= TerminalDevice
->InputState
;
1071 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1075 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1076 Key
.ScanCode
= SCAN_ESC
;
1077 Key
.UnicodeChar
= 0;
1078 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1081 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1082 Key
.ScanCode
= SCAN_NULL
;
1083 Key
.UnicodeChar
= CSI
;
1084 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1087 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1088 Key
.ScanCode
= SCAN_NULL
;
1089 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1090 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1093 if ((InputState
& INPUT_STATE_O
) != 0) {
1094 Key
.ScanCode
= SCAN_NULL
;
1095 Key
.UnicodeChar
= 'O';
1096 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1099 if ((InputState
& INPUT_STATE_2
) != 0) {
1100 Key
.ScanCode
= SCAN_NULL
;
1101 Key
.UnicodeChar
= '2';
1102 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1106 // Cancel the timer.
1109 TerminalDevice
->TwoSecondTimeOut
,
1114 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1119 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1120 can be read through the Simple Input Protocol.
1122 The table below shows the keyboard input mappings that this function supports.
1123 If the ESC sequence listed in one of the columns is presented, then it is translated
1124 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1125 key strokes are converted into EFI Keys.
1127 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1128 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1129 converted into EFI Keys.
1130 There is one special input sequence that will force the system to reset.
1131 This is ESC R ESC r ESC R.
1133 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1134 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1135 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1137 Symbols used in table below
1138 ===========================
1144 +=========+======+===========+==========+==========+
1145 | | EFI | UEFI 2.0 | | |
1146 | | Scan | | VT100+ | |
1147 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1148 +=========+======+===========+==========+==========+
1149 | NULL | 0x00 | | | |
1150 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1151 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1152 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1153 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1154 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1155 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1156 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1157 | | | ESC [ L | | ESC [ L |
1158 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1159 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1161 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1163 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1164 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1165 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1166 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1167 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1168 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1169 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1170 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1171 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1172 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1173 | Escape | 0x17 | ESC | ESC | ESC |
1174 | F11 | 0x15 | | ESC ! | |
1175 | F12 | 0x16 | | ESC @ | |
1176 +=========+======+===========+==========+==========+
1180 ESC R ESC r ESC R = Reset System
1182 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1187 IN TERMINAL_DEV
*TerminalDevice
1191 EFI_STATUS TimerStatus
;
1194 BOOLEAN SetDefaultResetState
;
1196 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1198 if (!EFI_ERROR (TimerStatus
)) {
1199 UnicodeToEfiKeyFlushState (TerminalDevice
);
1200 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1203 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1205 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1207 // Check to see if the 2 seconds timer has expired
1209 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1210 if (!EFI_ERROR (TimerStatus
)) {
1211 UnicodeToEfiKeyFlushState (TerminalDevice
);
1212 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1217 // Fetch one Unicode character from the Unicode FIFO
1219 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1221 SetDefaultResetState
= TRUE
;
1223 switch (TerminalDevice
->InputState
) {
1224 case INPUT_STATE_DEFAULT
:
1228 case INPUT_STATE_ESC
:
1230 if (UnicodeChar
== LEFTOPENBRACKET
) {
1231 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1232 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1236 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1237 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1238 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1242 Key
.ScanCode
= SCAN_NULL
;
1244 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1245 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1246 switch (UnicodeChar
) {
1248 Key
.ScanCode
= SCAN_F1
;
1251 Key
.ScanCode
= SCAN_F2
;
1254 Key
.ScanCode
= SCAN_F3
;
1257 Key
.ScanCode
= SCAN_F4
;
1260 Key
.ScanCode
= SCAN_F5
;
1263 Key
.ScanCode
= SCAN_F6
;
1266 Key
.ScanCode
= SCAN_F7
;
1269 Key
.ScanCode
= SCAN_F8
;
1272 Key
.ScanCode
= SCAN_F9
;
1275 Key
.ScanCode
= SCAN_F10
;
1278 Key
.ScanCode
= SCAN_F11
;
1281 Key
.ScanCode
= SCAN_F12
;
1284 Key
.ScanCode
= SCAN_HOME
;
1287 Key
.ScanCode
= SCAN_END
;
1290 Key
.ScanCode
= SCAN_INSERT
;
1293 Key
.ScanCode
= SCAN_DELETE
;
1296 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1299 Key
.ScanCode
= SCAN_PAGE_UP
;
1306 switch (UnicodeChar
) {
1308 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1309 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1310 SetDefaultResetState
= FALSE
;
1311 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1312 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1314 Key
.ScanCode
= SCAN_NULL
;
1317 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1318 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1319 SetDefaultResetState
= FALSE
;
1321 Key
.ScanCode
= SCAN_NULL
;
1327 if (SetDefaultResetState
) {
1328 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1331 if (Key
.ScanCode
!= SCAN_NULL
) {
1332 Key
.UnicodeChar
= 0;
1333 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1334 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1335 UnicodeToEfiKeyFlushState (TerminalDevice
);
1339 UnicodeToEfiKeyFlushState (TerminalDevice
);
1343 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1345 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1347 Key
.ScanCode
= SCAN_NULL
;
1349 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1350 switch (UnicodeChar
) {
1352 Key
.ScanCode
= SCAN_F1
;
1355 Key
.ScanCode
= SCAN_F2
;
1358 Key
.ScanCode
= SCAN_F3
;
1361 Key
.ScanCode
= SCAN_F4
;
1364 Key
.ScanCode
= SCAN_F5
;
1367 Key
.ScanCode
= SCAN_F6
;
1370 Key
.ScanCode
= SCAN_F7
;
1373 Key
.ScanCode
= SCAN_F8
;
1376 Key
.ScanCode
= SCAN_F9
;
1379 Key
.ScanCode
= SCAN_F10
;
1386 if (Key
.ScanCode
!= SCAN_NULL
) {
1387 Key
.UnicodeChar
= 0;
1388 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1389 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1390 UnicodeToEfiKeyFlushState (TerminalDevice
);
1394 UnicodeToEfiKeyFlushState (TerminalDevice
);
1398 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1400 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1402 Key
.ScanCode
= SCAN_NULL
;
1404 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1405 TerminalDevice
->TerminalType
== VT100TYPE
||
1406 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1407 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1408 switch (UnicodeChar
) {
1410 Key
.ScanCode
= SCAN_UP
;
1413 Key
.ScanCode
= SCAN_DOWN
;
1416 Key
.ScanCode
= SCAN_RIGHT
;
1419 Key
.ScanCode
= SCAN_LEFT
;
1422 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1423 TerminalDevice
->TerminalType
== VT100TYPE
) {
1424 Key
.ScanCode
= SCAN_HOME
;
1428 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1429 Key
.ScanCode
= SCAN_END
;
1433 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1434 Key
.ScanCode
= SCAN_END
;
1439 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1440 TerminalDevice
->TerminalType
== VT100TYPE
) {
1441 Key
.ScanCode
= SCAN_INSERT
;
1445 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1446 Key
.ScanCode
= SCAN_DELETE
;
1450 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1451 Key
.ScanCode
= SCAN_DELETE
;
1452 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1453 Key
.ScanCode
= SCAN_F4
;
1457 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1458 Key
.ScanCode
= SCAN_PAGE_UP
;
1462 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1463 Key
.ScanCode
= SCAN_F10
;
1466 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1467 Key
.ScanCode
= SCAN_PAGE_UP
;
1471 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1472 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1476 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1477 Key
.ScanCode
= SCAN_F9
;
1480 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1481 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1485 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1486 Key
.ScanCode
= SCAN_F1
;
1490 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1491 Key
.ScanCode
= SCAN_F2
;
1495 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1496 Key
.ScanCode
= SCAN_F3
;
1500 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1501 Key
.ScanCode
= SCAN_F5
;
1505 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1506 Key
.ScanCode
= SCAN_F6
;
1510 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1511 Key
.ScanCode
= SCAN_F7
;
1515 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1516 Key
.ScanCode
= SCAN_F8
;
1524 if (Key
.ScanCode
!= SCAN_NULL
) {
1525 Key
.UnicodeChar
= 0;
1526 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1527 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1528 UnicodeToEfiKeyFlushState (TerminalDevice
);
1532 UnicodeToEfiKeyFlushState (TerminalDevice
);
1539 // Invalid state. This should never happen.
1543 UnicodeToEfiKeyFlushState (TerminalDevice
);
1548 if (UnicodeChar
== ESC
) {
1549 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1552 if (UnicodeChar
== CSI
) {
1553 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1556 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1557 Status
= gBS
->SetTimer(
1558 TerminalDevice
->TwoSecondTimeOut
,
1562 ASSERT_EFI_ERROR (Status
);
1566 if (SetDefaultResetState
) {
1567 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1570 if (UnicodeChar
== DEL
) {
1571 Key
.ScanCode
= SCAN_DELETE
;
1572 Key
.UnicodeChar
= 0;
1574 Key
.ScanCode
= SCAN_NULL
;
1575 Key
.UnicodeChar
= UnicodeChar
;
1578 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);