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 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
450 NotifyList
= &TerminalDevice
->NotifyList
;
451 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
454 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
456 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
458 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
460 // Remove the notification function from NotifyList and free resources
462 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
464 gBS
->FreePool (CurrentNotify
);
469 return EFI_NOT_FOUND
;
473 Translate raw data into Unicode (according to different encode), and
474 translate Unicode into key information. (according to different standard).
476 @param TerminalDevice Terminal driver private structure.
480 TranslateRawDataToEfiKey (
481 IN TERMINAL_DEV
*TerminalDevice
484 switch (TerminalDevice
->TerminalType
) {
489 AnsiRawDataToUnicode (TerminalDevice
);
490 UnicodeToEfiKey (TerminalDevice
);
495 // Process all the raw data in the RawFIFO,
496 // put the processed key into UnicodeFIFO.
498 VTUTF8RawDataToUnicode (TerminalDevice
);
501 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
502 // then put into EfiKeyFIFO.
504 UnicodeToEfiKey (TerminalDevice
);
511 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
512 Signal the event if there is key available
514 @param Event Indicates the event that invoke this function.
515 @param Context Indicates the calling context.
520 TerminalConInWaitForKey (
526 // Someone is waiting on the keystroke event, if there's
527 // a key pending, signal the event
529 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
531 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
533 gBS
->SignalEvent (Event
);
539 Check for a pending key in the Efi Key FIFO or Serial device buffer.
541 @param This Indicates the calling context.
543 @retval EFI_SUCCESS There is key pending.
544 @retval EFI_NOT_READY There is no key pending.
545 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
549 TerminalConInCheckForKey (
550 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
554 TERMINAL_DEV
*TerminalDevice
;
557 EFI_SERIAL_IO_MODE
*Mode
;
558 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
559 UINTN SerialInTimeOut
;
561 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
563 SerialIo
= TerminalDevice
->SerialIo
;
564 if (SerialIo
== NULL
) {
565 return EFI_DEVICE_ERROR
;
568 // if current timeout value for serial device is not identical with
569 // the value saved in TERMINAL_DEV structure, then recalculate the
570 // timeout value again and set serial attribute according to this value.
572 Mode
= SerialIo
->Mode
;
573 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
576 if (Mode
->BaudRate
!= 0) {
578 // According to BAUD rate to calculate the timeout value.
580 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
583 Status
= SerialIo
->SetAttributes (
586 Mode
->ReceiveFifoDepth
,
587 (UINT32
) SerialInTimeOut
,
588 (EFI_PARITY_TYPE
) (Mode
->Parity
),
589 (UINT8
) Mode
->DataBits
,
590 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
593 if (EFI_ERROR (Status
)) {
594 TerminalDevice
->SerialInTimeOut
= 0;
596 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
600 // Check whether serial buffer is empty.
602 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
604 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
606 // Translate all the raw data in RawFIFO into EFI Key,
607 // according to different terminal type supported.
609 TranslateRawDataToEfiKey (TerminalDevice
);
612 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
615 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
618 return EFI_NOT_READY
;
622 // Fetch all the keys in the serial buffer,
623 // and insert the byte stream into RawFIFO.
627 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
629 if (EFI_ERROR (Status
)) {
630 if (Status
== EFI_DEVICE_ERROR
) {
631 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
632 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
633 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
634 TerminalDevice
->DevicePath
640 RawFiFoInsertOneKey (TerminalDevice
, Input
);
644 // Translate all the raw data in RawFIFO into EFI Key,
645 // according to different terminal type supported.
647 TranslateRawDataToEfiKey (TerminalDevice
);
649 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
650 return EFI_NOT_READY
;
657 Get one key out of serial buffer.
659 @param SerialIo Serial I/O protocol attached to the serial device.
660 @param Output The fetched key.
662 @retval EFI_NOT_READY If serial buffer is empty.
663 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
664 @retval EFI_SUCCESS If reading serial buffer successfully, put
665 the fetched key to the parameter output.
669 GetOneKeyFromSerial (
670 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
681 // Read one key from serial I/O device.
683 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
685 if (EFI_ERROR (Status
)) {
687 if (Status
== EFI_TIMEOUT
) {
688 return EFI_NOT_READY
;
691 return EFI_DEVICE_ERROR
;
696 return EFI_NOT_READY
;
703 Insert one byte raw data into the Raw Data FIFO.
705 @param TerminalDevice Terminal driver private structure.
706 @param Input The key will be input.
708 @retval TRUE If insert successfully.
709 @retval FLASE If Raw Data buffer is full before key insertion,
714 RawFiFoInsertOneKey (
715 TERMINAL_DEV
*TerminalDevice
,
721 Tail
= TerminalDevice
->RawFiFo
->Tail
;
723 if (IsRawFiFoFull (TerminalDevice
)) {
730 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
732 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
738 Remove one pre-fetched key out of the Raw Data FIFO.
740 @param TerminalDevice Terminal driver private structure.
741 @param Output The key will be removed.
743 @retval TRUE If insert successfully.
744 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
748 RawFiFoRemoveOneKey (
749 TERMINAL_DEV
*TerminalDevice
,
755 Head
= TerminalDevice
->RawFiFo
->Head
;
757 if (IsRawFiFoEmpty (TerminalDevice
)) {
765 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
767 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
773 Clarify whether Raw Data FIFO buffer is empty.
775 @param TerminalDevice Terminal driver private structure
777 @retval TRUE If Raw Data FIFO buffer is empty.
778 @retval FLASE If Raw Data FIFO buffer is not empty.
783 TERMINAL_DEV
*TerminalDevice
786 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
794 Clarify whether Raw Data FIFO buffer is full.
796 @param TerminalDevice Terminal driver private structure
798 @retval TRUE If Raw Data FIFO buffer is full.
799 @retval FLASE If Raw Data FIFO buffer is not full.
804 TERMINAL_DEV
*TerminalDevice
810 Tail
= TerminalDevice
->RawFiFo
->Tail
;
811 Head
= TerminalDevice
->RawFiFo
->Head
;
813 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
822 Insert one pre-fetched key into the FIFO buffer.
824 @param TerminalDevice Terminal driver private structure.
825 @param Key The key will be input.
827 @retval TRUE If insert successfully.
828 @retval FLASE If FIFO buffer is full before key insertion,
833 EfiKeyFiFoInsertOneKey (
834 TERMINAL_DEV
*TerminalDevice
,
840 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
841 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
843 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
845 // Efi Key FIFO is full
850 TerminalDevice
->EfiKeyFiFo
->Data
[Tail
] = Key
;
852 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
858 Remove one pre-fetched key out of the FIFO buffer.
860 @param TerminalDevice Terminal driver private structure.
861 @param Output The key will be removed.
863 @retval TRUE If insert successfully.
864 @retval FLASE If FIFO buffer is empty before remove operation.
868 EfiKeyFiFoRemoveOneKey (
869 TERMINAL_DEV
*TerminalDevice
,
870 EFI_INPUT_KEY
*Output
875 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
876 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
878 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
882 Output
->ScanCode
= SCAN_NULL
;
883 Output
->UnicodeChar
= 0;
887 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
889 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
895 Clarify whether FIFO buffer is empty.
897 @param TerminalDevice Terminal driver private structure
899 @retval TRUE If FIFO buffer is empty.
900 @retval FLASE If FIFO buffer is not empty.
905 TERMINAL_DEV
*TerminalDevice
908 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
916 Clarify whether FIFO buffer is full.
918 @param TerminalDevice Terminal driver private structure
920 @retval TRUE If FIFO buffer is full.
921 @retval FLASE If FIFO buffer is not full.
926 TERMINAL_DEV
*TerminalDevice
932 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
933 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
935 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
944 Insert one pre-fetched key into the Unicode FIFO buffer.
946 @param TerminalDevice Terminal driver private structure.
947 @param Input The key will be input.
949 @retval TRUE If insert successfully.
950 @retval FLASE If Unicode FIFO buffer is full before key insertion,
955 UnicodeFiFoInsertOneKey (
956 TERMINAL_DEV
*TerminalDevice
,
962 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
963 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
966 if (IsUnicodeFiFoFull (TerminalDevice
)) {
968 // Unicode FIFO is full
973 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
975 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
981 Remove one pre-fetched key out of the Unicode FIFO buffer.
983 @param TerminalDevice Terminal driver private structure.
984 @param Output The key will be removed.
986 @retval TRUE If insert successfully.
987 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
991 UnicodeFiFoRemoveOneKey (
992 TERMINAL_DEV
*TerminalDevice
,
998 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
999 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1001 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1009 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1011 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1017 Clarify whether Unicode FIFO buffer is empty.
1019 @param TerminalDevice Terminal driver private structure
1021 @retval TRUE If Unicode FIFO buffer is empty.
1022 @retval FLASE If Unicode FIFO buffer is not empty.
1026 IsUnicodeFiFoEmpty (
1027 TERMINAL_DEV
*TerminalDevice
1030 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1038 Clarify whether Unicode FIFO buffer is full.
1040 @param TerminalDevice Terminal driver private structure
1042 @retval TRUE If Unicode FIFO buffer is full.
1043 @retval FLASE If Unicode FIFO buffer is not full.
1048 TERMINAL_DEV
*TerminalDevice
1054 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1055 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1057 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1066 Count Unicode FIFO buffer.
1068 @param TerminalDevice Terminal driver private structure
1070 @return The count in bytes of Unicode FIFO.
1074 UnicodeFiFoGetKeyCount (
1075 TERMINAL_DEV
*TerminalDevice
1081 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1082 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1085 return (UINT8
) (Tail
- Head
);
1087 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1092 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1094 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1098 UnicodeToEfiKeyFlushState (
1099 IN TERMINAL_DEV
*TerminalDevice
1105 InputState
= TerminalDevice
->InputState
;
1107 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1108 Key
.ScanCode
= SCAN_ESC
;
1109 Key
.UnicodeChar
= 0;
1110 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1113 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1114 Key
.ScanCode
= SCAN_NULL
;
1115 Key
.UnicodeChar
= CSI
;
1116 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1119 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1120 Key
.ScanCode
= SCAN_NULL
;
1121 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1122 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1125 if ((InputState
& INPUT_STATE_O
) != 0) {
1126 Key
.ScanCode
= SCAN_NULL
;
1127 Key
.UnicodeChar
= 'O';
1128 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1131 if ((InputState
& INPUT_STATE_2
) != 0) {
1132 Key
.ScanCode
= SCAN_NULL
;
1133 Key
.UnicodeChar
= '2';
1134 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1138 // Cancel the timer.
1141 TerminalDevice
->TwoSecondTimeOut
,
1146 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1151 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1152 can be read through the Simple Input Protocol.
1154 The table below shows the keyboard input mappings that this function supports.
1155 If the ESC sequence listed in one of the columns is presented, then it is translated
1156 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1157 key strokes are converted into EFI Keys.
1159 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1160 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1161 converted into EFI Keys.
1162 There is one special input sequence that will force the system to reset.
1163 This is ESC R ESC r ESC R.
1165 Symbols used in table below
1166 ===========================
1172 +=========+======+===========+==========+==========+
1173 | | EFI | UEFI 2.0 | | |
1174 | | Scan | | VT100+ | |
1175 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1176 +=========+======+===========+==========+==========+
1177 | NULL | 0x00 | | | |
1178 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1179 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1180 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1181 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1182 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1183 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1184 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1185 | | | ESC [ L | | ESC [ L |
1186 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1187 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1189 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1191 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1192 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1193 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1194 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1195 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1196 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1197 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1198 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1199 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1200 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1201 | Escape | 0x17 | ESC | ESC | ESC |
1202 | F11 | 0x15 | | ESC ! | |
1203 | F12 | 0x16 | | ESC @ | |
1204 +=========+======+===========+==========+==========+
1208 ESC R ESC r ESC R = Reset System
1210 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1215 IN TERMINAL_DEV
*TerminalDevice
1219 EFI_STATUS TimerStatus
;
1222 BOOLEAN SetDefaultResetState
;
1224 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1226 if (!EFI_ERROR (TimerStatus
)) {
1227 UnicodeToEfiKeyFlushState (TerminalDevice
);
1228 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1231 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1233 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1235 // Check to see if the 2 seconds timer has expired
1237 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1238 if (!EFI_ERROR (TimerStatus
)) {
1239 UnicodeToEfiKeyFlushState (TerminalDevice
);
1240 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1245 // Fetch one Unicode character from the Unicode FIFO
1247 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1249 SetDefaultResetState
= TRUE
;
1251 switch (TerminalDevice
->InputState
) {
1252 case INPUT_STATE_DEFAULT
:
1256 case INPUT_STATE_ESC
:
1258 if (UnicodeChar
== LEFTOPENBRACKET
) {
1259 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1260 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1264 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1265 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1266 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1270 Key
.ScanCode
= SCAN_NULL
;
1272 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1273 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1274 switch (UnicodeChar
) {
1276 Key
.ScanCode
= SCAN_F1
;
1279 Key
.ScanCode
= SCAN_F2
;
1282 Key
.ScanCode
= SCAN_F3
;
1285 Key
.ScanCode
= SCAN_F4
;
1288 Key
.ScanCode
= SCAN_F5
;
1291 Key
.ScanCode
= SCAN_F6
;
1294 Key
.ScanCode
= SCAN_F7
;
1297 Key
.ScanCode
= SCAN_F8
;
1300 Key
.ScanCode
= SCAN_F9
;
1303 Key
.ScanCode
= SCAN_F10
;
1306 Key
.ScanCode
= SCAN_F11
;
1309 Key
.ScanCode
= SCAN_F12
;
1312 Key
.ScanCode
= SCAN_HOME
;
1315 Key
.ScanCode
= SCAN_END
;
1318 Key
.ScanCode
= SCAN_INSERT
;
1321 Key
.ScanCode
= SCAN_DELETE
;
1324 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1327 Key
.ScanCode
= SCAN_PAGE_UP
;
1334 switch (UnicodeChar
) {
1336 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1337 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1338 SetDefaultResetState
= FALSE
;
1339 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1340 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1342 Key
.ScanCode
= SCAN_NULL
;
1345 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1346 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1347 SetDefaultResetState
= FALSE
;
1349 Key
.ScanCode
= SCAN_NULL
;
1355 if (SetDefaultResetState
) {
1356 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1359 if (Key
.ScanCode
!= SCAN_NULL
) {
1360 Key
.UnicodeChar
= 0;
1361 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1362 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1363 UnicodeToEfiKeyFlushState (TerminalDevice
);
1367 UnicodeToEfiKeyFlushState (TerminalDevice
);
1371 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1373 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1375 Key
.ScanCode
= SCAN_NULL
;
1377 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1378 switch (UnicodeChar
) {
1380 Key
.ScanCode
= SCAN_F1
;
1383 Key
.ScanCode
= SCAN_F2
;
1386 Key
.ScanCode
= SCAN_F3
;
1389 Key
.ScanCode
= SCAN_F4
;
1392 Key
.ScanCode
= SCAN_F5
;
1395 Key
.ScanCode
= SCAN_F6
;
1398 Key
.ScanCode
= SCAN_F7
;
1401 Key
.ScanCode
= SCAN_F8
;
1404 Key
.ScanCode
= SCAN_F9
;
1407 Key
.ScanCode
= SCAN_F10
;
1414 if (Key
.ScanCode
!= SCAN_NULL
) {
1415 Key
.UnicodeChar
= 0;
1416 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1417 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1418 UnicodeToEfiKeyFlushState (TerminalDevice
);
1422 UnicodeToEfiKeyFlushState (TerminalDevice
);
1426 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1428 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1430 Key
.ScanCode
= SCAN_NULL
;
1432 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1433 TerminalDevice
->TerminalType
== VT100TYPE
||
1434 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1435 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1436 switch (UnicodeChar
) {
1438 Key
.ScanCode
= SCAN_UP
;
1441 Key
.ScanCode
= SCAN_DOWN
;
1444 Key
.ScanCode
= SCAN_RIGHT
;
1447 Key
.ScanCode
= SCAN_LEFT
;
1450 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1451 TerminalDevice
->TerminalType
== VT100TYPE
) {
1452 Key
.ScanCode
= SCAN_HOME
;
1456 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1457 Key
.ScanCode
= SCAN_END
;
1461 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1462 Key
.ScanCode
= SCAN_END
;
1467 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1468 TerminalDevice
->TerminalType
== VT100TYPE
) {
1469 Key
.ScanCode
= SCAN_INSERT
;
1473 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1474 Key
.ScanCode
= SCAN_DELETE
;
1478 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1479 Key
.ScanCode
= SCAN_DELETE
;
1480 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1481 Key
.ScanCode
= SCAN_F4
;
1485 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1486 Key
.ScanCode
= SCAN_PAGE_UP
;
1490 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1491 Key
.ScanCode
= SCAN_F10
;
1494 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1495 Key
.ScanCode
= SCAN_PAGE_UP
;
1499 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1500 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1504 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1505 Key
.ScanCode
= SCAN_F9
;
1508 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1509 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1513 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1514 Key
.ScanCode
= SCAN_F1
;
1518 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1519 Key
.ScanCode
= SCAN_F2
;
1523 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1524 Key
.ScanCode
= SCAN_F3
;
1528 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1529 Key
.ScanCode
= SCAN_F5
;
1533 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1534 Key
.ScanCode
= SCAN_F6
;
1538 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1539 Key
.ScanCode
= SCAN_F7
;
1543 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1544 Key
.ScanCode
= SCAN_F8
;
1552 if (Key
.ScanCode
!= SCAN_NULL
) {
1553 Key
.UnicodeChar
= 0;
1554 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1555 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1556 UnicodeToEfiKeyFlushState (TerminalDevice
);
1560 UnicodeToEfiKeyFlushState (TerminalDevice
);
1567 // Invalid state. This should never happen.
1571 UnicodeToEfiKeyFlushState (TerminalDevice
);
1576 if (UnicodeChar
== ESC
) {
1577 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1580 if (UnicodeChar
== CSI
) {
1581 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1584 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1585 Status
= gBS
->SetTimer(
1586 TerminalDevice
->TwoSecondTimeOut
,
1590 ASSERT_EFI_ERROR (Status
);
1594 if (SetDefaultResetState
) {
1595 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1598 if (UnicodeChar
== DEL
) {
1599 Key
.ScanCode
= SCAN_DELETE
;
1600 Key
.UnicodeChar
= 0;
1602 Key
.ScanCode
= SCAN_NULL
;
1603 Key
.UnicodeChar
= UnicodeChar
;
1606 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);