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 existance 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 availiable.
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 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
44 if (KeyData
== NULL
) {
45 return EFI_INVALID_PARAMETER
;
49 // Initialize *Key to nonsense value.
51 KeyData
->Key
.ScanCode
= SCAN_NULL
;
52 KeyData
->Key
.UnicodeChar
= 0;
54 Status
= TerminalConInCheckForKey (&TerminalDevice
->SimpleInput
);
55 if (EFI_ERROR (Status
)) {
59 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
63 KeyData
->KeyState
.KeyShiftState
= 0;
64 KeyData
->KeyState
.KeyToggleState
= 0;
67 // Invoke notification functions if exist
69 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
72 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
74 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
76 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
77 CurrentNotify
->KeyNotificationFn (KeyData
);
86 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
87 This driver only perform dependent serial device reset regardless of
88 the value of ExtendeVerification
90 @param This Indicates the calling context.
91 @param ExtendedVerification Skip by this driver.
93 @return EFI_SUCCESS The reset operation succeeds.
94 @return EFI_DEVICE_ERROR The dependent serial port reset fails.
100 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
101 IN BOOLEAN ExtendedVerification
105 TERMINAL_DEV
*TerminalDevice
;
107 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
110 // Report progress code here
112 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
114 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
115 TerminalDevice
->DevicePath
118 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
121 // clear all the internal buffer for keys
123 InitializeRawFiFo (TerminalDevice
);
124 InitializeUnicodeFiFo (TerminalDevice
);
125 InitializeEfiKeyFiFo (TerminalDevice
);
127 if (EFI_ERROR (Status
)) {
128 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
129 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
130 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
131 TerminalDevice
->DevicePath
139 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
141 @param This Indicates the calling context.
142 @param Key A pointer to a buffer that is filled in with the
143 keystroke information for the key that was sent
146 @return EFI_SUCCESS The keystroke information is returned successfully.
147 @return EFI_NOT_READY There is no keystroke data available.
148 @return EFI_DEVICE_ERROR The dependent serial device encounters error.
153 TerminalConInReadKeyStroke (
154 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
155 OUT EFI_INPUT_KEY
*Key
158 TERMINAL_DEV
*TerminalDevice
;
160 EFI_KEY_DATA KeyData
;
163 // get TERMINAL_DEV from "This" parameter.
165 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
167 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
168 if (EFI_ERROR (Status
)) {
172 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
179 Check if the key already has been registered.
181 @param RegsiteredData A pointer to a buffer that is filled in with the
182 keystroke state data for the key that was
184 @param InputData A pointer to a buffer that is filled in with the
185 keystroke state data for the key that was
188 @retval TRUE Key be pressed matches a registered key.
189 @retval FLASE Match failed.
194 IN EFI_KEY_DATA
*RegsiteredData
,
195 IN EFI_KEY_DATA
*InputData
198 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
200 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
201 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
211 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
212 Signal the event if there is key available
214 @param Event Indicates the event that invoke this function.
215 @param Context Indicates the calling context.
222 TerminalConInWaitForKeyEx (
227 TERMINAL_DEV
*TerminalDevice
;
229 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context
);
231 TerminalConInWaitForKey (Event
, &TerminalDevice
->SimpleInput
);
236 // Simple Text Input Ex protocol functions
240 Reset the input device and optionaly run diagnostics
242 @param This Protocol instance pointer.
243 @param ExtendedVerification Driver may perform diagnostics on reset.
245 @retval EFI_SUCCESS The device was reset.
246 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
252 TerminalConInResetEx (
253 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
254 IN BOOLEAN ExtendedVerification
258 TERMINAL_DEV
*TerminalDevice
;
260 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
262 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
263 if (EFI_ERROR (Status
)) {
264 return EFI_DEVICE_ERROR
;
273 Reads the next keystroke from the input device. The WaitForKey Event can
274 be used to test for existance of a keystroke via WaitForEvent () call.
276 @param This Protocol instance pointer.
277 @param KeyData A pointer to a buffer that is filled in with the
278 keystroke state data for the key that was
281 @retval EFI_SUCCESS The keystroke information was returned.
282 @retval EFI_NOT_READY There was no keystroke data availiable.
283 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
285 @retval EFI_INVALID_PARAMETER KeyData is NULL.
290 TerminalConInReadKeyStrokeEx (
291 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
292 OUT EFI_KEY_DATA
*KeyData
295 TERMINAL_DEV
*TerminalDevice
;
297 if (KeyData
== NULL
) {
298 return EFI_INVALID_PARAMETER
;
301 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
303 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
309 Set certain state for the input device.
311 @param This Protocol instance pointer.
312 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
313 state for the input device.
315 @retval EFI_SUCCESS The device state was set successfully.
316 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
317 could not have the setting adjusted.
318 @retval EFI_UNSUPPORTED The device does not have the ability to set its
320 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
325 TerminalConInSetState (
326 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
327 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
330 if (KeyToggleState
== NULL
) {
331 return EFI_INVALID_PARAMETER
;
339 Register a notification function for a particular keystroke for the input device.
341 @param This Protocol instance pointer.
342 @param KeyData A pointer to a buffer that is filled in with the
343 keystroke information data for the key that was
345 @param KeyNotificationFunction Points to the function to be called when the key
346 sequence is typed specified by KeyData.
347 @param NotifyHandle Points to the unique handle assigned to the
348 registered notification.
350 @retval EFI_SUCCESS The notification function was registered
352 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
354 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
359 TerminalConInRegisterKeyNotify (
360 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
361 IN EFI_KEY_DATA
*KeyData
,
362 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
363 OUT EFI_HANDLE
*NotifyHandle
367 TERMINAL_DEV
*TerminalDevice
;
368 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
370 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
372 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
373 return EFI_INVALID_PARAMETER
;
376 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
379 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
381 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
384 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
386 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
388 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
389 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
390 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
397 // Allocate resource to save the notification function
399 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
400 if (NewNotify
== NULL
) {
401 return EFI_OUT_OF_RESOURCES
;
404 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
405 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
406 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
407 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
409 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
411 Status
= gBS
->InstallMultipleProtocolInterfaces (
412 &NewNotify
->NotifyHandle
,
413 &gSimpleTextInExNotifyGuid
,
417 ASSERT_EFI_ERROR (Status
);
418 *NotifyHandle
= NewNotify
->NotifyHandle
;
425 Remove a registered notification function from a particular keystroke.
427 @param This Protocol instance pointer.
428 @param NotificationHandle The handle of the notification function being
431 @retval EFI_SUCCESS The notification function was unregistered
433 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
434 @retval EFI_NOT_FOUND Can not find the matching entry in database.
439 TerminalConInUnregisterKeyNotify (
440 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
441 IN EFI_HANDLE NotificationHandle
445 TERMINAL_DEV
*TerminalDevice
;
447 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
449 if (NotificationHandle
== NULL
) {
450 return EFI_INVALID_PARAMETER
;
453 Status
= gBS
->OpenProtocol (
455 &gSimpleTextInExNotifyGuid
,
459 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
461 if (EFI_ERROR (Status
)) {
462 return EFI_INVALID_PARAMETER
;
465 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
467 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
470 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
472 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
474 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
476 // Remove the notification function from NotifyList and free resources
478 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
479 Status
= gBS
->UninstallMultipleProtocolInterfaces (
480 CurrentNotify
->NotifyHandle
,
481 &gSimpleTextInExNotifyGuid
,
485 ASSERT_EFI_ERROR (Status
);
486 gBS
->FreePool (CurrentNotify
);
491 return EFI_NOT_FOUND
;
495 Translate raw data into Unicode (according to different encode), and
496 translate Unicode into key information. (according to different standard).
498 @param TerminalDevice Terminal driver private structure.
504 TranslateRawDataToEfiKey (
505 IN TERMINAL_DEV
*TerminalDevice
508 switch (TerminalDevice
->TerminalType
) {
513 AnsiRawDataToUnicode (TerminalDevice
);
514 UnicodeToEfiKey (TerminalDevice
);
519 // Process all the raw data in the RawFIFO,
520 // put the processed key into UnicodeFIFO.
522 VTUTF8RawDataToUnicode (TerminalDevice
);
525 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
526 // then put into EfiKeyFIFO.
528 UnicodeToEfiKey (TerminalDevice
);
535 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
536 Signal the event if there is key available
538 @param Event Indicates the event that invoke this function.
539 @param Context Indicates the calling context.
546 TerminalConInWaitForKey (
552 // Someone is waiting on the keystroke event, if there's
553 // a key pending, signal the event
555 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
557 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
559 gBS
->SignalEvent (Event
);
565 Check for a pending key in the Efi Key FIFO or Serial device buffer.
567 @param This Indicates the calling context.
569 @retval EFI_SUCCESS There is key pending.
570 @retval EFI_NOT_READY There is no key pending.
571 @retval EFI_DEVICE_ERROR If Serial IO is not attched to serial device.
575 TerminalConInCheckForKey (
576 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
580 TERMINAL_DEV
*TerminalDevice
;
583 EFI_SERIAL_IO_MODE
*Mode
;
584 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
585 UINTN SerialInTimeOut
;
587 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
589 SerialIo
= TerminalDevice
->SerialIo
;
590 if (SerialIo
== NULL
) {
591 return EFI_DEVICE_ERROR
;
594 // if current timeout value for serial device is not identical with
595 // the value saved in TERMINAL_DEV structure, then recalculate the
596 // timeout value again and set serial attribute according to this value.
598 Mode
= SerialIo
->Mode
;
599 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
602 if (Mode
->BaudRate
!= 0) {
604 // According to BAUD rate to calculate the timeout value.
606 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
609 Status
= SerialIo
->SetAttributes (
612 Mode
->ReceiveFifoDepth
,
613 (UINT32
) SerialInTimeOut
,
614 (EFI_PARITY_TYPE
) (Mode
->Parity
),
615 (UINT8
) Mode
->DataBits
,
616 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
619 if (EFI_ERROR (Status
)) {
620 TerminalDevice
->SerialInTimeOut
= 0;
622 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
626 // Check whether serial buffer is empty.
628 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
630 if ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
632 // Translate all the raw data in RawFIFO into EFI Key,
633 // according to different terminal type supported.
635 TranslateRawDataToEfiKey (TerminalDevice
);
638 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
641 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
644 return EFI_NOT_READY
;
648 // Fetch all the keys in the serial buffer,
649 // and insert the byte stream into RawFIFO.
653 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
655 if (EFI_ERROR (Status
)) {
656 if (Status
== EFI_DEVICE_ERROR
) {
657 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
658 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
659 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
660 TerminalDevice
->DevicePath
666 RawFiFoInsertOneKey (TerminalDevice
, Input
);
670 // Translate all the raw data in RawFIFO into EFI Key,
671 // according to different terminal type supported.
673 TranslateRawDataToEfiKey (TerminalDevice
);
675 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
676 return EFI_NOT_READY
;
683 Get one key out of serial buffer.
685 @param SerialIo Serial I/O protocl attached to the serial device.
686 @param Output The fetched key.
688 @return EFI_NOT_READY If serial buffer is empty.
689 @return EFI_DEVICE_ERROR If reading serial buffer encounter error.
690 @return EFI_SUCCESS If reading serial buffer successfully, put
691 the fetched key to the parameter output.
695 GetOneKeyFromSerial (
696 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
707 // Read one key from serial I/O device.
709 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
711 if (EFI_ERROR (Status
)) {
713 if (Status
== EFI_TIMEOUT
) {
714 return EFI_NOT_READY
;
717 return EFI_DEVICE_ERROR
;
722 return EFI_NOT_READY
;
729 Insert one byte raw data into the Raw Data FIFO.
731 @param TerminalDevice Terminal driver private structure.
732 @param Input The key will be input.
734 @return TRUE If insert successfully.
735 @return FLASE If Raw Data buffer is full before key insertion,
740 RawFiFoInsertOneKey (
741 TERMINAL_DEV
*TerminalDevice
,
747 Tail
= TerminalDevice
->RawFiFo
.Tail
;
749 if (IsRawFiFoFull (TerminalDevice
)) {
756 TerminalDevice
->RawFiFo
.Data
[Tail
] = Input
;
758 TerminalDevice
->RawFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
764 Remove one pre-fetched key out of the Raw Data FIFO.
766 @param TerminalDevice Terminal driver private structure.
767 @param Output The key will be removed.
769 @return TRUE If insert successfully.
770 @return FLASE If Raw Data FIFO buffer is empty before remove operation.
774 RawFiFoRemoveOneKey (
775 TERMINAL_DEV
*TerminalDevice
,
781 Head
= TerminalDevice
->RawFiFo
.Head
;
783 if (IsRawFiFoEmpty (TerminalDevice
)) {
791 *Output
= TerminalDevice
->RawFiFo
.Data
[Head
];
793 TerminalDevice
->RawFiFo
.Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
799 Clarify whether Raw Data FIFO buffer is empty.
801 @param TerminalDevice Terminal driver private structure
803 @return TRUE If Raw Data FIFO buffer is empty.
804 @return FLASE If Raw Data FIFO buffer is not empty.
809 TERMINAL_DEV
*TerminalDevice
812 if (TerminalDevice
->RawFiFo
.Head
== TerminalDevice
->RawFiFo
.Tail
) {
820 Clarify whether Raw Data FIFO buffer is full.
822 @param TerminalDevice Terminal driver private structure
824 @return TRUE If Raw Data FIFO buffer is full.
825 @return FLASE If Raw Data FIFO buffer is not full.
830 TERMINAL_DEV
*TerminalDevice
836 Tail
= TerminalDevice
->RawFiFo
.Tail
;
837 Head
= TerminalDevice
->RawFiFo
.Head
;
839 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
848 Insert one pre-fetched key into the FIFO buffer.
850 @param TerminalDevice Terminal driver private structure.
851 @param Key The key will be input.
853 @return TRUE If insert successfully.
854 @return FLASE If FIFO buffer is full before key insertion,
859 EfiKeyFiFoInsertOneKey (
860 TERMINAL_DEV
*TerminalDevice
,
866 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
868 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
870 // Efi Key FIFO is full
875 TerminalDevice
->EfiKeyFiFo
.Data
[Tail
] = Key
;
877 TerminalDevice
->EfiKeyFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
883 Remove one pre-fetched key out of the FIFO buffer.
885 @param TerminalDevice Terminal driver private structure.
886 @param Output The key will be removed.
888 @return TRUE If insert successfully.
889 @return FLASE If FIFO buffer is empty before remove operation.
893 EfiKeyFiFoRemoveOneKey (
894 TERMINAL_DEV
*TerminalDevice
,
895 EFI_INPUT_KEY
*Output
900 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
902 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
906 Output
->ScanCode
= SCAN_NULL
;
907 Output
->UnicodeChar
= 0;
911 *Output
= TerminalDevice
->EfiKeyFiFo
.Data
[Head
];
913 TerminalDevice
->EfiKeyFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
919 Clarify whether FIFO buffer is empty.
921 @param TerminalDevice Terminal driver private structure
923 @return TRUE If FIFO buffer is empty.
924 @return FLASE If FIFO buffer is not empty.
929 TERMINAL_DEV
*TerminalDevice
932 if (TerminalDevice
->EfiKeyFiFo
.Head
== TerminalDevice
->EfiKeyFiFo
.Tail
) {
940 Clarify whether FIFO buffer is full.
942 @param TerminalDevice Terminal driver private structure
944 @return TRUE If FIFO buffer is full.
945 @return FLASE If FIFO buffer is not full.
950 TERMINAL_DEV
*TerminalDevice
956 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
957 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
959 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
968 Insert one pre-fetched key into the Unicode FIFO buffer.
970 @param TerminalDevice Terminal driver private structure.
971 @param Input The key will be input.
973 @return TRUE If insert successfully.
974 @return FLASE If Unicode FIFO buffer is full before key insertion,
979 UnicodeFiFoInsertOneKey (
980 TERMINAL_DEV
*TerminalDevice
,
986 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
988 if (IsUnicodeFiFoFull (TerminalDevice
)) {
990 // Unicode FIFO is full
995 TerminalDevice
->UnicodeFiFo
.Data
[Tail
] = Input
;
997 TerminalDevice
->UnicodeFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1003 Remove one pre-fetched key out of the Unicode FIFO buffer.
1005 @param TerminalDevice Terminal driver private structure.
1006 @param Output The key will be removed.
1008 @return TRUE If insert successfully.
1009 @return FLASE If Unicode FIFO buffer is empty before remove operation.
1013 UnicodeFiFoRemoveOneKey (
1014 TERMINAL_DEV
*TerminalDevice
,
1020 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1022 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1030 *Output
= TerminalDevice
->UnicodeFiFo
.Data
[Head
];
1032 TerminalDevice
->UnicodeFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1038 Clarify whether Unicode FIFO buffer is empty.
1040 @param TerminalDevice Terminal driver private structure
1042 @return TRUE If Unicode FIFO buffer is empty.
1043 @return FLASE If Unicode FIFO buffer is not empty.
1047 IsUnicodeFiFoEmpty (
1048 TERMINAL_DEV
*TerminalDevice
1051 if (TerminalDevice
->UnicodeFiFo
.Head
== TerminalDevice
->UnicodeFiFo
.Tail
) {
1059 Clarify whether Unicode FIFO buffer is full.
1061 @param TerminalDevice Terminal driver private structure
1063 @return TRUE If Unicode FIFO buffer is full.
1064 @return FLASE If Unicode FIFO buffer is not full.
1069 TERMINAL_DEV
*TerminalDevice
1075 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1076 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1078 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1087 Count Unicode FIFO buffer.
1089 @param TerminalDevice Terminal driver private structure
1091 @return The count in bytes of Unicode FIFO.
1095 UnicodeFiFoGetKeyCount (
1096 TERMINAL_DEV
*TerminalDevice
1102 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1103 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1106 return (UINT8
) (Tail
- Head
);
1108 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1113 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1115 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1121 UnicodeToEfiKeyFlushState (
1122 IN TERMINAL_DEV
*TerminalDevice
1127 if ((TerminalDevice
->InputState
& INPUT_STATE_ESC
) != 0) {
1128 Key
.ScanCode
= SCAN_ESC
;
1129 Key
.UnicodeChar
= 0;
1130 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1133 if ((TerminalDevice
->InputState
& INPUT_STATE_CSI
) != 0) {
1134 Key
.ScanCode
= SCAN_NULL
;
1135 Key
.UnicodeChar
= CSI
;
1136 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1139 if ((TerminalDevice
->InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1140 Key
.ScanCode
= SCAN_NULL
;
1141 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1142 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1145 if ((TerminalDevice
->InputState
& INPUT_STATE_O
) != 0) {
1146 Key
.ScanCode
= SCAN_NULL
;
1147 Key
.UnicodeChar
= 'O';
1148 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1151 if ((TerminalDevice
->InputState
& INPUT_STATE_2
) != 0) {
1152 Key
.ScanCode
= SCAN_NULL
;
1153 Key
.UnicodeChar
= '2';
1154 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1158 // Cancel the timer.
1161 TerminalDevice
->TwoSecondTimeOut
,
1166 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1171 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1172 can be read through the Simple Input Protocol.
1174 The table below shows the keyboard input mappings that this function supports.
1175 If the ESC sequence listed in one of the columns is presented, then it is translated
1176 into the coorespoding EFI Scan Code. If a matching sequence is not found, then the raw
1177 key strokes are converted into EFI Keys.
1179 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1180 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1181 converted into EFI Keys.
1182 There is one special input sequence that will force the system to reset.
1183 This is ESC R ESC r ESC R.
1185 Symbols used in table below
1186 ===========================
1192 +=========+======+===========+==========+==========+
1193 | | EFI | UEFI 2.0 | | |
1194 | | Scan | | VT100+ | |
1195 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1196 +=========+======+===========+==========+==========+
1197 | NULL | 0x00 | | | |
1198 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1199 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1200 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1201 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1202 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1203 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1204 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1205 | | | ESC [ L | | ESC [ L |
1206 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1207 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1209 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1211 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1212 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1213 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1214 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1215 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1216 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1217 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1218 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1219 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1220 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1221 | Escape | 0x17 | ESC | ESC | ESC |
1222 | F11 | 0x15 | | ESC ! | |
1223 | F12 | 0x16 | | ESC @ | |
1224 +=========+======+===========+==========+==========+
1228 ESC R ESC r ESC R = Reset System
1230 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1237 IN TERMINAL_DEV
*TerminalDevice
1241 EFI_STATUS TimerStatus
;
1244 BOOLEAN SetDefaultResetState
;
1246 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1248 if (!EFI_ERROR (TimerStatus
)) {
1249 UnicodeToEfiKeyFlushState (TerminalDevice
);
1250 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1253 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1255 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1257 // Check to see if the 2 second timer has expired
1259 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1260 if (!EFI_ERROR (TimerStatus
)) {
1261 UnicodeToEfiKeyFlushState (TerminalDevice
);
1262 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1267 // Fetch one Unicode character from the Unicode FIFO
1269 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1271 SetDefaultResetState
= TRUE
;
1273 switch (TerminalDevice
->InputState
) {
1274 case INPUT_STATE_DEFAULT
:
1278 case INPUT_STATE_ESC
:
1280 if (UnicodeChar
== LEFTOPENBRACKET
) {
1281 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1282 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1286 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100TYPE
) {
1287 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1288 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1292 Key
.ScanCode
= SCAN_NULL
;
1294 if (TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1295 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1296 switch (UnicodeChar
) {
1298 Key
.ScanCode
= SCAN_F1
;
1301 Key
.ScanCode
= SCAN_F2
;
1304 Key
.ScanCode
= SCAN_F3
;
1307 Key
.ScanCode
= SCAN_F4
;
1310 Key
.ScanCode
= SCAN_F5
;
1313 Key
.ScanCode
= SCAN_F6
;
1316 Key
.ScanCode
= SCAN_F7
;
1319 Key
.ScanCode
= SCAN_F8
;
1322 Key
.ScanCode
= SCAN_F9
;
1325 Key
.ScanCode
= SCAN_F10
;
1328 Key
.ScanCode
= SCAN_F11
;
1331 Key
.ScanCode
= SCAN_F12
;
1334 Key
.ScanCode
= SCAN_HOME
;
1337 Key
.ScanCode
= SCAN_END
;
1340 Key
.ScanCode
= SCAN_INSERT
;
1343 Key
.ScanCode
= SCAN_DELETE
;
1346 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1349 Key
.ScanCode
= SCAN_PAGE_UP
;
1356 switch (UnicodeChar
) {
1358 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1359 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1360 SetDefaultResetState
= FALSE
;
1361 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1362 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1364 Key
.ScanCode
= SCAN_NULL
;
1367 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1368 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1369 SetDefaultResetState
= FALSE
;
1371 Key
.ScanCode
= SCAN_NULL
;
1377 if (SetDefaultResetState
) {
1378 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1381 if (Key
.ScanCode
!= SCAN_NULL
) {
1382 Key
.UnicodeChar
= 0;
1383 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1384 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1385 UnicodeToEfiKeyFlushState (TerminalDevice
);
1389 UnicodeToEfiKeyFlushState (TerminalDevice
);
1393 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1395 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1397 Key
.ScanCode
= SCAN_NULL
;
1399 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1400 switch (UnicodeChar
) {
1402 Key
.ScanCode
= SCAN_F1
;
1405 Key
.ScanCode
= SCAN_F2
;
1408 Key
.ScanCode
= SCAN_F3
;
1411 Key
.ScanCode
= SCAN_F4
;
1414 Key
.ScanCode
= SCAN_F5
;
1417 Key
.ScanCode
= SCAN_F6
;
1420 Key
.ScanCode
= SCAN_F7
;
1423 Key
.ScanCode
= SCAN_F8
;
1426 Key
.ScanCode
= SCAN_F9
;
1429 Key
.ScanCode
= SCAN_F10
;
1436 if (Key
.ScanCode
!= SCAN_NULL
) {
1437 Key
.UnicodeChar
= 0;
1438 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1439 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1440 UnicodeToEfiKeyFlushState (TerminalDevice
);
1444 UnicodeToEfiKeyFlushState (TerminalDevice
);
1448 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1450 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1452 Key
.ScanCode
= SCAN_NULL
;
1454 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1455 TerminalDevice
->TerminalType
== VT100TYPE
||
1456 TerminalDevice
->TerminalType
== VT100PLUSTYPE
||
1457 TerminalDevice
->TerminalType
== VTUTF8TYPE
) {
1458 switch (UnicodeChar
) {
1460 Key
.ScanCode
= SCAN_UP
;
1463 Key
.ScanCode
= SCAN_DOWN
;
1466 Key
.ScanCode
= SCAN_RIGHT
;
1469 Key
.ScanCode
= SCAN_LEFT
;
1472 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1473 TerminalDevice
->TerminalType
== VT100TYPE
) {
1474 Key
.ScanCode
= SCAN_HOME
;
1478 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1479 Key
.ScanCode
= SCAN_END
;
1483 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1484 Key
.ScanCode
= SCAN_END
;
1489 if (TerminalDevice
->TerminalType
== PCANSITYPE
||
1490 TerminalDevice
->TerminalType
== VT100TYPE
) {
1491 Key
.ScanCode
= SCAN_INSERT
;
1495 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1496 Key
.ScanCode
= SCAN_DELETE
;
1500 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1501 Key
.ScanCode
= SCAN_DELETE
;
1502 } else if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1503 Key
.ScanCode
= SCAN_F4
;
1507 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1508 Key
.ScanCode
= SCAN_PAGE_UP
;
1512 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1513 Key
.ScanCode
= SCAN_F10
;
1516 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1517 Key
.ScanCode
= SCAN_PAGE_UP
;
1521 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1522 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1526 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1527 Key
.ScanCode
= SCAN_F9
;
1530 if (TerminalDevice
->TerminalType
== VT100TYPE
) {
1531 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1535 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1536 Key
.ScanCode
= SCAN_F1
;
1540 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1541 Key
.ScanCode
= SCAN_F2
;
1545 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1546 Key
.ScanCode
= SCAN_F3
;
1550 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1551 Key
.ScanCode
= SCAN_F5
;
1555 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1556 Key
.ScanCode
= SCAN_F6
;
1560 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1561 Key
.ScanCode
= SCAN_F7
;
1565 if (TerminalDevice
->TerminalType
== PCANSITYPE
) {
1566 Key
.ScanCode
= SCAN_F8
;
1574 if (Key
.ScanCode
!= SCAN_NULL
) {
1575 Key
.UnicodeChar
= 0;
1576 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1577 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1578 UnicodeToEfiKeyFlushState (TerminalDevice
);
1582 UnicodeToEfiKeyFlushState (TerminalDevice
);
1589 // Invalid state. This should never happen.
1593 UnicodeToEfiKeyFlushState (TerminalDevice
);
1598 if (UnicodeChar
== ESC
) {
1599 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1602 if (UnicodeChar
== CSI
) {
1603 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1606 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1607 Status
= gBS
->SetTimer(
1608 TerminalDevice
->TwoSecondTimeOut
,
1612 ASSERT_EFI_ERROR (Status
);
1616 if (SetDefaultResetState
) {
1617 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1620 if (UnicodeChar
== DEL
) {
1621 Key
.ScanCode
= SCAN_DELETE
;
1622 Key
.UnicodeChar
= 0;
1624 Key
.ScanCode
= SCAN_NULL
;
1625 Key
.UnicodeChar
= UnicodeChar
;
1628 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);