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
369 TERMINAL_DEV
*TerminalDevice
;
370 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
372 LIST_ENTRY
*NotifyList
;
373 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
375 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
376 return EFI_INVALID_PARAMETER
;
379 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
382 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
384 NotifyList
= &TerminalDevice
->NotifyList
;
385 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
388 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
390 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
392 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
393 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
394 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
401 // Allocate resource to save the notification function
403 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
404 if (NewNotify
== NULL
) {
405 return EFI_OUT_OF_RESOURCES
;
408 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
409 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
410 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
411 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
413 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
415 Status
= gBS
->InstallMultipleProtocolInterfaces (
416 &NewNotify
->NotifyHandle
,
417 &gSimpleTextInExNotifyGuid
,
421 ASSERT_EFI_ERROR (Status
);
422 *NotifyHandle
= NewNotify
->NotifyHandle
;
429 Remove a registered notification function from a particular keystroke.
431 @param This Protocol instance pointer.
432 @param NotificationHandle The handle of the notification function being
435 @retval EFI_SUCCESS The notification function was unregistered
437 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
438 @retval EFI_NOT_FOUND Can not find the matching entry in database.
443 TerminalConInUnregisterKeyNotify (
444 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
445 IN EFI_HANDLE NotificationHandle
449 TERMINAL_DEV
*TerminalDevice
;
451 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
452 LIST_ENTRY
*NotifyList
;
454 if (NotificationHandle
== NULL
) {
455 return EFI_INVALID_PARAMETER
;
458 Status
= gBS
->OpenProtocol (
460 &gSimpleTextInExNotifyGuid
,
464 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
466 if (EFI_ERROR (Status
)) {
467 return EFI_INVALID_PARAMETER
;
470 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
472 NotifyList
= &TerminalDevice
->NotifyList
;
473 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
476 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
478 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
480 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
482 // Remove the notification function from NotifyList and free resources
484 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
485 Status
= gBS
->UninstallMultipleProtocolInterfaces (
486 CurrentNotify
->NotifyHandle
,
487 &gSimpleTextInExNotifyGuid
,
491 ASSERT_EFI_ERROR (Status
);
492 gBS
->FreePool (CurrentNotify
);
497 return EFI_NOT_FOUND
;
501 Translate raw data into Unicode (according to different encode), and
502 translate Unicode into key information. (according to different standard).
504 @param TerminalDevice Terminal driver private structure.
508 TranslateRawDataToEfiKey (
509 IN TERMINAL_DEV
*TerminalDevice
512 switch (TerminalDevice
->TerminalType
) {
517 AnsiRawDataToUnicode (TerminalDevice
);
518 UnicodeToEfiKey (TerminalDevice
);
523 // Process all the raw data in the RawFIFO,
524 // put the processed key into UnicodeFIFO.
526 VTUTF8RawDataToUnicode (TerminalDevice
);
529 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
530 // then put into EfiKeyFIFO.
532 UnicodeToEfiKey (TerminalDevice
);
539 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
540 Signal the event if there is key available
542 @param Event Indicates the event that invoke this function.
543 @param Context Indicates the calling context.
548 TerminalConInWaitForKey (
554 // Someone is waiting on the keystroke event, if there's
555 // a key pending, signal the event
557 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
559 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
561 gBS
->SignalEvent (Event
);
567 Check for a pending key in the Efi Key FIFO or Serial device buffer.
569 @param This Indicates the calling context.
571 @retval EFI_SUCCESS There is key pending.
572 @retval EFI_NOT_READY There is no key pending.
573 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
577 TerminalConInCheckForKey (
578 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
582 TERMINAL_DEV
*TerminalDevice
;
585 EFI_SERIAL_IO_MODE
*Mode
;
586 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
587 UINTN SerialInTimeOut
;
589 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
591 SerialIo
= TerminalDevice
->SerialIo
;
592 if (SerialIo
== NULL
) {
593 return EFI_DEVICE_ERROR
;
596 // if current timeout value for serial device is not identical with
597 // the value saved in TERMINAL_DEV structure, then recalculate the
598 // timeout value again and set serial attribute according to this value.
600 Mode
= SerialIo
->Mode
;
601 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
604 if (Mode
->BaudRate
!= 0) {
606 // According to BAUD rate to calculate the timeout value.
608 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
611 Status
= SerialIo
->SetAttributes (
614 Mode
->ReceiveFifoDepth
,
615 (UINT32
) SerialInTimeOut
,
616 (EFI_PARITY_TYPE
) (Mode
->Parity
),
617 (UINT8
) Mode
->DataBits
,
618 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
621 if (EFI_ERROR (Status
)) {
622 TerminalDevice
->SerialInTimeOut
= 0;
624 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
628 // Check whether serial buffer is empty.
630 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
632 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
634 // Translate all the raw data in RawFIFO into EFI Key,
635 // according to different terminal type supported.
637 TranslateRawDataToEfiKey (TerminalDevice
);
640 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
643 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
646 return EFI_NOT_READY
;
650 // Fetch all the keys in the serial buffer,
651 // and insert the byte stream into RawFIFO.
655 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
657 if (EFI_ERROR (Status
)) {
658 if (Status
== EFI_DEVICE_ERROR
) {
659 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
660 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
661 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
662 TerminalDevice
->DevicePath
668 RawFiFoInsertOneKey (TerminalDevice
, Input
);
672 // Translate all the raw data in RawFIFO into EFI Key,
673 // according to different terminal type supported.
675 TranslateRawDataToEfiKey (TerminalDevice
);
677 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
678 return EFI_NOT_READY
;
685 Get one key out of serial buffer.
687 @param SerialIo Serial I/O protocol attached to the serial device.
688 @param Output The fetched key.
690 @retval EFI_NOT_READY If serial buffer is empty.
691 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
692 @retval EFI_SUCCESS If reading serial buffer successfully, put
693 the fetched key to the parameter output.
697 GetOneKeyFromSerial (
698 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
709 // Read one key from serial I/O device.
711 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
713 if (EFI_ERROR (Status
)) {
715 if (Status
== EFI_TIMEOUT
) {
716 return EFI_NOT_READY
;
719 return EFI_DEVICE_ERROR
;
724 return EFI_NOT_READY
;
731 Insert one byte raw data into the Raw Data FIFO.
733 @param TerminalDevice Terminal driver private structure.
734 @param Input The key will be input.
736 @retval TRUE If insert successfully.
737 @retval FLASE If Raw Data buffer is full before key insertion,
742 RawFiFoInsertOneKey (
743 TERMINAL_DEV
*TerminalDevice
,
749 Tail
= TerminalDevice
->RawFiFo
->Tail
;
751 if (IsRawFiFoFull (TerminalDevice
)) {
758 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
760 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
766 Remove one pre-fetched key out of the Raw Data FIFO.
768 @param TerminalDevice Terminal driver private structure.
769 @param Output The key will be removed.
771 @retval TRUE If insert successfully.
772 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
776 RawFiFoRemoveOneKey (
777 TERMINAL_DEV
*TerminalDevice
,
783 Head
= TerminalDevice
->RawFiFo
->Head
;
785 if (IsRawFiFoEmpty (TerminalDevice
)) {
793 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
795 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
801 Clarify whether Raw Data FIFO buffer is empty.
803 @param TerminalDevice Terminal driver private structure
805 @retval TRUE If Raw Data FIFO buffer is empty.
806 @retval FLASE If Raw Data FIFO buffer is not empty.
811 TERMINAL_DEV
*TerminalDevice
814 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
822 Clarify whether Raw Data FIFO buffer is full.
824 @param TerminalDevice Terminal driver private structure
826 @retval TRUE If Raw Data FIFO buffer is full.
827 @retval FLASE If Raw Data FIFO buffer is not full.
832 TERMINAL_DEV
*TerminalDevice
838 Tail
= TerminalDevice
->RawFiFo
->Tail
;
839 Head
= TerminalDevice
->RawFiFo
->Head
;
841 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
850 Insert one pre-fetched key into the FIFO buffer.
852 @param TerminalDevice Terminal driver private structure.
853 @param Key The key will be input.
855 @retval TRUE If insert successfully.
856 @retval FLASE If FIFO buffer is full before key insertion,
861 EfiKeyFiFoInsertOneKey (
862 TERMINAL_DEV
*TerminalDevice
,
868 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
869 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
871 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
873 // Efi Key FIFO is full
878 TerminalDevice
->EfiKeyFiFo
->Data
[Tail
] = Key
;
880 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
886 Remove one pre-fetched key out of the FIFO buffer.
888 @param TerminalDevice Terminal driver private structure.
889 @param Output The key will be removed.
891 @retval TRUE If insert successfully.
892 @retval FLASE If FIFO buffer is empty before remove operation.
896 EfiKeyFiFoRemoveOneKey (
897 TERMINAL_DEV
*TerminalDevice
,
898 EFI_INPUT_KEY
*Output
903 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
904 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
906 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
910 Output
->ScanCode
= SCAN_NULL
;
911 Output
->UnicodeChar
= 0;
915 *Output
= TerminalDevice
->EfiKeyFiFo
->Data
[Head
];
917 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
923 Clarify whether FIFO buffer is empty.
925 @param TerminalDevice Terminal driver private structure
927 @retval TRUE If FIFO buffer is empty.
928 @retval FLASE If FIFO buffer is not empty.
933 TERMINAL_DEV
*TerminalDevice
936 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
944 Clarify whether FIFO buffer is full.
946 @param TerminalDevice Terminal driver private structure
948 @retval TRUE If FIFO buffer is full.
949 @retval FLASE If FIFO buffer is not full.
954 TERMINAL_DEV
*TerminalDevice
960 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
961 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
963 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
972 Insert one pre-fetched key into the Unicode FIFO buffer.
974 @param TerminalDevice Terminal driver private structure.
975 @param Input The key will be input.
977 @retval TRUE If insert successfully.
978 @retval FLASE If Unicode FIFO buffer is full before key insertion,
983 UnicodeFiFoInsertOneKey (
984 TERMINAL_DEV
*TerminalDevice
,
990 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
991 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
994 if (IsUnicodeFiFoFull (TerminalDevice
)) {
996 // Unicode FIFO is full
1001 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1003 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1009 Remove one pre-fetched key out of the Unicode FIFO buffer.
1011 @param TerminalDevice Terminal driver private structure.
1012 @param Output The key will be removed.
1014 @retval TRUE If insert successfully.
1015 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
1019 UnicodeFiFoRemoveOneKey (
1020 TERMINAL_DEV
*TerminalDevice
,
1026 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1027 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1029 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1037 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1039 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1045 Clarify whether Unicode FIFO buffer is empty.
1047 @param TerminalDevice Terminal driver private structure
1049 @retval TRUE If Unicode FIFO buffer is empty.
1050 @retval FLASE If Unicode FIFO buffer is not empty.
1054 IsUnicodeFiFoEmpty (
1055 TERMINAL_DEV
*TerminalDevice
1058 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1066 Clarify whether Unicode FIFO buffer is full.
1068 @param TerminalDevice Terminal driver private structure
1070 @retval TRUE If Unicode FIFO buffer is full.
1071 @retval FLASE If Unicode FIFO buffer is not full.
1076 TERMINAL_DEV
*TerminalDevice
1082 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1083 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1085 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1094 Count Unicode FIFO buffer.
1096 @param TerminalDevice Terminal driver private structure
1098 @return The count in bytes of Unicode FIFO.
1102 UnicodeFiFoGetKeyCount (
1103 TERMINAL_DEV
*TerminalDevice
1109 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1110 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1113 return (UINT8
) (Tail
- Head
);
1115 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1120 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1122 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1126 UnicodeToEfiKeyFlushState (
1127 IN TERMINAL_DEV
*TerminalDevice
1133 InputState
= TerminalDevice
->InputState
;
1135 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1136 Key
.ScanCode
= SCAN_ESC
;
1137 Key
.UnicodeChar
= 0;
1138 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1141 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1142 Key
.ScanCode
= SCAN_NULL
;
1143 Key
.UnicodeChar
= CSI
;
1144 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1147 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1148 Key
.ScanCode
= SCAN_NULL
;
1149 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1150 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1153 if ((InputState
& INPUT_STATE_O
) != 0) {
1154 Key
.ScanCode
= SCAN_NULL
;
1155 Key
.UnicodeChar
= 'O';
1156 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1159 if ((InputState
& INPUT_STATE_2
) != 0) {
1160 Key
.ScanCode
= SCAN_NULL
;
1161 Key
.UnicodeChar
= '2';
1162 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1166 // Cancel the timer.
1169 TerminalDevice
->TwoSecondTimeOut
,
1174 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1179 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1180 can be read through the Simple Input Protocol.
1182 The table below shows the keyboard input mappings that this function supports.
1183 If the ESC sequence listed in one of the columns is presented, then it is translated
1184 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1185 key strokes are converted into EFI Keys.
1187 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1188 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1189 converted into EFI Keys.
1190 There is one special input sequence that will force the system to reset.
1191 This is ESC R ESC r ESC R.
1193 Symbols used in table below
1194 ===========================
1200 +=========+======+===========+==========+==========+
1201 | | EFI | UEFI 2.0 | | |
1202 | | Scan | | VT100+ | |
1203 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1204 +=========+======+===========+==========+==========+
1205 | NULL | 0x00 | | | |
1206 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1207 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1208 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1209 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1210 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1211 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1212 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1213 | | | ESC [ L | | ESC [ L |
1214 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1215 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1217 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1219 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1220 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1221 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1222 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1223 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1224 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1225 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1226 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1227 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1228 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1229 | Escape | 0x17 | ESC | ESC | ESC |
1230 | F11 | 0x15 | | ESC ! | |
1231 | F12 | 0x16 | | ESC @ | |
1232 +=========+======+===========+==========+==========+
1236 ESC R ESC r ESC R = Reset System
1238 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1243 IN TERMINAL_DEV
*TerminalDevice
1247 EFI_STATUS TimerStatus
;
1250 BOOLEAN SetDefaultResetState
;
1252 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1254 if (!EFI_ERROR (TimerStatus
)) {
1255 UnicodeToEfiKeyFlushState (TerminalDevice
);
1256 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1259 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1261 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1263 // Check to see if the 2 seconds timer has expired
1265 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1266 if (!EFI_ERROR (TimerStatus
)) {
1267 UnicodeToEfiKeyFlushState (TerminalDevice
);
1268 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1273 // Fetch one Unicode character from the Unicode FIFO
1275 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1277 SetDefaultResetState
= TRUE
;
1279 switch (TerminalDevice
->InputState
) {
1280 case INPUT_STATE_DEFAULT
:
1284 case INPUT_STATE_ESC
:
1286 if (UnicodeChar
== LEFTOPENBRACKET
) {
1287 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1288 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1292 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1293 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1294 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1298 Key
.ScanCode
= SCAN_NULL
;
1300 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1301 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1302 switch (UnicodeChar
) {
1304 Key
.ScanCode
= SCAN_F1
;
1307 Key
.ScanCode
= SCAN_F2
;
1310 Key
.ScanCode
= SCAN_F3
;
1313 Key
.ScanCode
= SCAN_F4
;
1316 Key
.ScanCode
= SCAN_F5
;
1319 Key
.ScanCode
= SCAN_F6
;
1322 Key
.ScanCode
= SCAN_F7
;
1325 Key
.ScanCode
= SCAN_F8
;
1328 Key
.ScanCode
= SCAN_F9
;
1331 Key
.ScanCode
= SCAN_F10
;
1334 Key
.ScanCode
= SCAN_F11
;
1337 Key
.ScanCode
= SCAN_F12
;
1340 Key
.ScanCode
= SCAN_HOME
;
1343 Key
.ScanCode
= SCAN_END
;
1346 Key
.ScanCode
= SCAN_INSERT
;
1349 Key
.ScanCode
= SCAN_DELETE
;
1352 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1355 Key
.ScanCode
= SCAN_PAGE_UP
;
1362 switch (UnicodeChar
) {
1364 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1365 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1366 SetDefaultResetState
= FALSE
;
1367 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1368 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1370 Key
.ScanCode
= SCAN_NULL
;
1373 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1374 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1375 SetDefaultResetState
= FALSE
;
1377 Key
.ScanCode
= SCAN_NULL
;
1383 if (SetDefaultResetState
) {
1384 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1387 if (Key
.ScanCode
!= SCAN_NULL
) {
1388 Key
.UnicodeChar
= 0;
1389 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1390 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1391 UnicodeToEfiKeyFlushState (TerminalDevice
);
1395 UnicodeToEfiKeyFlushState (TerminalDevice
);
1399 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1401 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1403 Key
.ScanCode
= SCAN_NULL
;
1405 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1406 switch (UnicodeChar
) {
1408 Key
.ScanCode
= SCAN_F1
;
1411 Key
.ScanCode
= SCAN_F2
;
1414 Key
.ScanCode
= SCAN_F3
;
1417 Key
.ScanCode
= SCAN_F4
;
1420 Key
.ScanCode
= SCAN_F5
;
1423 Key
.ScanCode
= SCAN_F6
;
1426 Key
.ScanCode
= SCAN_F7
;
1429 Key
.ScanCode
= SCAN_F8
;
1432 Key
.ScanCode
= SCAN_F9
;
1435 Key
.ScanCode
= SCAN_F10
;
1442 if (Key
.ScanCode
!= SCAN_NULL
) {
1443 Key
.UnicodeChar
= 0;
1444 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1445 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1446 UnicodeToEfiKeyFlushState (TerminalDevice
);
1450 UnicodeToEfiKeyFlushState (TerminalDevice
);
1454 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1456 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1458 Key
.ScanCode
= SCAN_NULL
;
1460 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1461 TerminalDevice
->TerminalType
== VT100TYPE
||
1462 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1463 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1464 switch (UnicodeChar
) {
1466 Key
.ScanCode
= SCAN_UP
;
1469 Key
.ScanCode
= SCAN_DOWN
;
1472 Key
.ScanCode
= SCAN_RIGHT
;
1475 Key
.ScanCode
= SCAN_LEFT
;
1478 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1479 TerminalDevice
->TerminalType
== VT100TYPE
) {
1480 Key
.ScanCode
= SCAN_HOME
;
1484 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1485 Key
.ScanCode
= SCAN_END
;
1489 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1490 Key
.ScanCode
= SCAN_END
;
1495 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1496 TerminalDevice
->TerminalType
== VT100TYPE
) {
1497 Key
.ScanCode
= SCAN_INSERT
;
1501 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1502 Key
.ScanCode
= SCAN_DELETE
;
1506 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1507 Key
.ScanCode
= SCAN_DELETE
;
1508 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1509 Key
.ScanCode
= SCAN_F4
;
1513 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1514 Key
.ScanCode
= SCAN_PAGE_UP
;
1518 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1519 Key
.ScanCode
= SCAN_F10
;
1522 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1523 Key
.ScanCode
= SCAN_PAGE_UP
;
1527 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1528 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1532 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1533 Key
.ScanCode
= SCAN_F9
;
1536 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1537 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1541 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1542 Key
.ScanCode
= SCAN_F1
;
1546 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1547 Key
.ScanCode
= SCAN_F2
;
1551 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1552 Key
.ScanCode
= SCAN_F3
;
1556 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1557 Key
.ScanCode
= SCAN_F5
;
1561 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1562 Key
.ScanCode
= SCAN_F6
;
1566 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1567 Key
.ScanCode
= SCAN_F7
;
1571 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1572 Key
.ScanCode
= SCAN_F8
;
1580 if (Key
.ScanCode
!= SCAN_NULL
) {
1581 Key
.UnicodeChar
= 0;
1582 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1583 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1584 UnicodeToEfiKeyFlushState (TerminalDevice
);
1588 UnicodeToEfiKeyFlushState (TerminalDevice
);
1595 // Invalid state. This should never happen.
1599 UnicodeToEfiKeyFlushState (TerminalDevice
);
1604 if (UnicodeChar
== ESC
) {
1605 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1608 if (UnicodeChar
== CSI
) {
1609 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1612 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1613 Status
= gBS
->SetTimer(
1614 TerminalDevice
->TwoSecondTimeOut
,
1618 ASSERT_EFI_ERROR (Status
);
1622 if (SetDefaultResetState
) {
1623 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1626 if (UnicodeChar
== DEL
) {
1627 Key
.ScanCode
= SCAN_DELETE
;
1628 Key
.UnicodeChar
= 0;
1630 Key
.ScanCode
= SCAN_NULL
;
1631 Key
.UnicodeChar
= UnicodeChar
;
1634 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);