2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2013, 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
;
298 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
299 return EFI_UNSUPPORTED
;
307 Register a notification function for a particular keystroke for the input device.
309 @param This Protocol instance pointer.
310 @param KeyData A pointer to a buffer that is filled in with the
311 keystroke information data for the key that was
313 @param KeyNotificationFunction Points to the function to be called when the key
314 sequence is typed specified by KeyData.
315 @param NotifyHandle Points to the unique handle assigned to the
316 registered notification.
318 @retval EFI_SUCCESS The notification function was registered
320 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
322 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
327 TerminalConInRegisterKeyNotify (
328 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
329 IN EFI_KEY_DATA
*KeyData
,
330 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
331 OUT VOID
**NotifyHandle
334 TERMINAL_DEV
*TerminalDevice
;
335 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
337 LIST_ENTRY
*NotifyList
;
338 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
340 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
341 return EFI_INVALID_PARAMETER
;
344 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
347 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
349 NotifyList
= &TerminalDevice
->NotifyList
;
350 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
353 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
355 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
357 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
358 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
359 *NotifyHandle
= CurrentNotify
;
366 // Allocate resource to save the notification function
368 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
369 if (NewNotify
== NULL
) {
370 return EFI_OUT_OF_RESOURCES
;
373 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
374 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
375 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
376 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
378 *NotifyHandle
= NewNotify
;
385 Remove a registered notification function from a particular keystroke.
387 @param This Protocol instance pointer.
388 @param NotificationHandle The handle of the notification function being
391 @retval EFI_SUCCESS The notification function was unregistered
393 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
398 TerminalConInUnregisterKeyNotify (
399 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
400 IN VOID
*NotificationHandle
403 TERMINAL_DEV
*TerminalDevice
;
405 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
406 LIST_ENTRY
*NotifyList
;
408 if (NotificationHandle
== NULL
) {
409 return EFI_INVALID_PARAMETER
;
412 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
414 NotifyList
= &TerminalDevice
->NotifyList
;
415 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
418 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
420 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
422 if (CurrentNotify
== NotificationHandle
) {
424 // Remove the notification function from NotifyList and free resources
426 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
428 gBS
->FreePool (CurrentNotify
);
434 // Can not find the matching entry in database.
436 return EFI_INVALID_PARAMETER
;
440 Translate raw data into Unicode (according to different encode), and
441 translate Unicode into key information. (according to different standard).
443 @param TerminalDevice Terminal driver private structure.
447 TranslateRawDataToEfiKey (
448 IN TERMINAL_DEV
*TerminalDevice
451 switch (TerminalDevice
->TerminalType
) {
456 AnsiRawDataToUnicode (TerminalDevice
);
457 UnicodeToEfiKey (TerminalDevice
);
462 // Process all the raw data in the RawFIFO,
463 // put the processed key into UnicodeFIFO.
465 VTUTF8RawDataToUnicode (TerminalDevice
);
468 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
469 // then put into EfiKeyFIFO.
471 UnicodeToEfiKey (TerminalDevice
);
478 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
479 Signal the event if there is key available
481 @param Event Indicates the event that invoke this function.
482 @param Context Indicates the calling context.
487 TerminalConInWaitForKey (
493 // Someone is waiting on the keystroke event, if there's
494 // a key pending, signal the event
496 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
498 gBS
->SignalEvent (Event
);
503 Timer handler to poll the key from serial.
505 @param Event Indicates the event that invoke this function.
506 @param Context Indicates the calling context.
510 TerminalConInTimerHandler (
516 TERMINAL_DEV
*TerminalDevice
;
519 EFI_SERIAL_IO_MODE
*Mode
;
520 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
521 UINTN SerialInTimeOut
;
523 TerminalDevice
= (TERMINAL_DEV
*) Context
;
525 SerialIo
= TerminalDevice
->SerialIo
;
526 if (SerialIo
== NULL
) {
530 // if current timeout value for serial device is not identical with
531 // the value saved in TERMINAL_DEV structure, then recalculate the
532 // timeout value again and set serial attribute according to this value.
534 Mode
= SerialIo
->Mode
;
535 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
538 if (Mode
->BaudRate
!= 0) {
540 // According to BAUD rate to calculate the timeout value.
542 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
545 Status
= SerialIo
->SetAttributes (
548 Mode
->ReceiveFifoDepth
,
549 (UINT32
) SerialInTimeOut
,
550 (EFI_PARITY_TYPE
) (Mode
->Parity
),
551 (UINT8
) Mode
->DataBits
,
552 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
555 if (EFI_ERROR (Status
)) {
556 TerminalDevice
->SerialInTimeOut
= 0;
558 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
562 // Check whether serial buffer is empty.
564 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
566 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0) {
568 // Fetch all the keys in the serial buffer,
569 // and insert the byte stream into RawFIFO.
571 while (!IsRawFiFoFull (TerminalDevice
)) {
573 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
575 if (EFI_ERROR (Status
)) {
576 if (Status
== EFI_DEVICE_ERROR
) {
577 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
578 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
579 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
580 TerminalDevice
->DevicePath
586 RawFiFoInsertOneKey (TerminalDevice
, Input
);
591 // Translate all the raw data in RawFIFO into EFI Key,
592 // according to different terminal type supported.
594 TranslateRawDataToEfiKey (TerminalDevice
);
598 Get one key out of serial buffer.
600 @param SerialIo Serial I/O protocol attached to the serial device.
601 @param Output The fetched key.
603 @retval EFI_NOT_READY If serial buffer is empty.
604 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
605 @retval EFI_SUCCESS If reading serial buffer successfully, put
606 the fetched key to the parameter output.
610 GetOneKeyFromSerial (
611 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
622 // Read one key from serial I/O device.
624 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
626 if (EFI_ERROR (Status
)) {
628 if (Status
== EFI_TIMEOUT
) {
629 return EFI_NOT_READY
;
632 return EFI_DEVICE_ERROR
;
637 return EFI_NOT_READY
;
644 Insert one byte raw data into the Raw Data FIFO.
646 @param TerminalDevice Terminal driver private structure.
647 @param Input The key will be input.
649 @retval TRUE If insert successfully.
650 @retval FLASE If Raw Data buffer is full before key insertion,
655 RawFiFoInsertOneKey (
656 TERMINAL_DEV
*TerminalDevice
,
662 Tail
= TerminalDevice
->RawFiFo
->Tail
;
664 if (IsRawFiFoFull (TerminalDevice
)) {
671 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
673 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
679 Remove one pre-fetched key out of the Raw Data FIFO.
681 @param TerminalDevice Terminal driver private structure.
682 @param Output The key will be removed.
684 @retval TRUE If insert successfully.
685 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
689 RawFiFoRemoveOneKey (
690 TERMINAL_DEV
*TerminalDevice
,
696 Head
= TerminalDevice
->RawFiFo
->Head
;
698 if (IsRawFiFoEmpty (TerminalDevice
)) {
706 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
708 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
714 Clarify whether Raw Data FIFO buffer is empty.
716 @param TerminalDevice Terminal driver private structure
718 @retval TRUE If Raw Data FIFO buffer is empty.
719 @retval FLASE If Raw Data FIFO buffer is not empty.
724 TERMINAL_DEV
*TerminalDevice
727 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
735 Clarify whether Raw Data FIFO buffer is full.
737 @param TerminalDevice Terminal driver private structure
739 @retval TRUE If Raw Data FIFO buffer is full.
740 @retval FLASE If Raw Data FIFO buffer is not full.
745 TERMINAL_DEV
*TerminalDevice
751 Tail
= TerminalDevice
->RawFiFo
->Tail
;
752 Head
= TerminalDevice
->RawFiFo
->Head
;
754 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
763 Insert one pre-fetched key into the FIFO buffer.
765 @param TerminalDevice Terminal driver private structure.
766 @param Key The key will be input.
768 @retval TRUE If insert successfully.
769 @retval FLASE If FIFO buffer is full before key insertion,
774 EfiKeyFiFoInsertOneKey (
775 TERMINAL_DEV
*TerminalDevice
,
781 LIST_ENTRY
*NotifyList
;
782 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
783 EFI_KEY_DATA KeyData
;
785 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
787 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
788 KeyData
.KeyState
.KeyShiftState
= 0;
789 KeyData
.KeyState
.KeyToggleState
= 0;
792 // Invoke notification functions if exist
794 NotifyList
= &TerminalDevice
->NotifyList
;
795 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
798 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
800 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
802 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
803 CurrentNotify
->KeyNotificationFn (&KeyData
);
806 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
808 // Efi Key FIFO is full
813 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
815 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
821 Remove one pre-fetched key out of the FIFO buffer.
823 @param TerminalDevice Terminal driver private structure.
824 @param Output The key will be removed.
826 @retval TRUE If insert successfully.
827 @retval FLASE If FIFO buffer is empty before remove operation.
831 EfiKeyFiFoRemoveOneKey (
832 TERMINAL_DEV
*TerminalDevice
,
833 EFI_INPUT_KEY
*Output
838 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
839 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
841 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
845 Output
->ScanCode
= SCAN_NULL
;
846 Output
->UnicodeChar
= 0;
850 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
852 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
858 Clarify whether FIFO buffer is empty.
860 @param TerminalDevice Terminal driver private structure
862 @retval TRUE If FIFO buffer is empty.
863 @retval FLASE If FIFO buffer is not empty.
868 TERMINAL_DEV
*TerminalDevice
871 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
879 Clarify whether FIFO buffer is full.
881 @param TerminalDevice Terminal driver private structure
883 @retval TRUE If FIFO buffer is full.
884 @retval FLASE If FIFO buffer is not full.
889 TERMINAL_DEV
*TerminalDevice
895 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
896 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
898 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
907 Insert one pre-fetched key into the Unicode FIFO buffer.
909 @param TerminalDevice Terminal driver private structure.
910 @param Input The key will be input.
912 @retval TRUE If insert successfully.
913 @retval FLASE If Unicode FIFO buffer is full before key insertion,
918 UnicodeFiFoInsertOneKey (
919 TERMINAL_DEV
*TerminalDevice
,
925 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
926 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
929 if (IsUnicodeFiFoFull (TerminalDevice
)) {
931 // Unicode FIFO is full
936 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
938 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
944 Remove one pre-fetched key out of the Unicode FIFO buffer.
946 @param TerminalDevice Terminal driver private structure.
947 @param Output The key will be removed.
949 @retval TRUE If insert successfully.
950 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
954 UnicodeFiFoRemoveOneKey (
955 TERMINAL_DEV
*TerminalDevice
,
961 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
962 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
964 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
972 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
974 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
980 Clarify whether Unicode FIFO buffer is empty.
982 @param TerminalDevice Terminal driver private structure
984 @retval TRUE If Unicode FIFO buffer is empty.
985 @retval FLASE If Unicode FIFO buffer is not empty.
990 TERMINAL_DEV
*TerminalDevice
993 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1001 Clarify whether Unicode FIFO buffer is full.
1003 @param TerminalDevice Terminal driver private structure
1005 @retval TRUE If Unicode FIFO buffer is full.
1006 @retval FLASE If Unicode FIFO buffer is not full.
1011 TERMINAL_DEV
*TerminalDevice
1017 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1018 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1020 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1029 Count Unicode FIFO buffer.
1031 @param TerminalDevice Terminal driver private structure
1033 @return The count in bytes of Unicode FIFO.
1037 UnicodeFiFoGetKeyCount (
1038 TERMINAL_DEV
*TerminalDevice
1044 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1045 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1048 return (UINT8
) (Tail
- Head
);
1050 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1055 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1057 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1061 UnicodeToEfiKeyFlushState (
1062 IN TERMINAL_DEV
*TerminalDevice
1068 InputState
= TerminalDevice
->InputState
;
1070 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1074 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1075 Key
.ScanCode
= SCAN_ESC
;
1076 Key
.UnicodeChar
= 0;
1077 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1080 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1081 Key
.ScanCode
= SCAN_NULL
;
1082 Key
.UnicodeChar
= CSI
;
1083 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1086 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1087 Key
.ScanCode
= SCAN_NULL
;
1088 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1089 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1092 if ((InputState
& INPUT_STATE_O
) != 0) {
1093 Key
.ScanCode
= SCAN_NULL
;
1094 Key
.UnicodeChar
= 'O';
1095 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1098 if ((InputState
& INPUT_STATE_2
) != 0) {
1099 Key
.ScanCode
= SCAN_NULL
;
1100 Key
.UnicodeChar
= '2';
1101 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1105 // Cancel the timer.
1108 TerminalDevice
->TwoSecondTimeOut
,
1113 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1118 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1119 can be read through the Simple Input Protocol.
1121 The table below shows the keyboard input mappings that this function supports.
1122 If the ESC sequence listed in one of the columns is presented, then it is translated
1123 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1124 key strokes are converted into EFI Keys.
1126 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1127 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1128 converted into EFI Keys.
1129 There is one special input sequence that will force the system to reset.
1130 This is ESC R ESC r ESC R.
1132 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1133 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1134 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1136 Symbols used in table below
1137 ===========================
1143 +=========+======+===========+==========+==========+
1144 | | EFI | UEFI 2.0 | | |
1145 | | Scan | | VT100+ | |
1146 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1147 +=========+======+===========+==========+==========+
1148 | NULL | 0x00 | | | |
1149 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1150 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1151 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1152 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1153 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1154 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1155 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1156 | | | ESC [ L | | ESC [ L |
1157 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1158 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1160 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1162 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1163 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1164 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1165 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1166 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1167 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1168 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1169 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1170 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1171 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1172 | Escape | 0x17 | ESC | ESC | ESC |
1173 | F11 | 0x15 | | ESC ! | |
1174 | F12 | 0x16 | | ESC @ | |
1175 +=========+======+===========+==========+==========+
1179 ESC R ESC r ESC R = Reset System
1181 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1186 IN TERMINAL_DEV
*TerminalDevice
1190 EFI_STATUS TimerStatus
;
1193 BOOLEAN SetDefaultResetState
;
1195 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1197 if (!EFI_ERROR (TimerStatus
)) {
1198 UnicodeToEfiKeyFlushState (TerminalDevice
);
1199 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1202 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1204 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1206 // Check to see if the 2 seconds timer has expired
1208 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1209 if (!EFI_ERROR (TimerStatus
)) {
1210 UnicodeToEfiKeyFlushState (TerminalDevice
);
1211 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1216 // Fetch one Unicode character from the Unicode FIFO
1218 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1220 SetDefaultResetState
= TRUE
;
1222 switch (TerminalDevice
->InputState
) {
1223 case INPUT_STATE_DEFAULT
:
1227 case INPUT_STATE_ESC
:
1229 if (UnicodeChar
== LEFTOPENBRACKET
) {
1230 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1231 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1235 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1236 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1237 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1241 Key
.ScanCode
= SCAN_NULL
;
1243 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1244 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1245 switch (UnicodeChar
) {
1247 Key
.ScanCode
= SCAN_F1
;
1250 Key
.ScanCode
= SCAN_F2
;
1253 Key
.ScanCode
= SCAN_F3
;
1256 Key
.ScanCode
= SCAN_F4
;
1259 Key
.ScanCode
= SCAN_F5
;
1262 Key
.ScanCode
= SCAN_F6
;
1265 Key
.ScanCode
= SCAN_F7
;
1268 Key
.ScanCode
= SCAN_F8
;
1271 Key
.ScanCode
= SCAN_F9
;
1274 Key
.ScanCode
= SCAN_F10
;
1277 Key
.ScanCode
= SCAN_F11
;
1280 Key
.ScanCode
= SCAN_F12
;
1283 Key
.ScanCode
= SCAN_HOME
;
1286 Key
.ScanCode
= SCAN_END
;
1289 Key
.ScanCode
= SCAN_INSERT
;
1292 Key
.ScanCode
= SCAN_DELETE
;
1295 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1298 Key
.ScanCode
= SCAN_PAGE_UP
;
1305 switch (UnicodeChar
) {
1307 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1308 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1309 SetDefaultResetState
= FALSE
;
1310 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1311 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1313 Key
.ScanCode
= SCAN_NULL
;
1316 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1317 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1318 SetDefaultResetState
= FALSE
;
1320 Key
.ScanCode
= SCAN_NULL
;
1326 if (SetDefaultResetState
) {
1327 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1330 if (Key
.ScanCode
!= SCAN_NULL
) {
1331 Key
.UnicodeChar
= 0;
1332 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1333 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1334 UnicodeToEfiKeyFlushState (TerminalDevice
);
1338 UnicodeToEfiKeyFlushState (TerminalDevice
);
1342 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1344 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1346 Key
.ScanCode
= SCAN_NULL
;
1348 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1349 switch (UnicodeChar
) {
1351 Key
.ScanCode
= SCAN_F1
;
1354 Key
.ScanCode
= SCAN_F2
;
1357 Key
.ScanCode
= SCAN_F3
;
1360 Key
.ScanCode
= SCAN_F4
;
1363 Key
.ScanCode
= SCAN_F5
;
1366 Key
.ScanCode
= SCAN_F6
;
1369 Key
.ScanCode
= SCAN_F7
;
1372 Key
.ScanCode
= SCAN_F8
;
1375 Key
.ScanCode
= SCAN_F9
;
1378 Key
.ScanCode
= SCAN_F10
;
1385 if (Key
.ScanCode
!= SCAN_NULL
) {
1386 Key
.UnicodeChar
= 0;
1387 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1388 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1389 UnicodeToEfiKeyFlushState (TerminalDevice
);
1393 UnicodeToEfiKeyFlushState (TerminalDevice
);
1397 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1399 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1401 Key
.ScanCode
= SCAN_NULL
;
1403 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1404 TerminalDevice
->TerminalType
== VT100TYPE
||
1405 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1406 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1407 switch (UnicodeChar
) {
1409 Key
.ScanCode
= SCAN_UP
;
1412 Key
.ScanCode
= SCAN_DOWN
;
1415 Key
.ScanCode
= SCAN_RIGHT
;
1418 Key
.ScanCode
= SCAN_LEFT
;
1421 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1422 TerminalDevice
->TerminalType
== VT100TYPE
) {
1423 Key
.ScanCode
= SCAN_HOME
;
1427 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1428 Key
.ScanCode
= SCAN_END
;
1432 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1433 Key
.ScanCode
= SCAN_END
;
1438 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1439 TerminalDevice
->TerminalType
== VT100TYPE
) {
1440 Key
.ScanCode
= SCAN_INSERT
;
1444 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1445 Key
.ScanCode
= SCAN_DELETE
;
1449 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1450 Key
.ScanCode
= SCAN_DELETE
;
1451 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1452 Key
.ScanCode
= SCAN_F4
;
1456 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1457 Key
.ScanCode
= SCAN_PAGE_UP
;
1461 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1462 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
;
1481 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1482 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1486 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1487 Key
.ScanCode
= SCAN_F1
;
1491 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1492 Key
.ScanCode
= SCAN_F2
;
1496 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1497 Key
.ScanCode
= SCAN_F3
;
1501 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1502 Key
.ScanCode
= SCAN_F5
;
1506 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1507 Key
.ScanCode
= SCAN_F6
;
1511 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1512 Key
.ScanCode
= SCAN_F7
;
1516 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1517 Key
.ScanCode
= SCAN_F8
;
1525 if (Key
.ScanCode
!= SCAN_NULL
) {
1526 Key
.UnicodeChar
= 0;
1527 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1528 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1529 UnicodeToEfiKeyFlushState (TerminalDevice
);
1533 UnicodeToEfiKeyFlushState (TerminalDevice
);
1540 // Invalid state. This should never happen.
1544 UnicodeToEfiKeyFlushState (TerminalDevice
);
1549 if (UnicodeChar
== ESC
) {
1550 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1553 if (UnicodeChar
== CSI
) {
1554 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1557 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1558 Status
= gBS
->SetTimer(
1559 TerminalDevice
->TwoSecondTimeOut
,
1563 ASSERT_EFI_ERROR (Status
);
1567 if (SetDefaultResetState
) {
1568 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1571 if (UnicodeChar
== DEL
) {
1572 Key
.ScanCode
= SCAN_DELETE
;
1573 Key
.UnicodeChar
= 0;
1575 Key
.ScanCode
= SCAN_NULL
;
1576 Key
.UnicodeChar
= UnicodeChar
;
1579 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);