2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2008, 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 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
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 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
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.
429 @retval EFI_NOT_FOUND Can not find the matching entry in database.
434 TerminalConInUnregisterKeyNotify (
435 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
436 IN EFI_HANDLE NotificationHandle
439 TERMINAL_DEV
*TerminalDevice
;
441 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
442 LIST_ENTRY
*NotifyList
;
444 if (NotificationHandle
== NULL
) {
445 return EFI_INVALID_PARAMETER
;
448 if (((TERMINAL_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
449 return EFI_INVALID_PARAMETER
;
452 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
454 NotifyList
= &TerminalDevice
->NotifyList
;
455 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
458 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
460 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
462 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
464 // Remove the notification function from NotifyList and free resources
466 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
468 gBS
->FreePool (CurrentNotify
);
473 return EFI_NOT_FOUND
;
477 Translate raw data into Unicode (according to different encode), and
478 translate Unicode into key information. (according to different standard).
480 @param TerminalDevice Terminal driver private structure.
484 TranslateRawDataToEfiKey (
485 IN TERMINAL_DEV
*TerminalDevice
488 switch (TerminalDevice
->TerminalType
) {
493 AnsiRawDataToUnicode (TerminalDevice
);
494 UnicodeToEfiKey (TerminalDevice
);
499 // Process all the raw data in the RawFIFO,
500 // put the processed key into UnicodeFIFO.
502 VTUTF8RawDataToUnicode (TerminalDevice
);
505 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
506 // then put into EfiKeyFIFO.
508 UnicodeToEfiKey (TerminalDevice
);
515 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
516 Signal the event if there is key available
518 @param Event Indicates the event that invoke this function.
519 @param Context Indicates the calling context.
524 TerminalConInWaitForKey (
530 // Someone is waiting on the keystroke event, if there's
531 // a key pending, signal the event
533 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
535 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
537 gBS
->SignalEvent (Event
);
543 Check for a pending key in the Efi Key FIFO or Serial device buffer.
545 @param This Indicates the calling context.
547 @retval EFI_SUCCESS There is key pending.
548 @retval EFI_NOT_READY There is no key pending.
549 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
553 TerminalConInCheckForKey (
554 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
558 TERMINAL_DEV
*TerminalDevice
;
561 EFI_SERIAL_IO_MODE
*Mode
;
562 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
563 UINTN SerialInTimeOut
;
565 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
567 SerialIo
= TerminalDevice
->SerialIo
;
568 if (SerialIo
== NULL
) {
569 return EFI_DEVICE_ERROR
;
572 // if current timeout value for serial device is not identical with
573 // the value saved in TERMINAL_DEV structure, then recalculate the
574 // timeout value again and set serial attribute according to this value.
576 Mode
= SerialIo
->Mode
;
577 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
580 if (Mode
->BaudRate
!= 0) {
582 // According to BAUD rate to calculate the timeout value.
584 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
587 Status
= SerialIo
->SetAttributes (
590 Mode
->ReceiveFifoDepth
,
591 (UINT32
) SerialInTimeOut
,
592 (EFI_PARITY_TYPE
) (Mode
->Parity
),
593 (UINT8
) Mode
->DataBits
,
594 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
597 if (EFI_ERROR (Status
)) {
598 TerminalDevice
->SerialInTimeOut
= 0;
600 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
604 // Check whether serial buffer is empty.
606 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
608 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
610 // Translate all the raw data in RawFIFO into EFI Key,
611 // according to different terminal type supported.
613 TranslateRawDataToEfiKey (TerminalDevice
);
616 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
619 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
622 return EFI_NOT_READY
;
626 // Fetch all the keys in the serial buffer,
627 // and insert the byte stream into RawFIFO.
631 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
633 if (EFI_ERROR (Status
)) {
634 if (Status
== EFI_DEVICE_ERROR
) {
635 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
636 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
637 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
638 TerminalDevice
->DevicePath
644 RawFiFoInsertOneKey (TerminalDevice
, Input
);
648 // Translate all the raw data in RawFIFO into EFI Key,
649 // according to different terminal type supported.
651 TranslateRawDataToEfiKey (TerminalDevice
);
653 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
654 return EFI_NOT_READY
;
661 Get one key out of serial buffer.
663 @param SerialIo Serial I/O protocol attached to the serial device.
664 @param Output The fetched key.
666 @retval EFI_NOT_READY If serial buffer is empty.
667 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
668 @retval EFI_SUCCESS If reading serial buffer successfully, put
669 the fetched key to the parameter output.
673 GetOneKeyFromSerial (
674 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
685 // Read one key from serial I/O device.
687 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
689 if (EFI_ERROR (Status
)) {
691 if (Status
== EFI_TIMEOUT
) {
692 return EFI_NOT_READY
;
695 return EFI_DEVICE_ERROR
;
700 return EFI_NOT_READY
;
707 Insert one byte raw data into the Raw Data FIFO.
709 @param TerminalDevice Terminal driver private structure.
710 @param Input The key will be input.
712 @retval TRUE If insert successfully.
713 @retval FLASE If Raw Data buffer is full before key insertion,
718 RawFiFoInsertOneKey (
719 TERMINAL_DEV
*TerminalDevice
,
725 Tail
= TerminalDevice
->RawFiFo
->Tail
;
727 if (IsRawFiFoFull (TerminalDevice
)) {
734 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
736 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
742 Remove one pre-fetched key out of the Raw Data FIFO.
744 @param TerminalDevice Terminal driver private structure.
745 @param Output The key will be removed.
747 @retval TRUE If insert successfully.
748 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
752 RawFiFoRemoveOneKey (
753 TERMINAL_DEV
*TerminalDevice
,
759 Head
= TerminalDevice
->RawFiFo
->Head
;
761 if (IsRawFiFoEmpty (TerminalDevice
)) {
769 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
771 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
777 Clarify whether Raw Data FIFO buffer is empty.
779 @param TerminalDevice Terminal driver private structure
781 @retval TRUE If Raw Data FIFO buffer is empty.
782 @retval FLASE If Raw Data FIFO buffer is not empty.
787 TERMINAL_DEV
*TerminalDevice
790 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
798 Clarify whether Raw Data FIFO buffer is full.
800 @param TerminalDevice Terminal driver private structure
802 @retval TRUE If Raw Data FIFO buffer is full.
803 @retval FLASE If Raw Data FIFO buffer is not full.
808 TERMINAL_DEV
*TerminalDevice
814 Tail
= TerminalDevice
->RawFiFo
->Tail
;
815 Head
= TerminalDevice
->RawFiFo
->Head
;
817 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
826 Insert one pre-fetched key into the FIFO buffer.
828 @param TerminalDevice Terminal driver private structure.
829 @param Key The key will be input.
831 @retval TRUE If insert successfully.
832 @retval FLASE If FIFO buffer is full before key insertion,
837 EfiKeyFiFoInsertOneKey (
838 TERMINAL_DEV
*TerminalDevice
,
844 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
845 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
847 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
849 // Efi Key FIFO is full
854 TerminalDevice
->EfiKeyFiFo
->Data
[Tail
] = Key
;
856 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
862 Remove one pre-fetched key out of the FIFO buffer.
864 @param TerminalDevice Terminal driver private structure.
865 @param Output The key will be removed.
867 @retval TRUE If insert successfully.
868 @retval FLASE If FIFO buffer is empty before remove operation.
872 EfiKeyFiFoRemoveOneKey (
873 TERMINAL_DEV
*TerminalDevice
,
874 EFI_INPUT_KEY
*Output
879 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
880 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
882 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
886 Output
->ScanCode
= SCAN_NULL
;
887 Output
->UnicodeChar
= 0;
891 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
893 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
899 Clarify whether FIFO buffer is empty.
901 @param TerminalDevice Terminal driver private structure
903 @retval TRUE If FIFO buffer is empty.
904 @retval FLASE If FIFO buffer is not empty.
909 TERMINAL_DEV
*TerminalDevice
912 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
920 Clarify whether FIFO buffer is full.
922 @param TerminalDevice Terminal driver private structure
924 @retval TRUE If FIFO buffer is full.
925 @retval FLASE If FIFO buffer is not full.
930 TERMINAL_DEV
*TerminalDevice
936 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
937 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
939 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
948 Insert one pre-fetched key into the Unicode FIFO buffer.
950 @param TerminalDevice Terminal driver private structure.
951 @param Input The key will be input.
953 @retval TRUE If insert successfully.
954 @retval FLASE If Unicode FIFO buffer is full before key insertion,
959 UnicodeFiFoInsertOneKey (
960 TERMINAL_DEV
*TerminalDevice
,
966 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
967 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
970 if (IsUnicodeFiFoFull (TerminalDevice
)) {
972 // Unicode FIFO is full
977 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
979 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
985 Remove one pre-fetched key out of the Unicode FIFO buffer.
987 @param TerminalDevice Terminal driver private structure.
988 @param Output The key will be removed.
990 @retval TRUE If insert successfully.
991 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
995 UnicodeFiFoRemoveOneKey (
996 TERMINAL_DEV
*TerminalDevice
,
1002 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1003 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1005 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1013 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1015 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1021 Clarify whether Unicode FIFO buffer is empty.
1023 @param TerminalDevice Terminal driver private structure
1025 @retval TRUE If Unicode FIFO buffer is empty.
1026 @retval FLASE If Unicode FIFO buffer is not empty.
1030 IsUnicodeFiFoEmpty (
1031 TERMINAL_DEV
*TerminalDevice
1034 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1042 Clarify whether Unicode FIFO buffer is full.
1044 @param TerminalDevice Terminal driver private structure
1046 @retval TRUE If Unicode FIFO buffer is full.
1047 @retval FLASE If Unicode FIFO buffer is not full.
1052 TERMINAL_DEV
*TerminalDevice
1058 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1059 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1061 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1070 Count Unicode FIFO buffer.
1072 @param TerminalDevice Terminal driver private structure
1074 @return The count in bytes of Unicode FIFO.
1078 UnicodeFiFoGetKeyCount (
1079 TERMINAL_DEV
*TerminalDevice
1085 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1086 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1089 return (UINT8
) (Tail
- Head
);
1091 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1096 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1098 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1102 UnicodeToEfiKeyFlushState (
1103 IN TERMINAL_DEV
*TerminalDevice
1109 InputState
= TerminalDevice
->InputState
;
1111 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1112 Key
.ScanCode
= SCAN_ESC
;
1113 Key
.UnicodeChar
= 0;
1114 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1117 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1118 Key
.ScanCode
= SCAN_NULL
;
1119 Key
.UnicodeChar
= CSI
;
1120 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1123 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1124 Key
.ScanCode
= SCAN_NULL
;
1125 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1126 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1129 if ((InputState
& INPUT_STATE_O
) != 0) {
1130 Key
.ScanCode
= SCAN_NULL
;
1131 Key
.UnicodeChar
= 'O';
1132 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1135 if ((InputState
& INPUT_STATE_2
) != 0) {
1136 Key
.ScanCode
= SCAN_NULL
;
1137 Key
.UnicodeChar
= '2';
1138 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1142 // Cancel the timer.
1145 TerminalDevice
->TwoSecondTimeOut
,
1150 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1155 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1156 can be read through the Simple Input Protocol.
1158 The table below shows the keyboard input mappings that this function supports.
1159 If the ESC sequence listed in one of the columns is presented, then it is translated
1160 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1161 key strokes are converted into EFI Keys.
1163 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1164 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1165 converted into EFI Keys.
1166 There is one special input sequence that will force the system to reset.
1167 This is ESC R ESC r ESC R.
1169 Symbols used in table below
1170 ===========================
1176 +=========+======+===========+==========+==========+
1177 | | EFI | UEFI 2.0 | | |
1178 | | Scan | | VT100+ | |
1179 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1180 +=========+======+===========+==========+==========+
1181 | NULL | 0x00 | | | |
1182 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1183 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1184 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1185 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1186 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1187 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1188 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1189 | | | ESC [ L | | ESC [ L |
1190 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1191 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1193 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1195 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1196 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1197 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1198 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1199 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1200 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1201 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1202 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1203 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1204 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1205 | Escape | 0x17 | ESC | ESC | ESC |
1206 | F11 | 0x15 | | ESC ! | |
1207 | F12 | 0x16 | | ESC @ | |
1208 +=========+======+===========+==========+==========+
1212 ESC R ESC r ESC R = Reset System
1214 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1219 IN TERMINAL_DEV
*TerminalDevice
1223 EFI_STATUS TimerStatus
;
1226 BOOLEAN SetDefaultResetState
;
1228 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1230 if (!EFI_ERROR (TimerStatus
)) {
1231 UnicodeToEfiKeyFlushState (TerminalDevice
);
1232 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1235 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1237 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1239 // Check to see if the 2 seconds timer has expired
1241 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1242 if (!EFI_ERROR (TimerStatus
)) {
1243 UnicodeToEfiKeyFlushState (TerminalDevice
);
1244 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1249 // Fetch one Unicode character from the Unicode FIFO
1251 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1253 SetDefaultResetState
= TRUE
;
1255 switch (TerminalDevice
->InputState
) {
1256 case INPUT_STATE_DEFAULT
:
1260 case INPUT_STATE_ESC
:
1262 if (UnicodeChar
== LEFTOPENBRACKET
) {
1263 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1264 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1268 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1269 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1270 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1274 Key
.ScanCode
= SCAN_NULL
;
1276 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1277 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1278 switch (UnicodeChar
) {
1280 Key
.ScanCode
= SCAN_F1
;
1283 Key
.ScanCode
= SCAN_F2
;
1286 Key
.ScanCode
= SCAN_F3
;
1289 Key
.ScanCode
= SCAN_F4
;
1292 Key
.ScanCode
= SCAN_F5
;
1295 Key
.ScanCode
= SCAN_F6
;
1298 Key
.ScanCode
= SCAN_F7
;
1301 Key
.ScanCode
= SCAN_F8
;
1304 Key
.ScanCode
= SCAN_F9
;
1307 Key
.ScanCode
= SCAN_F10
;
1310 Key
.ScanCode
= SCAN_F11
;
1313 Key
.ScanCode
= SCAN_F12
;
1316 Key
.ScanCode
= SCAN_HOME
;
1319 Key
.ScanCode
= SCAN_END
;
1322 Key
.ScanCode
= SCAN_INSERT
;
1325 Key
.ScanCode
= SCAN_DELETE
;
1328 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1331 Key
.ScanCode
= SCAN_PAGE_UP
;
1338 switch (UnicodeChar
) {
1340 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1341 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1342 SetDefaultResetState
= FALSE
;
1343 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1344 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1346 Key
.ScanCode
= SCAN_NULL
;
1349 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1350 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1351 SetDefaultResetState
= FALSE
;
1353 Key
.ScanCode
= SCAN_NULL
;
1359 if (SetDefaultResetState
) {
1360 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1363 if (Key
.ScanCode
!= SCAN_NULL
) {
1364 Key
.UnicodeChar
= 0;
1365 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1366 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1367 UnicodeToEfiKeyFlushState (TerminalDevice
);
1371 UnicodeToEfiKeyFlushState (TerminalDevice
);
1375 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1377 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1379 Key
.ScanCode
= SCAN_NULL
;
1381 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1382 switch (UnicodeChar
) {
1384 Key
.ScanCode
= SCAN_F1
;
1387 Key
.ScanCode
= SCAN_F2
;
1390 Key
.ScanCode
= SCAN_F3
;
1393 Key
.ScanCode
= SCAN_F4
;
1396 Key
.ScanCode
= SCAN_F5
;
1399 Key
.ScanCode
= SCAN_F6
;
1402 Key
.ScanCode
= SCAN_F7
;
1405 Key
.ScanCode
= SCAN_F8
;
1408 Key
.ScanCode
= SCAN_F9
;
1411 Key
.ScanCode
= SCAN_F10
;
1418 if (Key
.ScanCode
!= SCAN_NULL
) {
1419 Key
.UnicodeChar
= 0;
1420 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1421 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1422 UnicodeToEfiKeyFlushState (TerminalDevice
);
1426 UnicodeToEfiKeyFlushState (TerminalDevice
);
1430 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1432 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1434 Key
.ScanCode
= SCAN_NULL
;
1436 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1437 TerminalDevice
->TerminalType
== VT100TYPE
||
1438 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1439 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1440 switch (UnicodeChar
) {
1442 Key
.ScanCode
= SCAN_UP
;
1445 Key
.ScanCode
= SCAN_DOWN
;
1448 Key
.ScanCode
= SCAN_RIGHT
;
1451 Key
.ScanCode
= SCAN_LEFT
;
1454 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1455 TerminalDevice
->TerminalType
== VT100TYPE
) {
1456 Key
.ScanCode
= SCAN_HOME
;
1460 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1461 Key
.ScanCode
= SCAN_END
;
1465 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1466 Key
.ScanCode
= SCAN_END
;
1471 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1472 TerminalDevice
->TerminalType
== VT100TYPE
) {
1473 Key
.ScanCode
= SCAN_INSERT
;
1477 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1478 Key
.ScanCode
= SCAN_DELETE
;
1482 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1483 Key
.ScanCode
= SCAN_DELETE
;
1484 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1485 Key
.ScanCode
= SCAN_F4
;
1489 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1490 Key
.ScanCode
= SCAN_PAGE_UP
;
1494 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1495 Key
.ScanCode
= SCAN_F10
;
1498 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1499 Key
.ScanCode
= SCAN_PAGE_UP
;
1503 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1504 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1508 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1509 Key
.ScanCode
= SCAN_F9
;
1512 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1513 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1517 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1518 Key
.ScanCode
= SCAN_F1
;
1522 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1523 Key
.ScanCode
= SCAN_F2
;
1527 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1528 Key
.ScanCode
= SCAN_F3
;
1532 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1533 Key
.ScanCode
= SCAN_F5
;
1537 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1538 Key
.ScanCode
= SCAN_F6
;
1542 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1543 Key
.ScanCode
= SCAN_F7
;
1547 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1548 Key
.ScanCode
= SCAN_F8
;
1556 if (Key
.ScanCode
!= SCAN_NULL
) {
1557 Key
.UnicodeChar
= 0;
1558 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1559 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1560 UnicodeToEfiKeyFlushState (TerminalDevice
);
1564 UnicodeToEfiKeyFlushState (TerminalDevice
);
1571 // Invalid state. This should never happen.
1575 UnicodeToEfiKeyFlushState (TerminalDevice
);
1580 if (UnicodeChar
== ESC
) {
1581 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1584 if (UnicodeChar
== CSI
) {
1585 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1588 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1589 Status
= gBS
->SetTimer(
1590 TerminalDevice
->TwoSecondTimeOut
,
1594 ASSERT_EFI_ERROR (Status
);
1598 if (SetDefaultResetState
) {
1599 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1602 if (UnicodeChar
== DEL
) {
1603 Key
.ScanCode
= SCAN_DELETE
;
1604 Key
.UnicodeChar
= 0;
1606 Key
.ScanCode
= SCAN_NULL
;
1607 Key
.UnicodeChar
= UnicodeChar
;
1610 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);