2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2010, Intel Corporation. <BR>
5 All rights reserved. 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_DEVICE_ERROR The keystroke information was not returned due
31 @retval EFI_INVALID_PARAMETER KeyData is NULL.
36 IN TERMINAL_DEV
*TerminalDevice
,
37 OUT EFI_KEY_DATA
*KeyData
42 LIST_ENTRY
*NotifyList
;
43 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
45 if (KeyData
== NULL
) {
46 return EFI_INVALID_PARAMETER
;
50 // Initialize *Key to nonsense value.
52 KeyData
->Key
.ScanCode
= SCAN_NULL
;
53 KeyData
->Key
.UnicodeChar
= 0;
55 Status
= TerminalConInCheckForKey (&TerminalDevice
->SimpleInput
);
56 if (EFI_ERROR (Status
)) {
60 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
64 KeyData
->KeyState
.KeyShiftState
= 0;
65 KeyData
->KeyState
.KeyToggleState
= 0;
68 // Invoke notification functions if exist
70 NotifyList
= &TerminalDevice
->NotifyList
;
71 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
74 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
76 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
78 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
79 CurrentNotify
->KeyNotificationFn (KeyData
);
88 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
89 This driver only perform dependent serial device reset regardless of
90 the value of ExtendeVerification
92 @param This Indicates the calling context.
93 @param ExtendedVerification Skip by this driver.
95 @retval EFI_SUCCESS The reset operation succeeds.
96 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
102 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
103 IN BOOLEAN ExtendedVerification
107 TERMINAL_DEV
*TerminalDevice
;
109 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
112 // Report progress code here
114 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
116 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
117 TerminalDevice
->DevicePath
120 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
123 // Make all the internal buffer empty for keys
125 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
126 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
127 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
129 if (EFI_ERROR (Status
)) {
130 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
131 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
132 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
133 TerminalDevice
->DevicePath
141 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
143 @param This Indicates the calling context.
144 @param Key A pointer to a buffer that is filled in with the
145 keystroke information for the key that was sent
148 @retval EFI_SUCCESS The keystroke information is returned successfully.
149 @retval EFI_NOT_READY There is no keystroke data available.
150 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
155 TerminalConInReadKeyStroke (
156 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
157 OUT EFI_INPUT_KEY
*Key
160 TERMINAL_DEV
*TerminalDevice
;
162 EFI_KEY_DATA KeyData
;
165 // get TERMINAL_DEV from "This" parameter.
167 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
169 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
170 if (EFI_ERROR (Status
)) {
174 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
181 Check if the key already has been registered.
183 If both RegsiteredData and InputData is NULL, then ASSERT().
185 @param RegsiteredData A pointer to a buffer that is filled in with the
186 keystroke state data for the key that was
188 @param InputData A pointer to a buffer that is filled in with the
189 keystroke state data for the key that was
192 @retval TRUE Key be pressed matches a registered key.
193 @retval FLASE Match failed.
198 IN EFI_KEY_DATA
*RegsiteredData
,
199 IN EFI_KEY_DATA
*InputData
202 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
204 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
205 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
215 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
216 Signal the event if there is key available
218 @param Event Indicates the event that invoke this function.
219 @param Context Indicates the calling context.
224 TerminalConInWaitForKeyEx (
229 TERMINAL_DEV
*TerminalDevice
;
231 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context
);
233 TerminalConInWaitForKey (Event
, &TerminalDevice
->SimpleInput
);
238 // Simple Text Input Ex protocol functions
242 Reset the input device and optionally run diagnostics
244 @param This Protocol instance pointer.
245 @param ExtendedVerification Driver may perform diagnostics on reset.
247 @retval EFI_SUCCESS The device was reset.
248 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
254 TerminalConInResetEx (
255 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
256 IN BOOLEAN ExtendedVerification
260 TERMINAL_DEV
*TerminalDevice
;
262 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
264 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
265 if (EFI_ERROR (Status
)) {
266 return EFI_DEVICE_ERROR
;
275 Reads the next keystroke from the input device. The WaitForKey Event can
276 be used to test for existence of a keystroke via WaitForEvent () call.
278 @param This Protocol instance pointer.
279 @param KeyData A pointer to a buffer that is filled in with the
280 keystroke state data for the key that was
283 @retval EFI_SUCCESS The keystroke information was returned.
284 @retval EFI_NOT_READY There was no keystroke data available.
285 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
287 @retval EFI_INVALID_PARAMETER KeyData is NULL.
292 TerminalConInReadKeyStrokeEx (
293 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
294 OUT EFI_KEY_DATA
*KeyData
297 TERMINAL_DEV
*TerminalDevice
;
299 if (KeyData
== NULL
) {
300 return EFI_INVALID_PARAMETER
;
303 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
305 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
311 Set certain state for the input device.
313 @param This Protocol instance pointer.
314 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
315 state for the input device.
317 @retval EFI_SUCCESS The device state was set successfully.
318 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
319 could not have the setting adjusted.
320 @retval EFI_UNSUPPORTED The device does not have the ability to set its
322 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
327 TerminalConInSetState (
328 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
329 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
332 if (KeyToggleState
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
341 Register a notification function for a particular keystroke for the input device.
343 @param This Protocol instance pointer.
344 @param KeyData A pointer to a buffer that is filled in with the
345 keystroke information data for the key that was
347 @param KeyNotificationFunction Points to the function to be called when the key
348 sequence is typed specified by KeyData.
349 @param NotifyHandle Points to the unique handle assigned to the
350 registered notification.
352 @retval EFI_SUCCESS The notification function was registered
354 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
356 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
361 TerminalConInRegisterKeyNotify (
362 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
363 IN EFI_KEY_DATA
*KeyData
,
364 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
365 OUT EFI_HANDLE
*NotifyHandle
368 TERMINAL_DEV
*TerminalDevice
;
369 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
371 LIST_ENTRY
*NotifyList
;
372 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
374 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
375 return EFI_INVALID_PARAMETER
;
378 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
381 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
383 NotifyList
= &TerminalDevice
->NotifyList
;
384 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
387 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
389 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
391 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
392 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
393 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
400 // Allocate resource to save the notification function
402 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
403 if (NewNotify
== NULL
) {
404 return EFI_OUT_OF_RESOURCES
;
407 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
408 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
409 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
410 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
411 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
413 *NotifyHandle
= NewNotify
->NotifyHandle
;
420 Remove a registered notification function from a particular keystroke.
422 @param This Protocol instance pointer.
423 @param NotificationHandle The handle of the notification function being
426 @retval EFI_SUCCESS The notification function was unregistered
428 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
433 TerminalConInUnregisterKeyNotify (
434 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
435 IN EFI_HANDLE NotificationHandle
438 TERMINAL_DEV
*TerminalDevice
;
440 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
441 LIST_ENTRY
*NotifyList
;
443 if (NotificationHandle
== NULL
) {
444 return EFI_INVALID_PARAMETER
;
447 if (((TERMINAL_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
448 return EFI_INVALID_PARAMETER
;
451 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
453 NotifyList
= &TerminalDevice
->NotifyList
;
454 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
457 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
459 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
461 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
463 // Remove the notification function from NotifyList and free resources
465 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
467 gBS
->FreePool (CurrentNotify
);
473 // Can not find the matching entry in database.
475 return EFI_INVALID_PARAMETER
;
479 Translate raw data into Unicode (according to different encode), and
480 translate Unicode into key information. (according to different standard).
482 @param TerminalDevice Terminal driver private structure.
486 TranslateRawDataToEfiKey (
487 IN TERMINAL_DEV
*TerminalDevice
490 switch (TerminalDevice
->TerminalType
) {
495 AnsiRawDataToUnicode (TerminalDevice
);
496 UnicodeToEfiKey (TerminalDevice
);
501 // Process all the raw data in the RawFIFO,
502 // put the processed key into UnicodeFIFO.
504 VTUTF8RawDataToUnicode (TerminalDevice
);
507 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
508 // then put into EfiKeyFIFO.
510 UnicodeToEfiKey (TerminalDevice
);
517 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
518 Signal the event if there is key available
520 @param Event Indicates the event that invoke this function.
521 @param Context Indicates the calling context.
526 TerminalConInWaitForKey (
532 // Someone is waiting on the keystroke event, if there's
533 // a key pending, signal the event
535 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
537 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
539 gBS
->SignalEvent (Event
);
545 Check for a pending key in the Efi Key FIFO or Serial device buffer.
547 @param This Indicates the calling context.
549 @retval EFI_SUCCESS There is key pending.
550 @retval EFI_NOT_READY There is no key pending.
551 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
555 TerminalConInCheckForKey (
556 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
560 TERMINAL_DEV
*TerminalDevice
;
563 EFI_SERIAL_IO_MODE
*Mode
;
564 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
565 UINTN SerialInTimeOut
;
567 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
569 SerialIo
= TerminalDevice
->SerialIo
;
570 if (SerialIo
== NULL
) {
571 return EFI_DEVICE_ERROR
;
574 // if current timeout value for serial device is not identical with
575 // the value saved in TERMINAL_DEV structure, then recalculate the
576 // timeout value again and set serial attribute according to this value.
578 Mode
= SerialIo
->Mode
;
579 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
582 if (Mode
->BaudRate
!= 0) {
584 // According to BAUD rate to calculate the timeout value.
586 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
589 Status
= SerialIo
->SetAttributes (
592 Mode
->ReceiveFifoDepth
,
593 (UINT32
) SerialInTimeOut
,
594 (EFI_PARITY_TYPE
) (Mode
->Parity
),
595 (UINT8
) Mode
->DataBits
,
596 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
599 if (EFI_ERROR (Status
)) {
600 TerminalDevice
->SerialInTimeOut
= 0;
602 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
606 // Check whether serial buffer is empty.
608 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
610 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
612 // Translate all the raw data in RawFIFO into EFI Key,
613 // according to different terminal type supported.
615 TranslateRawDataToEfiKey (TerminalDevice
);
618 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
621 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
624 return EFI_NOT_READY
;
628 // Fetch all the keys in the serial buffer,
629 // and insert the byte stream into RawFIFO.
633 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
635 if (EFI_ERROR (Status
)) {
636 if (Status
== EFI_DEVICE_ERROR
) {
637 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
638 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
639 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
640 TerminalDevice
->DevicePath
646 RawFiFoInsertOneKey (TerminalDevice
, Input
);
650 // Translate all the raw data in RawFIFO into EFI Key,
651 // according to different terminal type supported.
653 TranslateRawDataToEfiKey (TerminalDevice
);
655 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
656 return EFI_NOT_READY
;
663 Get one key out of serial buffer.
665 @param SerialIo Serial I/O protocol attached to the serial device.
666 @param Output The fetched key.
668 @retval EFI_NOT_READY If serial buffer is empty.
669 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
670 @retval EFI_SUCCESS If reading serial buffer successfully, put
671 the fetched key to the parameter output.
675 GetOneKeyFromSerial (
676 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
687 // Read one key from serial I/O device.
689 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
691 if (EFI_ERROR (Status
)) {
693 if (Status
== EFI_TIMEOUT
) {
694 return EFI_NOT_READY
;
697 return EFI_DEVICE_ERROR
;
702 return EFI_NOT_READY
;
709 Insert one byte raw data into the Raw Data FIFO.
711 @param TerminalDevice Terminal driver private structure.
712 @param Input The key will be input.
714 @retval TRUE If insert successfully.
715 @retval FLASE If Raw Data buffer is full before key insertion,
720 RawFiFoInsertOneKey (
721 TERMINAL_DEV
*TerminalDevice
,
727 Tail
= TerminalDevice
->RawFiFo
->Tail
;
729 if (IsRawFiFoFull (TerminalDevice
)) {
736 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
738 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
744 Remove one pre-fetched key out of the Raw Data FIFO.
746 @param TerminalDevice Terminal driver private structure.
747 @param Output The key will be removed.
749 @retval TRUE If insert successfully.
750 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
754 RawFiFoRemoveOneKey (
755 TERMINAL_DEV
*TerminalDevice
,
761 Head
= TerminalDevice
->RawFiFo
->Head
;
763 if (IsRawFiFoEmpty (TerminalDevice
)) {
771 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
773 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
779 Clarify whether Raw Data FIFO buffer is empty.
781 @param TerminalDevice Terminal driver private structure
783 @retval TRUE If Raw Data FIFO buffer is empty.
784 @retval FLASE If Raw Data FIFO buffer is not empty.
789 TERMINAL_DEV
*TerminalDevice
792 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
800 Clarify whether Raw Data FIFO buffer is full.
802 @param TerminalDevice Terminal driver private structure
804 @retval TRUE If Raw Data FIFO buffer is full.
805 @retval FLASE If Raw Data FIFO buffer is not full.
810 TERMINAL_DEV
*TerminalDevice
816 Tail
= TerminalDevice
->RawFiFo
->Tail
;
817 Head
= TerminalDevice
->RawFiFo
->Head
;
819 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
828 Insert one pre-fetched key into the FIFO buffer.
830 @param TerminalDevice Terminal driver private structure.
831 @param Key The key will be input.
833 @retval TRUE If insert successfully.
834 @retval FLASE If FIFO buffer is full before key insertion,
839 EfiKeyFiFoInsertOneKey (
840 TERMINAL_DEV
*TerminalDevice
,
846 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
847 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
849 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
851 // Efi Key FIFO is full
856 TerminalDevice
->EfiKeyFiFo
->Data
[Tail
] = Key
;
858 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
864 Remove one pre-fetched key out of the FIFO buffer.
866 @param TerminalDevice Terminal driver private structure.
867 @param Output The key will be removed.
869 @retval TRUE If insert successfully.
870 @retval FLASE If FIFO buffer is empty before remove operation.
874 EfiKeyFiFoRemoveOneKey (
875 TERMINAL_DEV
*TerminalDevice
,
876 EFI_INPUT_KEY
*Output
881 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
882 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
884 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
888 Output
->ScanCode
= SCAN_NULL
;
889 Output
->UnicodeChar
= 0;
893 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
895 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
901 Clarify whether FIFO buffer is empty.
903 @param TerminalDevice Terminal driver private structure
905 @retval TRUE If FIFO buffer is empty.
906 @retval FLASE If FIFO buffer is not empty.
911 TERMINAL_DEV
*TerminalDevice
914 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
922 Clarify whether FIFO buffer is full.
924 @param TerminalDevice Terminal driver private structure
926 @retval TRUE If FIFO buffer is full.
927 @retval FLASE If FIFO buffer is not full.
932 TERMINAL_DEV
*TerminalDevice
938 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
939 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
941 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
950 Insert one pre-fetched key into the Unicode FIFO buffer.
952 @param TerminalDevice Terminal driver private structure.
953 @param Input The key will be input.
955 @retval TRUE If insert successfully.
956 @retval FLASE If Unicode FIFO buffer is full before key insertion,
961 UnicodeFiFoInsertOneKey (
962 TERMINAL_DEV
*TerminalDevice
,
968 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
969 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
972 if (IsUnicodeFiFoFull (TerminalDevice
)) {
974 // Unicode FIFO is full
979 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
981 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
987 Remove one pre-fetched key out of the Unicode FIFO buffer.
989 @param TerminalDevice Terminal driver private structure.
990 @param Output The key will be removed.
992 @retval TRUE If insert successfully.
993 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
997 UnicodeFiFoRemoveOneKey (
998 TERMINAL_DEV
*TerminalDevice
,
1004 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1005 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1007 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1015 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1017 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1023 Clarify whether Unicode FIFO buffer is empty.
1025 @param TerminalDevice Terminal driver private structure
1027 @retval TRUE If Unicode FIFO buffer is empty.
1028 @retval FLASE If Unicode FIFO buffer is not empty.
1032 IsUnicodeFiFoEmpty (
1033 TERMINAL_DEV
*TerminalDevice
1036 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1044 Clarify whether Unicode FIFO buffer is full.
1046 @param TerminalDevice Terminal driver private structure
1048 @retval TRUE If Unicode FIFO buffer is full.
1049 @retval FLASE If Unicode FIFO buffer is not full.
1054 TERMINAL_DEV
*TerminalDevice
1060 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1061 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1063 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1072 Count Unicode FIFO buffer.
1074 @param TerminalDevice Terminal driver private structure
1076 @return The count in bytes of Unicode FIFO.
1080 UnicodeFiFoGetKeyCount (
1081 TERMINAL_DEV
*TerminalDevice
1087 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1088 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1091 return (UINT8
) (Tail
- Head
);
1093 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1098 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1100 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1104 UnicodeToEfiKeyFlushState (
1105 IN TERMINAL_DEV
*TerminalDevice
1111 InputState
= TerminalDevice
->InputState
;
1113 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1114 Key
.ScanCode
= SCAN_ESC
;
1115 Key
.UnicodeChar
= 0;
1116 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1119 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1120 Key
.ScanCode
= SCAN_NULL
;
1121 Key
.UnicodeChar
= CSI
;
1122 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1125 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1126 Key
.ScanCode
= SCAN_NULL
;
1127 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1128 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1131 if ((InputState
& INPUT_STATE_O
) != 0) {
1132 Key
.ScanCode
= SCAN_NULL
;
1133 Key
.UnicodeChar
= 'O';
1134 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1137 if ((InputState
& INPUT_STATE_2
) != 0) {
1138 Key
.ScanCode
= SCAN_NULL
;
1139 Key
.UnicodeChar
= '2';
1140 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1144 // Cancel the timer.
1147 TerminalDevice
->TwoSecondTimeOut
,
1152 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1157 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1158 can be read through the Simple Input Protocol.
1160 The table below shows the keyboard input mappings that this function supports.
1161 If the ESC sequence listed in one of the columns is presented, then it is translated
1162 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1163 key strokes are converted into EFI Keys.
1165 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1166 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1167 converted into EFI Keys.
1168 There is one special input sequence that will force the system to reset.
1169 This is ESC R ESC r ESC R.
1171 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1172 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1173 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1175 Symbols used in table below
1176 ===========================
1182 +=========+======+===========+==========+==========+
1183 | | EFI | UEFI 2.0 | | |
1184 | | Scan | | VT100+ | |
1185 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1186 +=========+======+===========+==========+==========+
1187 | NULL | 0x00 | | | |
1188 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1189 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1190 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1191 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1192 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1193 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1194 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1195 | | | ESC [ L | | ESC [ L |
1196 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1197 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1199 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1201 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1202 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1203 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1204 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1205 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1206 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1207 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1208 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1209 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1210 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1211 | Escape | 0x17 | ESC | ESC | ESC |
1212 | F11 | 0x15 | | ESC ! | |
1213 | F12 | 0x16 | | ESC @ | |
1214 +=========+======+===========+==========+==========+
1218 ESC R ESC r ESC R = Reset System
1220 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1225 IN TERMINAL_DEV
*TerminalDevice
1229 EFI_STATUS TimerStatus
;
1232 BOOLEAN SetDefaultResetState
;
1234 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1236 if (!EFI_ERROR (TimerStatus
)) {
1237 UnicodeToEfiKeyFlushState (TerminalDevice
);
1238 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1241 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1243 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1245 // Check to see if the 2 seconds timer has expired
1247 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1248 if (!EFI_ERROR (TimerStatus
)) {
1249 UnicodeToEfiKeyFlushState (TerminalDevice
);
1250 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1255 // Fetch one Unicode character from the Unicode FIFO
1257 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1259 SetDefaultResetState
= TRUE
;
1261 switch (TerminalDevice
->InputState
) {
1262 case INPUT_STATE_DEFAULT
:
1266 case INPUT_STATE_ESC
:
1268 if (UnicodeChar
== LEFTOPENBRACKET
) {
1269 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1270 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1274 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1275 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1276 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1280 Key
.ScanCode
= SCAN_NULL
;
1282 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1283 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1284 switch (UnicodeChar
) {
1286 Key
.ScanCode
= SCAN_F1
;
1289 Key
.ScanCode
= SCAN_F2
;
1292 Key
.ScanCode
= SCAN_F3
;
1295 Key
.ScanCode
= SCAN_F4
;
1298 Key
.ScanCode
= SCAN_F5
;
1301 Key
.ScanCode
= SCAN_F6
;
1304 Key
.ScanCode
= SCAN_F7
;
1307 Key
.ScanCode
= SCAN_F8
;
1310 Key
.ScanCode
= SCAN_F9
;
1313 Key
.ScanCode
= SCAN_F10
;
1316 Key
.ScanCode
= SCAN_F11
;
1319 Key
.ScanCode
= SCAN_F12
;
1322 Key
.ScanCode
= SCAN_HOME
;
1325 Key
.ScanCode
= SCAN_END
;
1328 Key
.ScanCode
= SCAN_INSERT
;
1331 Key
.ScanCode
= SCAN_DELETE
;
1334 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1337 Key
.ScanCode
= SCAN_PAGE_UP
;
1344 switch (UnicodeChar
) {
1346 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1347 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1348 SetDefaultResetState
= FALSE
;
1349 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1350 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1352 Key
.ScanCode
= SCAN_NULL
;
1355 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1356 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1357 SetDefaultResetState
= FALSE
;
1359 Key
.ScanCode
= SCAN_NULL
;
1365 if (SetDefaultResetState
) {
1366 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1369 if (Key
.ScanCode
!= SCAN_NULL
) {
1370 Key
.UnicodeChar
= 0;
1371 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1372 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1373 UnicodeToEfiKeyFlushState (TerminalDevice
);
1377 UnicodeToEfiKeyFlushState (TerminalDevice
);
1381 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1383 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1385 Key
.ScanCode
= SCAN_NULL
;
1387 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1388 switch (UnicodeChar
) {
1390 Key
.ScanCode
= SCAN_F1
;
1393 Key
.ScanCode
= SCAN_F2
;
1396 Key
.ScanCode
= SCAN_F3
;
1399 Key
.ScanCode
= SCAN_F4
;
1402 Key
.ScanCode
= SCAN_F5
;
1405 Key
.ScanCode
= SCAN_F6
;
1408 Key
.ScanCode
= SCAN_F7
;
1411 Key
.ScanCode
= SCAN_F8
;
1414 Key
.ScanCode
= SCAN_F9
;
1417 Key
.ScanCode
= SCAN_F10
;
1424 if (Key
.ScanCode
!= SCAN_NULL
) {
1425 Key
.UnicodeChar
= 0;
1426 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1427 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1428 UnicodeToEfiKeyFlushState (TerminalDevice
);
1432 UnicodeToEfiKeyFlushState (TerminalDevice
);
1436 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1438 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1440 Key
.ScanCode
= SCAN_NULL
;
1442 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1443 TerminalDevice
->TerminalType
== VT100TYPE
||
1444 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1445 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1446 switch (UnicodeChar
) {
1448 Key
.ScanCode
= SCAN_UP
;
1451 Key
.ScanCode
= SCAN_DOWN
;
1454 Key
.ScanCode
= SCAN_RIGHT
;
1457 Key
.ScanCode
= SCAN_LEFT
;
1460 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1461 TerminalDevice
->TerminalType
== VT100TYPE
) {
1462 Key
.ScanCode
= SCAN_HOME
;
1466 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1467 Key
.ScanCode
= SCAN_END
;
1471 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1472 Key
.ScanCode
= SCAN_END
;
1477 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1478 TerminalDevice
->TerminalType
== VT100TYPE
) {
1479 Key
.ScanCode
= SCAN_INSERT
;
1483 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1484 Key
.ScanCode
= SCAN_DELETE
;
1488 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1489 Key
.ScanCode
= SCAN_DELETE
;
1490 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1491 Key
.ScanCode
= SCAN_F4
;
1495 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1496 Key
.ScanCode
= SCAN_PAGE_UP
;
1500 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1501 Key
.ScanCode
= SCAN_F10
;
1504 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1505 Key
.ScanCode
= SCAN_PAGE_UP
;
1509 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1510 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1514 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1515 Key
.ScanCode
= SCAN_F9
;
1518 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1519 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1523 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1524 Key
.ScanCode
= SCAN_F1
;
1528 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1529 Key
.ScanCode
= SCAN_F2
;
1533 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1534 Key
.ScanCode
= SCAN_F3
;
1538 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1539 Key
.ScanCode
= SCAN_F5
;
1543 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1544 Key
.ScanCode
= SCAN_F6
;
1548 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1549 Key
.ScanCode
= SCAN_F7
;
1553 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1554 Key
.ScanCode
= SCAN_F8
;
1562 if (Key
.ScanCode
!= SCAN_NULL
) {
1563 Key
.UnicodeChar
= 0;
1564 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1565 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1566 UnicodeToEfiKeyFlushState (TerminalDevice
);
1570 UnicodeToEfiKeyFlushState (TerminalDevice
);
1577 // Invalid state. This should never happen.
1581 UnicodeToEfiKeyFlushState (TerminalDevice
);
1586 if (UnicodeChar
== ESC
) {
1587 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1590 if (UnicodeChar
== CSI
) {
1591 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1594 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1595 Status
= gBS
->SetTimer(
1596 TerminalDevice
->TwoSecondTimeOut
,
1600 ASSERT_EFI_ERROR (Status
);
1604 if (SetDefaultResetState
) {
1605 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1608 if (UnicodeChar
== DEL
) {
1609 Key
.ScanCode
= SCAN_DELETE
;
1610 Key
.UnicodeChar
= 0;
1612 Key
.ScanCode
= SCAN_NULL
;
1613 Key
.UnicodeChar
= UnicodeChar
;
1616 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);