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 @return EFI_SUCCESS The reset operation succeeds.
96 @return 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 // clear all the internal buffer for keys
125 InitializeRawFiFo (TerminalDevice
);
126 InitializeUnicodeFiFo (TerminalDevice
);
127 InitializeEfiKeyFiFo (TerminalDevice
);
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 @return EFI_SUCCESS The keystroke information is returned successfully.
149 @return EFI_NOT_READY There is no keystroke data available.
150 @return 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.
226 TerminalConInWaitForKeyEx (
231 TERMINAL_DEV
*TerminalDevice
;
233 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context
);
235 TerminalConInWaitForKey (Event
, &TerminalDevice
->SimpleInput
);
240 // Simple Text Input Ex protocol functions
244 Reset the input device and optionally run diagnostics
246 @param This Protocol instance pointer.
247 @param ExtendedVerification Driver may perform diagnostics on reset.
249 @retval EFI_SUCCESS The device was reset.
250 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
256 TerminalConInResetEx (
257 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
258 IN BOOLEAN ExtendedVerification
262 TERMINAL_DEV
*TerminalDevice
;
264 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
266 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
267 if (EFI_ERROR (Status
)) {
268 return EFI_DEVICE_ERROR
;
277 Reads the next keystroke from the input device. The WaitForKey Event can
278 be used to test for existence of a keystroke via WaitForEvent () call.
280 @param This Protocol instance pointer.
281 @param KeyData A pointer to a buffer that is filled in with the
282 keystroke state data for the key that was
285 @retval EFI_SUCCESS The keystroke information was returned.
286 @retval EFI_NOT_READY There was no keystroke data available.
287 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
289 @retval EFI_INVALID_PARAMETER KeyData is NULL.
294 TerminalConInReadKeyStrokeEx (
295 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
296 OUT EFI_KEY_DATA
*KeyData
299 TERMINAL_DEV
*TerminalDevice
;
301 if (KeyData
== NULL
) {
302 return EFI_INVALID_PARAMETER
;
305 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
307 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
313 Set certain state for the input device.
315 @param This Protocol instance pointer.
316 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
317 state for the input device.
319 @retval EFI_SUCCESS The device state was set successfully.
320 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
321 could not have the setting adjusted.
322 @retval EFI_UNSUPPORTED The device does not have the ability to set its
324 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
329 TerminalConInSetState (
330 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
331 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
334 if (KeyToggleState
== NULL
) {
335 return EFI_INVALID_PARAMETER
;
343 Register a notification function for a particular keystroke for the input device.
345 @param This Protocol instance pointer.
346 @param KeyData A pointer to a buffer that is filled in with the
347 keystroke information data for the key that was
349 @param KeyNotificationFunction Points to the function to be called when the key
350 sequence is typed specified by KeyData.
351 @param NotifyHandle Points to the unique handle assigned to the
352 registered notification.
354 @retval EFI_SUCCESS The notification function was registered
356 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
358 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
363 TerminalConInRegisterKeyNotify (
364 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
365 IN EFI_KEY_DATA
*KeyData
,
366 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
367 OUT EFI_HANDLE
*NotifyHandle
371 TERMINAL_DEV
*TerminalDevice
;
372 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
374 LIST_ENTRY
*NotifyList
;
375 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
377 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
378 return EFI_INVALID_PARAMETER
;
381 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
384 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
386 NotifyList
= &TerminalDevice
->NotifyList
;
387 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
390 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
392 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
394 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
395 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
396 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
403 // Allocate resource to save the notification function
405 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
406 if (NewNotify
== NULL
) {
407 return EFI_OUT_OF_RESOURCES
;
410 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
411 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
412 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
413 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
415 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
417 Status
= gBS
->InstallMultipleProtocolInterfaces (
418 &NewNotify
->NotifyHandle
,
419 &gSimpleTextInExNotifyGuid
,
423 ASSERT_EFI_ERROR (Status
);
424 *NotifyHandle
= NewNotify
->NotifyHandle
;
431 Remove a registered notification function from a particular keystroke.
433 @param This Protocol instance pointer.
434 @param NotificationHandle The handle of the notification function being
437 @retval EFI_SUCCESS The notification function was unregistered
439 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
440 @retval EFI_NOT_FOUND Can not find the matching entry in database.
445 TerminalConInUnregisterKeyNotify (
446 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
447 IN EFI_HANDLE NotificationHandle
451 TERMINAL_DEV
*TerminalDevice
;
453 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
454 LIST_ENTRY
*NotifyList
;
456 if (NotificationHandle
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
460 Status
= gBS
->OpenProtocol (
462 &gSimpleTextInExNotifyGuid
,
466 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
468 if (EFI_ERROR (Status
)) {
469 return EFI_INVALID_PARAMETER
;
472 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
474 NotifyList
= &TerminalDevice
->NotifyList
;
475 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
478 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
480 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
482 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
484 // Remove the notification function from NotifyList and free resources
486 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
487 Status
= gBS
->UninstallMultipleProtocolInterfaces (
488 CurrentNotify
->NotifyHandle
,
489 &gSimpleTextInExNotifyGuid
,
493 ASSERT_EFI_ERROR (Status
);
494 gBS
->FreePool (CurrentNotify
);
499 return EFI_NOT_FOUND
;
503 Translate raw data into Unicode (according to different encode), and
504 translate Unicode into key information. (according to different standard).
506 @param TerminalDevice Terminal driver private structure.
512 TranslateRawDataToEfiKey (
513 IN TERMINAL_DEV
*TerminalDevice
516 switch (TerminalDevice
->TerminalType
) {
521 AnsiRawDataToUnicode (TerminalDevice
);
522 UnicodeToEfiKey (TerminalDevice
);
527 // Process all the raw data in the RawFIFO,
528 // put the processed key into UnicodeFIFO.
530 VTUTF8RawDataToUnicode (TerminalDevice
);
533 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
534 // then put into EfiKeyFIFO.
536 UnicodeToEfiKey (TerminalDevice
);
543 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
544 Signal the event if there is key available
546 @param Event Indicates the event that invoke this function.
547 @param Context Indicates the calling context.
554 TerminalConInWaitForKey (
560 // Someone is waiting on the keystroke event, if there's
561 // a key pending, signal the event
563 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
565 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
567 gBS
->SignalEvent (Event
);
573 Check for a pending key in the Efi Key FIFO or Serial device buffer.
575 @param This Indicates the calling context.
577 @retval EFI_SUCCESS There is key pending.
578 @retval EFI_NOT_READY There is no key pending.
579 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
583 TerminalConInCheckForKey (
584 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
588 TERMINAL_DEV
*TerminalDevice
;
591 EFI_SERIAL_IO_MODE
*Mode
;
592 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
593 UINTN SerialInTimeOut
;
595 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
597 SerialIo
= TerminalDevice
->SerialIo
;
598 if (SerialIo
== NULL
) {
599 return EFI_DEVICE_ERROR
;
602 // if current timeout value for serial device is not identical with
603 // the value saved in TERMINAL_DEV structure, then recalculate the
604 // timeout value again and set serial attribute according to this value.
606 Mode
= SerialIo
->Mode
;
607 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
610 if (Mode
->BaudRate
!= 0) {
612 // According to BAUD rate to calculate the timeout value.
614 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
617 Status
= SerialIo
->SetAttributes (
620 Mode
->ReceiveFifoDepth
,
621 (UINT32
) SerialInTimeOut
,
622 (EFI_PARITY_TYPE
) (Mode
->Parity
),
623 (UINT8
) Mode
->DataBits
,
624 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
627 if (EFI_ERROR (Status
)) {
628 TerminalDevice
->SerialInTimeOut
= 0;
630 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
634 // Check whether serial buffer is empty.
636 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
638 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
640 // Translate all the raw data in RawFIFO into EFI Key,
641 // according to different terminal type supported.
643 TranslateRawDataToEfiKey (TerminalDevice
);
646 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
649 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
652 return EFI_NOT_READY
;
656 // Fetch all the keys in the serial buffer,
657 // and insert the byte stream into RawFIFO.
661 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
663 if (EFI_ERROR (Status
)) {
664 if (Status
== EFI_DEVICE_ERROR
) {
665 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
666 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
667 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
668 TerminalDevice
->DevicePath
674 RawFiFoInsertOneKey (TerminalDevice
, Input
);
678 // Translate all the raw data in RawFIFO into EFI Key,
679 // according to different terminal type supported.
681 TranslateRawDataToEfiKey (TerminalDevice
);
683 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
684 return EFI_NOT_READY
;
691 Get one key out of serial buffer.
693 @param SerialIo Serial I/O protocol attached to the serial device.
694 @param Output The fetched key.
696 @return EFI_NOT_READY If serial buffer is empty.
697 @return EFI_DEVICE_ERROR If reading serial buffer encounter error.
698 @return EFI_SUCCESS If reading serial buffer successfully, put
699 the fetched key to the parameter output.
703 GetOneKeyFromSerial (
704 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
715 // Read one key from serial I/O device.
717 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
719 if (EFI_ERROR (Status
)) {
721 if (Status
== EFI_TIMEOUT
) {
722 return EFI_NOT_READY
;
725 return EFI_DEVICE_ERROR
;
730 return EFI_NOT_READY
;
737 Insert one byte raw data into the Raw Data FIFO.
739 @param TerminalDevice Terminal driver private structure.
740 @param Input The key will be input.
742 @return TRUE If insert successfully.
743 @return FLASE If Raw Data buffer is full before key insertion,
748 RawFiFoInsertOneKey (
749 TERMINAL_DEV
*TerminalDevice
,
755 Tail
= TerminalDevice
->RawFiFo
.Tail
;
757 if (IsRawFiFoFull (TerminalDevice
)) {
764 TerminalDevice
->RawFiFo
.Data
[Tail
] = Input
;
766 TerminalDevice
->RawFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
772 Remove one pre-fetched key out of the Raw Data FIFO.
774 @param TerminalDevice Terminal driver private structure.
775 @param Output The key will be removed.
777 @return TRUE If insert successfully.
778 @return FLASE If Raw Data FIFO buffer is empty before remove operation.
782 RawFiFoRemoveOneKey (
783 TERMINAL_DEV
*TerminalDevice
,
789 Head
= TerminalDevice
->RawFiFo
.Head
;
791 if (IsRawFiFoEmpty (TerminalDevice
)) {
799 *Output
= TerminalDevice
->RawFiFo
.Data
[Head
];
801 TerminalDevice
->RawFiFo
.Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
807 Clarify whether Raw Data FIFO buffer is empty.
809 @param TerminalDevice Terminal driver private structure
811 @return TRUE If Raw Data FIFO buffer is empty.
812 @return FLASE If Raw Data FIFO buffer is not empty.
817 TERMINAL_DEV
*TerminalDevice
820 if (TerminalDevice
->RawFiFo
.Head
== TerminalDevice
->RawFiFo
.Tail
) {
828 Clarify whether Raw Data FIFO buffer is full.
830 @param TerminalDevice Terminal driver private structure
832 @return TRUE If Raw Data FIFO buffer is full.
833 @return FLASE If Raw Data FIFO buffer is not full.
838 TERMINAL_DEV
*TerminalDevice
844 Tail
= TerminalDevice
->RawFiFo
.Tail
;
845 Head
= TerminalDevice
->RawFiFo
.Head
;
847 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
856 Insert one pre-fetched key into the FIFO buffer.
858 @param TerminalDevice Terminal driver private structure.
859 @param Key The key will be input.
861 @return TRUE If insert successfully.
862 @return FLASE If FIFO buffer is full before key insertion,
867 EfiKeyFiFoInsertOneKey (
868 TERMINAL_DEV
*TerminalDevice
,
874 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
876 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
878 // Efi Key FIFO is full
883 TerminalDevice
->EfiKeyFiFo
.Data
[Tail
] = Key
;
885 TerminalDevice
->EfiKeyFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
891 Remove one pre-fetched key out of the FIFO buffer.
893 @param TerminalDevice Terminal driver private structure.
894 @param Output The key will be removed.
896 @return TRUE If insert successfully.
897 @return FLASE If FIFO buffer is empty before remove operation.
901 EfiKeyFiFoRemoveOneKey (
902 TERMINAL_DEV
*TerminalDevice
,
903 EFI_INPUT_KEY
*Output
908 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
910 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
914 Output
->ScanCode
= SCAN_NULL
;
915 Output
->UnicodeChar
= 0;
919 *Output
= TerminalDevice
->EfiKeyFiFo
.Data
[Head
];
921 TerminalDevice
->EfiKeyFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
927 Clarify whether FIFO buffer is empty.
929 @param TerminalDevice Terminal driver private structure
931 @return TRUE If FIFO buffer is empty.
932 @return FLASE If FIFO buffer is not empty.
937 TERMINAL_DEV
*TerminalDevice
940 if (TerminalDevice
->EfiKeyFiFo
.Head
== TerminalDevice
->EfiKeyFiFo
.Tail
) {
948 Clarify whether FIFO buffer is full.
950 @param TerminalDevice Terminal driver private structure
952 @return TRUE If FIFO buffer is full.
953 @return FLASE If FIFO buffer is not full.
958 TERMINAL_DEV
*TerminalDevice
964 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
965 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
967 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
976 Insert one pre-fetched key into the Unicode FIFO buffer.
978 @param TerminalDevice Terminal driver private structure.
979 @param Input The key will be input.
981 @return TRUE If insert successfully.
982 @return FLASE If Unicode FIFO buffer is full before key insertion,
987 UnicodeFiFoInsertOneKey (
988 TERMINAL_DEV
*TerminalDevice
,
994 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
996 if (IsUnicodeFiFoFull (TerminalDevice
)) {
998 // Unicode FIFO is full
1003 TerminalDevice
->UnicodeFiFo
.Data
[Tail
] = Input
;
1005 TerminalDevice
->UnicodeFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1011 Remove one pre-fetched key out of the Unicode FIFO buffer.
1013 @param TerminalDevice Terminal driver private structure.
1014 @param Output The key will be removed.
1016 @return TRUE If insert successfully.
1017 @return FLASE If Unicode FIFO buffer is empty before remove operation.
1021 UnicodeFiFoRemoveOneKey (
1022 TERMINAL_DEV
*TerminalDevice
,
1028 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1030 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1038 *Output
= TerminalDevice
->UnicodeFiFo
.Data
[Head
];
1040 TerminalDevice
->UnicodeFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1046 Clarify whether Unicode FIFO buffer is empty.
1048 @param TerminalDevice Terminal driver private structure
1050 @return TRUE If Unicode FIFO buffer is empty.
1051 @return FLASE If Unicode FIFO buffer is not empty.
1055 IsUnicodeFiFoEmpty (
1056 TERMINAL_DEV
*TerminalDevice
1059 if (TerminalDevice
->UnicodeFiFo
.Head
== TerminalDevice
->UnicodeFiFo
.Tail
) {
1067 Clarify whether Unicode FIFO buffer is full.
1069 @param TerminalDevice Terminal driver private structure
1071 @return TRUE If Unicode FIFO buffer is full.
1072 @return FLASE If Unicode FIFO buffer is not full.
1077 TERMINAL_DEV
*TerminalDevice
1083 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1084 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1086 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1095 Count Unicode FIFO buffer.
1097 @param TerminalDevice Terminal driver private structure
1099 @return The count in bytes of Unicode FIFO.
1103 UnicodeFiFoGetKeyCount (
1104 TERMINAL_DEV
*TerminalDevice
1110 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1111 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1114 return (UINT8
) (Tail
- Head
);
1116 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1121 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1123 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1129 UnicodeToEfiKeyFlushState (
1130 IN TERMINAL_DEV
*TerminalDevice
1136 InputState
= TerminalDevice
->InputState
;
1138 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1139 Key
.ScanCode
= SCAN_ESC
;
1140 Key
.UnicodeChar
= 0;
1141 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1144 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1145 Key
.ScanCode
= SCAN_NULL
;
1146 Key
.UnicodeChar
= CSI
;
1147 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1150 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1151 Key
.ScanCode
= SCAN_NULL
;
1152 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1153 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1156 if ((InputState
& INPUT_STATE_O
) != 0) {
1157 Key
.ScanCode
= SCAN_NULL
;
1158 Key
.UnicodeChar
= 'O';
1159 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1162 if ((InputState
& INPUT_STATE_2
) != 0) {
1163 Key
.ScanCode
= SCAN_NULL
;
1164 Key
.UnicodeChar
= '2';
1165 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1169 // Cancel the timer.
1172 TerminalDevice
->TwoSecondTimeOut
,
1177 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1182 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1183 can be read through the Simple Input Protocol.
1185 The table below shows the keyboard input mappings that this function supports.
1186 If the ESC sequence listed in one of the columns is presented, then it is translated
1187 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1188 key strokes are converted into EFI Keys.
1190 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1191 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1192 converted into EFI Keys.
1193 There is one special input sequence that will force the system to reset.
1194 This is ESC R ESC r ESC R.
1196 Symbols used in table below
1197 ===========================
1203 +=========+======+===========+==========+==========+
1204 | | EFI | UEFI 2.0 | | |
1205 | | Scan | | VT100+ | |
1206 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1207 +=========+======+===========+==========+==========+
1208 | NULL | 0x00 | | | |
1209 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1210 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1211 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1212 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1213 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1214 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1215 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1216 | | | ESC [ L | | ESC [ L |
1217 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1218 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1220 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1222 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1223 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1224 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1225 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1226 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1227 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1228 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1229 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1230 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1231 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1232 | Escape | 0x17 | ESC | ESC | ESC |
1233 | F11 | 0x15 | | ESC ! | |
1234 | F12 | 0x16 | | ESC @ | |
1235 +=========+======+===========+==========+==========+
1239 ESC R ESC r ESC R = Reset System
1241 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1248 IN TERMINAL_DEV
*TerminalDevice
1252 EFI_STATUS TimerStatus
;
1255 BOOLEAN SetDefaultResetState
;
1257 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1259 if (!EFI_ERROR (TimerStatus
)) {
1260 UnicodeToEfiKeyFlushState (TerminalDevice
);
1261 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1264 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1266 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1268 // Check to see if the 2 second timer has expired
1270 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1271 if (!EFI_ERROR (TimerStatus
)) {
1272 UnicodeToEfiKeyFlushState (TerminalDevice
);
1273 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1278 // Fetch one Unicode character from the Unicode FIFO
1280 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1282 SetDefaultResetState
= TRUE
;
1284 switch (TerminalDevice
->InputState
) {
1285 case INPUT_STATE_DEFAULT
:
1289 case INPUT_STATE_ESC
:
1291 if (UnicodeChar
== LEFTOPENBRACKET
) {
1292 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1293 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1297 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1298 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1299 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1303 Key
.ScanCode
= SCAN_NULL
;
1305 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1306 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1307 switch (UnicodeChar
) {
1309 Key
.ScanCode
= SCAN_F1
;
1312 Key
.ScanCode
= SCAN_F2
;
1315 Key
.ScanCode
= SCAN_F3
;
1318 Key
.ScanCode
= SCAN_F4
;
1321 Key
.ScanCode
= SCAN_F5
;
1324 Key
.ScanCode
= SCAN_F6
;
1327 Key
.ScanCode
= SCAN_F7
;
1330 Key
.ScanCode
= SCAN_F8
;
1333 Key
.ScanCode
= SCAN_F9
;
1336 Key
.ScanCode
= SCAN_F10
;
1339 Key
.ScanCode
= SCAN_F11
;
1342 Key
.ScanCode
= SCAN_F12
;
1345 Key
.ScanCode
= SCAN_HOME
;
1348 Key
.ScanCode
= SCAN_END
;
1351 Key
.ScanCode
= SCAN_INSERT
;
1354 Key
.ScanCode
= SCAN_DELETE
;
1357 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1360 Key
.ScanCode
= SCAN_PAGE_UP
;
1367 switch (UnicodeChar
) {
1369 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1370 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1371 SetDefaultResetState
= FALSE
;
1372 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1373 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1375 Key
.ScanCode
= SCAN_NULL
;
1378 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1379 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1380 SetDefaultResetState
= FALSE
;
1382 Key
.ScanCode
= SCAN_NULL
;
1388 if (SetDefaultResetState
) {
1389 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1392 if (Key
.ScanCode
!= SCAN_NULL
) {
1393 Key
.UnicodeChar
= 0;
1394 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1395 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1396 UnicodeToEfiKeyFlushState (TerminalDevice
);
1400 UnicodeToEfiKeyFlushState (TerminalDevice
);
1404 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1406 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1408 Key
.ScanCode
= SCAN_NULL
;
1410 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1411 switch (UnicodeChar
) {
1413 Key
.ScanCode
= SCAN_F1
;
1416 Key
.ScanCode
= SCAN_F2
;
1419 Key
.ScanCode
= SCAN_F3
;
1422 Key
.ScanCode
= SCAN_F4
;
1425 Key
.ScanCode
= SCAN_F5
;
1428 Key
.ScanCode
= SCAN_F6
;
1431 Key
.ScanCode
= SCAN_F7
;
1434 Key
.ScanCode
= SCAN_F8
;
1437 Key
.ScanCode
= SCAN_F9
;
1440 Key
.ScanCode
= SCAN_F10
;
1447 if (Key
.ScanCode
!= SCAN_NULL
) {
1448 Key
.UnicodeChar
= 0;
1449 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1450 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1451 UnicodeToEfiKeyFlushState (TerminalDevice
);
1455 UnicodeToEfiKeyFlushState (TerminalDevice
);
1459 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1461 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1463 Key
.ScanCode
= SCAN_NULL
;
1465 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1466 TerminalDevice
->TerminalType
== VT100TYPE
||
1467 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1468 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1469 switch (UnicodeChar
) {
1471 Key
.ScanCode
= SCAN_UP
;
1474 Key
.ScanCode
= SCAN_DOWN
;
1477 Key
.ScanCode
= SCAN_RIGHT
;
1480 Key
.ScanCode
= SCAN_LEFT
;
1483 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1484 TerminalDevice
->TerminalType
== VT100TYPE
) {
1485 Key
.ScanCode
= SCAN_HOME
;
1489 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1490 Key
.ScanCode
= SCAN_END
;
1494 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1495 Key
.ScanCode
= SCAN_END
;
1500 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1501 TerminalDevice
->TerminalType
== VT100TYPE
) {
1502 Key
.ScanCode
= SCAN_INSERT
;
1506 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1507 Key
.ScanCode
= SCAN_DELETE
;
1511 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1512 Key
.ScanCode
= SCAN_DELETE
;
1513 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1514 Key
.ScanCode
= SCAN_F4
;
1518 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1519 Key
.ScanCode
= SCAN_PAGE_UP
;
1523 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1524 Key
.ScanCode
= SCAN_F10
;
1527 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1528 Key
.ScanCode
= SCAN_PAGE_UP
;
1532 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1533 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1537 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1538 Key
.ScanCode
= SCAN_F9
;
1541 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1542 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1546 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1547 Key
.ScanCode
= SCAN_F1
;
1551 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1552 Key
.ScanCode
= SCAN_F2
;
1556 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1557 Key
.ScanCode
= SCAN_F3
;
1561 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1562 Key
.ScanCode
= SCAN_F5
;
1566 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1567 Key
.ScanCode
= SCAN_F6
;
1571 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1572 Key
.ScanCode
= SCAN_F7
;
1576 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1577 Key
.ScanCode
= SCAN_F8
;
1585 if (Key
.ScanCode
!= SCAN_NULL
) {
1586 Key
.UnicodeChar
= 0;
1587 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1588 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1589 UnicodeToEfiKeyFlushState (TerminalDevice
);
1593 UnicodeToEfiKeyFlushState (TerminalDevice
);
1600 // Invalid state. This should never happen.
1604 UnicodeToEfiKeyFlushState (TerminalDevice
);
1609 if (UnicodeChar
== ESC
) {
1610 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1613 if (UnicodeChar
== CSI
) {
1614 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1617 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1618 Status
= gBS
->SetTimer(
1619 TerminalDevice
->TwoSecondTimeOut
,
1623 ASSERT_EFI_ERROR (Status
);
1627 if (SetDefaultResetState
) {
1628 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1631 if (UnicodeChar
== DEL
) {
1632 Key
.ScanCode
= SCAN_DELETE
;
1633 Key
.UnicodeChar
= 0;
1635 Key
.ScanCode
= SCAN_NULL
;
1636 Key
.UnicodeChar
= UnicodeChar
;
1639 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);