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.
20 Reads the next keystroke from the input device. The WaitForKey Event can
21 be used to test for existance of a keystroke via WaitForEvent () call.
23 @param TerminalDevice Terminal driver private structure
24 @param KeyData A pointer to a buffer that is filled in with the
25 keystroke state data for the key that was
28 @retval EFI_SUCCESS The keystroke information was returned.
29 @retval EFI_NOT_READY There was no keystroke data availiable.
30 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
32 @retval EFI_INVALID_PARAMETER KeyData is NULL.
37 IN TERMINAL_DEV
*TerminalDevice
,
38 OUT EFI_KEY_DATA
*KeyData
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 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
73 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
75 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
77 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
78 CurrentNotify
->KeyNotificationFn (KeyData
);
87 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
88 This driver only perform dependent serial device reset regardless of
89 the value of ExtendeVerification
91 @param This Indicates the calling context.
92 @param ExtendedVerification Skip by this driver.
94 @return EFI_SUCCESS The reset operation succeeds.
95 @return EFI_DEVICE_ERROR The dependent serial port reset fails.
101 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
102 IN BOOLEAN ExtendedVerification
106 TERMINAL_DEV
*TerminalDevice
;
108 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
111 // Report progress code here
113 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
115 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
116 TerminalDevice
->DevicePath
119 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
122 // clear all the internal buffer for keys
124 InitializeRawFiFo (TerminalDevice
);
125 InitializeUnicodeFiFo (TerminalDevice
);
126 InitializeEfiKeyFiFo (TerminalDevice
);
128 if (EFI_ERROR (Status
)) {
129 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
130 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
131 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
132 TerminalDevice
->DevicePath
140 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
142 @param This Indicates the calling context.
143 @param Key A pointer to a buffer that is filled in with the
144 keystroke information for the key that was sent
147 @return EFI_SUCCESS The keystroke information is returned successfully.
148 @return EFI_NOT_READY There is no keystroke data available.
149 @return EFI_DEVICE_ERROR The dependent serial device encounters error.
154 TerminalConInReadKeyStroke (
155 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
156 OUT EFI_INPUT_KEY
*Key
159 TERMINAL_DEV
*TerminalDevice
;
161 EFI_KEY_DATA KeyData
;
164 // get TERMINAL_DEV from "This" parameter.
166 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
168 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
169 if (EFI_ERROR (Status
)) {
173 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
180 Check if the key already has been registered.
182 @param RegsiteredData A pointer to a buffer that is filled in with the
183 keystroke state data for the key that was
185 @param InputData A pointer to a buffer that is filled in with the
186 keystroke state data for the key that was
189 @retval TRUE Key be pressed matches a registered key.
190 @retval FLASE Match failed.
195 IN EFI_KEY_DATA
*RegsiteredData
,
196 IN EFI_KEY_DATA
*InputData
199 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
201 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
202 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
212 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
213 Signal the event if there is key available
215 @param Event Indicates the event that invoke this function.
216 @param Context Indicates the calling context.
223 TerminalConInWaitForKeyEx (
228 TERMINAL_DEV
*TerminalDevice
;
230 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context
);
232 TerminalConInWaitForKey (Event
, &TerminalDevice
->SimpleInput
);
237 // Simple Text Input Ex protocol functions
241 Reset the input device and optionaly run diagnostics
243 @param This Protocol instance pointer.
244 @param ExtendedVerification Driver may perform diagnostics on reset.
246 @retval EFI_SUCCESS The device was reset.
247 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
253 TerminalConInResetEx (
254 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
255 IN BOOLEAN ExtendedVerification
259 TERMINAL_DEV
*TerminalDevice
;
261 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
263 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
264 if (EFI_ERROR (Status
)) {
265 return EFI_DEVICE_ERROR
;
274 Reads the next keystroke from the input device. The WaitForKey Event can
275 be used to test for existance of a keystroke via WaitForEvent () call.
277 @param This Protocol instance pointer.
278 @param KeyData A pointer to a buffer that is filled in with the
279 keystroke state data for the key that was
282 @retval EFI_SUCCESS The keystroke information was returned.
283 @retval EFI_NOT_READY There was no keystroke data availiable.
284 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
286 @retval EFI_INVALID_PARAMETER KeyData is NULL.
291 TerminalConInReadKeyStrokeEx (
292 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
293 OUT EFI_KEY_DATA
*KeyData
296 TERMINAL_DEV
*TerminalDevice
;
298 if (KeyData
== NULL
) {
299 return EFI_INVALID_PARAMETER
;
302 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
304 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
310 Set certain state for the input device.
312 @param This Protocol instance pointer.
313 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
314 state for the input device.
316 @retval EFI_SUCCESS The device state was set successfully.
317 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
318 could not have the setting adjusted.
319 @retval EFI_UNSUPPORTED The device does not have the ability to set its
321 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
326 TerminalConInSetState (
327 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
328 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
331 if (KeyToggleState
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
340 Register a notification function for a particular keystroke for the input device.
342 @param This Protocol instance pointer.
343 @param KeyData A pointer to a buffer that is filled in with the
344 keystroke information data for the key that was
346 @param KeyNotificationFunction Points to the function to be called when the key
347 sequence is typed specified by KeyData.
348 @param NotifyHandle Points to the unique handle assigned to the
349 registered notification.
351 @retval EFI_SUCCESS The notification function was registered
353 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
355 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
360 TerminalConInRegisterKeyNotify (
361 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
362 IN EFI_KEY_DATA
*KeyData
,
363 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
364 OUT EFI_HANDLE
*NotifyHandle
368 TERMINAL_DEV
*TerminalDevice
;
369 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
371 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
373 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
374 return EFI_INVALID_PARAMETER
;
377 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
380 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
382 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
385 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
387 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
389 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
390 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
391 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
398 // Allocate resource to save the notification function
400 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
401 if (NewNotify
== NULL
) {
402 return EFI_OUT_OF_RESOURCES
;
405 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
406 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
407 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
408 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
410 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
412 Status
= gBS
->InstallMultipleProtocolInterfaces (
413 &NewNotify
->NotifyHandle
,
414 &gSimpleTextInExNotifyGuid
,
418 ASSERT_EFI_ERROR (Status
);
419 *NotifyHandle
= NewNotify
->NotifyHandle
;
426 Remove a registered notification function from a particular keystroke.
428 @param This Protocol instance pointer.
429 @param NotificationHandle The handle of the notification function being
432 @retval EFI_SUCCESS The notification function was unregistered
434 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
435 @retval EFI_NOT_FOUND Can not find the matching entry in database.
440 TerminalConInUnregisterKeyNotify (
441 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
442 IN EFI_HANDLE NotificationHandle
446 TERMINAL_DEV
*TerminalDevice
;
448 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
450 if (NotificationHandle
== NULL
) {
451 return EFI_INVALID_PARAMETER
;
454 Status
= gBS
->OpenProtocol (
456 &gSimpleTextInExNotifyGuid
,
460 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
462 if (EFI_ERROR (Status
)) {
463 return EFI_INVALID_PARAMETER
;
466 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
468 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
471 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
473 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
475 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
477 // Remove the notification function from NotifyList and free resources
479 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
480 Status
= gBS
->UninstallMultipleProtocolInterfaces (
481 CurrentNotify
->NotifyHandle
,
482 &gSimpleTextInExNotifyGuid
,
486 ASSERT_EFI_ERROR (Status
);
487 gBS
->FreePool (CurrentNotify
);
492 return EFI_NOT_FOUND
;
496 Translate raw data into Unicode (according to different encode), and
497 translate Unicode into key information. (according to different standard).
499 @param TerminalDevice Terminal driver private structure.
505 TranslateRawDataToEfiKey (
506 IN TERMINAL_DEV
*TerminalDevice
509 switch (TerminalDevice
->TerminalType
) {
514 AnsiRawDataToUnicode (TerminalDevice
);
515 UnicodeToEfiKey (TerminalDevice
);
520 // Process all the raw data in the RawFIFO,
521 // put the processed key into UnicodeFIFO.
523 VTUTF8RawDataToUnicode (TerminalDevice
);
526 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
527 // then put into EfiKeyFIFO.
529 UnicodeToEfiKey (TerminalDevice
);
536 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
537 Signal the event if there is key available
539 @param Event Indicates the event that invoke this function.
540 @param Context Indicates the calling context.
547 TerminalConInWaitForKey (
553 // Someone is waiting on the keystroke event, if there's
554 // a key pending, signal the event
556 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
558 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
560 gBS
->SignalEvent (Event
);
566 Check for a pending key in the Efi Key FIFO or Serial device buffer.
568 @param This Indicates the calling context.
570 @retval EFI_SUCCESS There is key pending.
571 @retval EFI_NOT_READY There is no key pending.
572 @retval EFI_DEVICE_ERROR If Serial IO is not attched to serial device.
576 TerminalConInCheckForKey (
577 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
581 TERMINAL_DEV
*TerminalDevice
;
584 EFI_SERIAL_IO_MODE
*Mode
;
585 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
586 UINTN SerialInTimeOut
;
588 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
590 SerialIo
= TerminalDevice
->SerialIo
;
591 if (SerialIo
== NULL
) {
592 return EFI_DEVICE_ERROR
;
595 // if current timeout value for serial device is not identical with
596 // the value saved in TERMINAL_DEV structure, then recalculate the
597 // timeout value again and set serial attribute according to this value.
599 Mode
= SerialIo
->Mode
;
600 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
603 if (Mode
->BaudRate
!= 0) {
604 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
607 Status
= SerialIo
->SetAttributes (
610 Mode
->ReceiveFifoDepth
,
611 (UINT32
) SerialInTimeOut
,
612 (EFI_PARITY_TYPE
) (Mode
->Parity
),
613 (UINT8
) Mode
->DataBits
,
614 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
617 if (EFI_ERROR (Status
)) {
618 TerminalDevice
->SerialInTimeOut
= 0;
620 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
624 // check whether serial buffer is empty
626 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
628 if (0 != (Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
)) {
630 // Translate all the raw data in RawFIFO into EFI Key,
631 // according to different terminal type supported.
633 TranslateRawDataToEfiKey (TerminalDevice
);
636 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
639 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
642 return EFI_NOT_READY
;
646 // Fetch all the keys in the serial buffer,
647 // and insert the byte stream into RawFIFO.
651 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
653 if (EFI_ERROR (Status
)) {
654 if (Status
== EFI_DEVICE_ERROR
) {
655 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
656 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
657 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
658 TerminalDevice
->DevicePath
664 RawFiFoInsertOneKey (TerminalDevice
, Input
);
668 // Translate all the raw data in RawFIFO into EFI Key,
669 // according to different terminal type supported.
671 TranslateRawDataToEfiKey (TerminalDevice
);
673 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
674 return EFI_NOT_READY
;
681 Get one key out of serial buffer.
683 @param SerialIo Serial I/O protocl attached to the serial device.
684 @param Output The fetched key.
686 @return EFI_NOT_READY If serial buffer is empty.
687 @return EFI_DEVICE_ERROR If reading serial buffer encounter error.
688 @return EFI_SUCCESS If reading serial buffer successfully, put
689 the fetched key to the parameter output.
693 GetOneKeyFromSerial (
694 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
704 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
706 if (EFI_ERROR (Status
)) {
708 if (Status
== EFI_TIMEOUT
) {
709 return EFI_NOT_READY
;
712 return EFI_DEVICE_ERROR
;
717 return EFI_NOT_READY
;
724 Insert one byte raw data into the Raw Data FIFO.
726 @param TerminalDevice Terminal driver private structure.
727 @param Input The key will be input.
729 @return TRUE If insert successfully.
730 @return FLASE If Raw Data buffer is full before key insertion,
735 RawFiFoInsertOneKey (
736 TERMINAL_DEV
*TerminalDevice
,
742 Tail
= TerminalDevice
->RawFiFo
.Tail
;
744 if (IsRawFiFoFull (TerminalDevice
)) {
751 TerminalDevice
->RawFiFo
.Data
[Tail
] = Input
;
753 TerminalDevice
->RawFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
759 Remove one pre-fetched key out of the Raw Data FIFO.
761 @param TerminalDevice Terminal driver private structure.
762 @param Output The key will be removed.
764 @return TRUE If insert successfully.
765 @return FLASE If Raw Data FIFO buffer is empty before remove operation.
769 RawFiFoRemoveOneKey (
770 TERMINAL_DEV
*TerminalDevice
,
776 Head
= TerminalDevice
->RawFiFo
.Head
;
778 if (IsRawFiFoEmpty (TerminalDevice
)) {
786 *Output
= TerminalDevice
->RawFiFo
.Data
[Head
];
788 TerminalDevice
->RawFiFo
.Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
794 Clarify whether Raw Data FIFO buffer is empty.
796 @param TerminalDevice Terminal driver private structure
798 @return TRUE If Raw Data FIFO buffer is empty.
799 @return FLASE If Raw Data FIFO buffer is not empty.
804 TERMINAL_DEV
*TerminalDevice
807 if (TerminalDevice
->RawFiFo
.Head
== TerminalDevice
->RawFiFo
.Tail
) {
815 Clarify whether Raw Data FIFO buffer is full.
817 @param TerminalDevice Terminal driver private structure
819 @return TRUE If Raw Data FIFO buffer is full.
820 @return FLASE If Raw Data FIFO buffer is not full.
825 TERMINAL_DEV
*TerminalDevice
831 Tail
= TerminalDevice
->RawFiFo
.Tail
;
832 Head
= TerminalDevice
->RawFiFo
.Head
;
834 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
843 Insert one pre-fetched key into the FIFO buffer.
845 @param TerminalDevice Terminal driver private structure.
846 @param Key The key will be input.
848 @return TRUE If insert successfully.
849 @return FLASE If FIFO buffer is full before key insertion,
854 EfiKeyFiFoInsertOneKey (
855 TERMINAL_DEV
*TerminalDevice
,
861 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
863 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
865 // Efi Key FIFO is full
870 TerminalDevice
->EfiKeyFiFo
.Data
[Tail
] = Key
;
872 TerminalDevice
->EfiKeyFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
878 Remove one pre-fetched key out of the FIFO buffer.
880 @param TerminalDevice Terminal driver private structure.
881 @param Output The key will be removed.
883 @return TRUE If insert successfully.
884 @return FLASE If FIFO buffer is empty before remove operation.
888 EfiKeyFiFoRemoveOneKey (
889 TERMINAL_DEV
*TerminalDevice
,
890 EFI_INPUT_KEY
*Output
895 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
897 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
901 Output
->ScanCode
= SCAN_NULL
;
902 Output
->UnicodeChar
= 0;
906 *Output
= TerminalDevice
->EfiKeyFiFo
.Data
[Head
];
908 TerminalDevice
->EfiKeyFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
914 Clarify whether FIFO buffer is empty.
916 @param TerminalDevice Terminal driver private structure
918 @return TRUE If FIFO buffer is empty.
919 @return FLASE If FIFO buffer is not empty.
924 TERMINAL_DEV
*TerminalDevice
927 if (TerminalDevice
->EfiKeyFiFo
.Head
== TerminalDevice
->EfiKeyFiFo
.Tail
) {
935 Clarify whether FIFO buffer is full.
937 @param TerminalDevice Terminal driver private structure
939 @return TRUE If FIFO buffer is full.
940 @return FLASE If FIFO buffer is not full.
945 TERMINAL_DEV
*TerminalDevice
951 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
952 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
954 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
963 Insert one pre-fetched key into the Unicode FIFO buffer.
965 @param TerminalDevice Terminal driver private structure.
966 @param Input The key will be input.
968 @return TRUE If insert successfully.
969 @return FLASE If Unicode FIFO buffer is full before key insertion,
974 UnicodeFiFoInsertOneKey (
975 TERMINAL_DEV
*TerminalDevice
,
981 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
983 if (IsUnicodeFiFoFull (TerminalDevice
)) {
985 // Unicode FIFO is full
990 TerminalDevice
->UnicodeFiFo
.Data
[Tail
] = Input
;
992 TerminalDevice
->UnicodeFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
998 Remove one pre-fetched key out of the Unicode FIFO buffer.
1000 @param TerminalDevice Terminal driver private structure.
1001 @param Output The key will be removed.
1003 @return TRUE If insert successfully.
1004 @return FLASE If Unicode FIFO buffer is empty before remove operation.
1008 UnicodeFiFoRemoveOneKey (
1009 TERMINAL_DEV
*TerminalDevice
,
1015 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1017 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1025 *Output
= TerminalDevice
->UnicodeFiFo
.Data
[Head
];
1027 TerminalDevice
->UnicodeFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1033 Clarify whether Unicode FIFO buffer is empty.
1035 @param TerminalDevice Terminal driver private structure
1037 @return TRUE If Unicode FIFO buffer is empty.
1038 @return FLASE If Unicode FIFO buffer is not empty.
1042 IsUnicodeFiFoEmpty (
1043 TERMINAL_DEV
*TerminalDevice
1046 if (TerminalDevice
->UnicodeFiFo
.Head
== TerminalDevice
->UnicodeFiFo
.Tail
) {
1054 Clarify whether Unicode FIFO buffer is full.
1056 @param TerminalDevice Terminal driver private structure
1058 @return TRUE If Unicode FIFO buffer is full.
1059 @return FLASE If Unicode FIFO buffer is not full.
1064 TERMINAL_DEV
*TerminalDevice
1070 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1071 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1073 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1082 Count Unicode FIFO buffer.
1084 @param TerminalDevice Terminal driver private structure
1086 @return The count in bytes of Unicode FIFO.
1090 UnicodeFiFoGetKeyCount (
1091 TERMINAL_DEV
*TerminalDevice
1097 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1098 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1101 return (UINT8
) (Tail
- Head
);
1103 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1108 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1110 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1116 UnicodeToEfiKeyFlushState (
1117 IN TERMINAL_DEV
*TerminalDevice
1122 if (0 != (TerminalDevice
->InputState
& INPUT_STATE_ESC
)) {
1123 Key
.ScanCode
= SCAN_ESC
;
1124 Key
.UnicodeChar
= 0;
1125 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1128 if (0 != (TerminalDevice
->InputState
& INPUT_STATE_CSI
)) {
1129 Key
.ScanCode
= SCAN_NULL
;
1130 Key
.UnicodeChar
= CSI
;
1131 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1134 if (0 != (TerminalDevice
->InputState
& INPUT_STATE_LEFTOPENBRACKET
)) {
1135 Key
.ScanCode
= SCAN_NULL
;
1136 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1137 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1140 if (0 != (TerminalDevice
->InputState
& INPUT_STATE_O
)) {
1141 Key
.ScanCode
= SCAN_NULL
;
1142 Key
.UnicodeChar
= 'O';
1143 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1146 if (0 != (TerminalDevice
->InputState
& INPUT_STATE_2
)) {
1147 Key
.ScanCode
= SCAN_NULL
;
1148 Key
.UnicodeChar
= '2';
1149 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1153 TerminalDevice
->TwoSecondTimeOut
,
1158 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1163 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1164 can be read through the Simple Input Protocol.
1166 The table below shows the keyboard input mappings that this function supports.
1167 If the ESC sequence listed in one of the columns is presented, then it is translated
1168 into the coorespoding EFI Scan Code. If a matching sequence is not found, then the raw
1169 key strokes are converted into EFI Keys.
1171 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1172 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1173 converted into EFI Keys.
1174 There is one special input sequence that will force the system to reset.
1175 This is ESC R ESC r ESC R.
1177 Symbols used in table below
1178 ===========================
1184 +=========+======+===========+==========+==========+
1185 | | EFI | UEFI 2.0 | | |
1186 | | Scan | | VT100+ | |
1187 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1188 +=========+======+===========+==========+==========+
1189 | NULL | 0x00 | | | |
1190 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1191 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1192 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1193 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1194 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1195 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1196 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1197 | | | ESC [ L | | ESC [ L |
1198 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1199 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1201 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1203 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1204 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1205 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1206 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1207 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1208 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1209 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1210 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1211 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1212 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1213 | Escape | 0x17 | ESC | ESC | ESC |
1214 | F11 | 0x15 | | ESC ! | |
1215 | F12 | 0x16 | | ESC @ | |
1216 +=========+======+===========+==========+==========+
1220 ESC R ESC r ESC R = Reset System
1222 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1229 IN TERMINAL_DEV
*TerminalDevice
1233 EFI_STATUS TimerStatus
;
1236 BOOLEAN SetDefaultResetState
;
1238 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1240 if (!EFI_ERROR (TimerStatus
)) {
1241 UnicodeToEfiKeyFlushState (TerminalDevice
);
1242 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1245 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1247 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1249 // Check to see if the 2 second timer has expired
1251 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1252 if (!EFI_ERROR (TimerStatus
)) {
1253 UnicodeToEfiKeyFlushState (TerminalDevice
);
1254 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1259 // Fetch one Unicode character from the Unicode FIFO
1261 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1263 SetDefaultResetState
= TRUE
;
1265 switch (TerminalDevice
->InputState
) {
1266 case INPUT_STATE_DEFAULT
:
1270 case INPUT_STATE_ESC
:
1272 if (UnicodeChar
== LEFTOPENBRACKET
) {
1273 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1274 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1278 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1279 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1280 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1284 Key
.ScanCode
= SCAN_NULL
;
1286 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1287 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1288 switch (UnicodeChar
) {
1290 Key
.ScanCode
= SCAN_F1
;
1293 Key
.ScanCode
= SCAN_F2
;
1296 Key
.ScanCode
= SCAN_F3
;
1299 Key
.ScanCode
= SCAN_F4
;
1302 Key
.ScanCode
= SCAN_F5
;
1305 Key
.ScanCode
= SCAN_F6
;
1308 Key
.ScanCode
= SCAN_F7
;
1311 Key
.ScanCode
= SCAN_F8
;
1314 Key
.ScanCode
= SCAN_F9
;
1317 Key
.ScanCode
= SCAN_F10
;
1320 Key
.ScanCode
= SCAN_F11
;
1323 Key
.ScanCode
= SCAN_F12
;
1326 Key
.ScanCode
= SCAN_HOME
;
1329 Key
.ScanCode
= SCAN_END
;
1332 Key
.ScanCode
= SCAN_INSERT
;
1335 Key
.ScanCode
= SCAN_DELETE
;
1338 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1341 Key
.ScanCode
= SCAN_PAGE_UP
;
1348 switch (UnicodeChar
) {
1350 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1351 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1352 SetDefaultResetState
= FALSE
;
1353 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1354 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1356 Key
.ScanCode
= SCAN_NULL
;
1359 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1360 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1361 SetDefaultResetState
= FALSE
;
1363 Key
.ScanCode
= SCAN_NULL
;
1369 if (SetDefaultResetState
) {
1370 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1373 if (Key
.ScanCode
!= SCAN_NULL
) {
1374 Key
.UnicodeChar
= 0;
1375 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1376 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1377 UnicodeToEfiKeyFlushState (TerminalDevice
);
1381 UnicodeToEfiKeyFlushState (TerminalDevice
);
1385 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1387 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1389 Key
.ScanCode
= SCAN_NULL
;
1391 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1392 switch (UnicodeChar
) {
1394 Key
.ScanCode
= SCAN_F1
;
1397 Key
.ScanCode
= SCAN_F2
;
1400 Key
.ScanCode
= SCAN_F3
;
1403 Key
.ScanCode
= SCAN_F4
;
1406 Key
.ScanCode
= SCAN_F5
;
1409 Key
.ScanCode
= SCAN_F6
;
1412 Key
.ScanCode
= SCAN_F7
;
1415 Key
.ScanCode
= SCAN_F8
;
1418 Key
.ScanCode
= SCAN_F9
;
1421 Key
.ScanCode
= SCAN_F10
;
1428 if (Key
.ScanCode
!= SCAN_NULL
) {
1429 Key
.UnicodeChar
= 0;
1430 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1431 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1432 UnicodeToEfiKeyFlushState (TerminalDevice
);
1436 UnicodeToEfiKeyFlushState (TerminalDevice
);
1440 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1442 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1444 Key
.ScanCode
= SCAN_NULL
;
1446 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1447 TerminalDevice
->TerminalType
== VT100TYPE
||
1448 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1449 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1450 switch (UnicodeChar
) {
1452 Key
.ScanCode
= SCAN_UP
;
1455 Key
.ScanCode
= SCAN_DOWN
;
1458 Key
.ScanCode
= SCAN_RIGHT
;
1461 Key
.ScanCode
= SCAN_LEFT
;
1464 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1465 TerminalDevice
->TerminalType
== VT100TYPE
) {
1466 Key
.ScanCode
= SCAN_HOME
;
1470 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1471 Key
.ScanCode
= SCAN_END
;
1475 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1476 Key
.ScanCode
= SCAN_END
;
1481 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1482 TerminalDevice
->TerminalType
== VT100TYPE
) {
1483 Key
.ScanCode
= SCAN_INSERT
;
1487 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1488 Key
.ScanCode
= SCAN_DELETE
;
1492 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1493 Key
.ScanCode
= SCAN_DELETE
;
1494 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1495 Key
.ScanCode
= SCAN_F4
;
1499 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1500 Key
.ScanCode
= SCAN_PAGE_UP
;
1504 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1505 Key
.ScanCode
= SCAN_F10
;
1508 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1509 Key
.ScanCode
= SCAN_PAGE_UP
;
1513 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1514 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1518 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1519 Key
.ScanCode
= SCAN_F9
;
1522 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1523 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1527 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1528 Key
.ScanCode
= SCAN_F1
;
1532 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1533 Key
.ScanCode
= SCAN_F2
;
1537 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1538 Key
.ScanCode
= SCAN_F3
;
1542 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1543 Key
.ScanCode
= SCAN_F5
;
1547 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1548 Key
.ScanCode
= SCAN_F6
;
1552 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1553 Key
.ScanCode
= SCAN_F7
;
1557 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1558 Key
.ScanCode
= SCAN_F8
;
1566 if (Key
.ScanCode
!= SCAN_NULL
) {
1567 Key
.UnicodeChar
= 0;
1568 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1569 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1570 UnicodeToEfiKeyFlushState (TerminalDevice
);
1574 UnicodeToEfiKeyFlushState (TerminalDevice
);
1581 // Invalid state. This should never happen.
1585 UnicodeToEfiKeyFlushState (TerminalDevice
);
1590 if (UnicodeChar
== ESC
) {
1591 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1594 if (UnicodeChar
== CSI
) {
1595 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1598 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1599 Status
= gBS
->SetTimer(
1600 TerminalDevice
->TwoSecondTimeOut
,
1604 ASSERT_EFI_ERROR (Status
);
1608 if (SetDefaultResetState
) {
1609 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1612 if (UnicodeChar
== DEL
) {
1613 Key
.ScanCode
= SCAN_DELETE
;
1614 Key
.UnicodeChar
= 0;
1616 Key
.ScanCode
= SCAN_NULL
;
1617 Key
.UnicodeChar
= UnicodeChar
;
1620 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);