2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2007 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.
21 IN TERMINAL_DEV
*TerminalDevice
,
22 OUT EFI_KEY_DATA
*KeyData
27 Reads the next keystroke from the input device. The WaitForKey Event can
28 be used to test for existance of a keystroke via WaitForEvent () call.
31 TerminalDevice - Terminal driver private structure
32 KeyData - A pointer to a buffer that is filled in with the keystroke
33 state data for the key that was pressed.
36 EFI_SUCCESS - The keystroke information was returned.
37 EFI_NOT_READY - There was no keystroke data availiable.
38 EFI_DEVICE_ERROR - The keystroke information was not returned due to
40 EFI_INVALID_PARAMETER - KeyData is NULL.
46 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
48 if (KeyData
== NULL
) {
49 return EFI_INVALID_PARAMETER
;
53 // Initialize *Key to nonsense value.
55 KeyData
->Key
.ScanCode
= SCAN_NULL
;
56 KeyData
->Key
.UnicodeChar
= 0;
58 Status
= TerminalConInCheckForKey (&TerminalDevice
->SimpleInput
);
59 if (EFI_ERROR (Status
)) {
63 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
67 KeyData
->KeyState
.KeyShiftState
= 0;
68 KeyData
->KeyState
.KeyToggleState
= 0;
71 // Invoke notification functions if exist
73 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
76 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
78 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
80 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
81 CurrentNotify
->KeyNotificationFn (KeyData
);
93 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
94 IN BOOLEAN ExtendedVerification
99 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
100 This driver only perform dependent serial device reset regardless of
101 the value of ExtendeVerification
105 This - Indicates the calling context.
107 ExtendedVerification - Skip by this driver.
112 The reset operation succeeds.
115 The dependent serial port reset fails.
120 TERMINAL_DEV
*TerminalDevice
;
122 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
125 // Report progress code here
127 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
129 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
130 TerminalDevice
->DevicePath
133 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
136 // clear all the internal buffer for keys
138 InitializeRawFiFo (TerminalDevice
);
139 InitializeUnicodeFiFo (TerminalDevice
);
140 InitializeEfiKeyFiFo (TerminalDevice
);
142 if (EFI_ERROR (Status
)) {
143 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
144 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
145 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
146 TerminalDevice
->DevicePath
155 TerminalConInReadKeyStroke (
156 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
157 OUT EFI_INPUT_KEY
*Key
162 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
166 This - Indicates the calling context.
168 Key - A pointer to a buffer that is filled in with the keystroke
169 information for the key that was sent from terminal.
174 The keystroke information is returned successfully.
177 There is no keystroke data available.
180 The dependent serial device encounters error.
184 TERMINAL_DEV
*TerminalDevice
;
186 EFI_KEY_DATA KeyData
;
189 // get TERMINAL_DEV from "This" parameter.
191 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
193 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
194 if (EFI_ERROR (Status
)) {
198 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
207 IN EFI_KEY_DATA
*RegsiteredData
,
208 IN EFI_KEY_DATA
*InputData
216 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
217 state data for the key that was registered.
218 InputData - A pointer to a buffer that is filled in with the keystroke
219 state data for the key that was pressed.
222 TRUE - Key be pressed matches a registered key.
223 FLASE - Match failed.
227 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
229 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
230 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
240 TerminalConInWaitForKeyEx (
247 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
248 Signal the event if there is key available
252 Event - Indicates the event that invoke this function.
254 Context - Indicates the calling context.
262 TERMINAL_DEV
*TerminalDevice
;
264 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context
);
266 TerminalConInWaitForKey (Event
, &TerminalDevice
->SimpleInput
);
271 // Simple Text Input Ex protocol functions
276 TerminalConInResetEx (
277 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
278 IN BOOLEAN ExtendedVerification
283 Reset the input device and optionaly run diagnostics
286 This - Protocol instance pointer.
287 ExtendedVerification - Driver may perform diagnostics on reset.
290 EFI_SUCCESS - The device was reset.
291 EFI_DEVICE_ERROR - The device is not functioning properly and could
297 TERMINAL_DEV
*TerminalDevice
;
299 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
301 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
302 if (EFI_ERROR (Status
)) {
303 return EFI_DEVICE_ERROR
;
312 TerminalConInReadKeyStrokeEx (
313 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
314 OUT EFI_KEY_DATA
*KeyData
319 Reads the next keystroke from the input device. The WaitForKey Event can
320 be used to test for existance of a keystroke via WaitForEvent () call.
323 This - Protocol instance pointer.
324 KeyData - A pointer to a buffer that is filled in with the keystroke
325 state data for the key that was pressed.
328 EFI_SUCCESS - The keystroke information was returned.
329 EFI_NOT_READY - There was no keystroke data availiable.
330 EFI_DEVICE_ERROR - The keystroke information was not returned due to
332 EFI_INVALID_PARAMETER - KeyData is NULL.
336 TERMINAL_DEV
*TerminalDevice
;
338 if (KeyData
== NULL
) {
339 return EFI_INVALID_PARAMETER
;
342 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
344 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
350 TerminalConInSetState (
351 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
352 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
357 Set certain state for the input device.
360 This - Protocol instance pointer.
361 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
362 state for the input device.
365 EFI_SUCCESS - The device state was set successfully.
366 EFI_DEVICE_ERROR - The device is not functioning correctly and could
367 not have the setting adjusted.
368 EFI_UNSUPPORTED - The device does not have the ability to set its state.
369 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
373 if (KeyToggleState
== NULL
) {
374 return EFI_INVALID_PARAMETER
;
382 TerminalConInRegisterKeyNotify (
383 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
384 IN EFI_KEY_DATA
*KeyData
,
385 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
386 OUT EFI_HANDLE
*NotifyHandle
391 Register a notification function for a particular keystroke for the input device.
394 This - Protocol instance pointer.
395 KeyData - A pointer to a buffer that is filled in with the keystroke
396 information data for the key that was pressed.
397 KeyNotificationFunction - Points to the function to be called when the key
398 sequence is typed specified by KeyData.
399 NotifyHandle - Points to the unique handle assigned to the registered notification.
402 EFI_SUCCESS - The notification function was registered successfully.
403 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
404 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
409 TERMINAL_DEV
*TerminalDevice
;
410 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
412 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
414 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
415 return EFI_INVALID_PARAMETER
;
418 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
421 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
423 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
426 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
428 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
430 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
431 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
432 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
439 // Allocate resource to save the notification function
441 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
442 if (NewNotify
== NULL
) {
443 return EFI_OUT_OF_RESOURCES
;
446 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
447 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
448 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
449 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
451 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
453 Status
= gBS
->InstallMultipleProtocolInterfaces (
454 &NewNotify
->NotifyHandle
,
455 &gSimpleTextInExNotifyGuid
,
459 ASSERT_EFI_ERROR (Status
);
460 *NotifyHandle
= NewNotify
->NotifyHandle
;
467 TerminalConInUnregisterKeyNotify (
468 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
469 IN EFI_HANDLE NotificationHandle
474 Remove a registered notification function from a particular keystroke.
477 This - Protocol instance pointer.
478 NotificationHandle - The handle of the notification function being unregistered.
481 EFI_SUCCESS - The notification function was unregistered successfully.
482 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
483 EFI_NOT_FOUND - Can not find the matching entry in database.
488 TERMINAL_DEV
*TerminalDevice
;
490 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
492 if (NotificationHandle
== NULL
) {
493 return EFI_INVALID_PARAMETER
;
496 Status
= gBS
->OpenProtocol (
498 &gSimpleTextInExNotifyGuid
,
502 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
504 if (EFI_ERROR (Status
)) {
505 return EFI_INVALID_PARAMETER
;
508 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
510 for (Link
= TerminalDevice
->NotifyList
.ForwardLink
; Link
!= &TerminalDevice
->NotifyList
; Link
= Link
->ForwardLink
) {
513 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
515 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
517 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
519 // Remove the notification function from NotifyList and free resources
521 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
522 Status
= gBS
->UninstallMultipleProtocolInterfaces (
523 CurrentNotify
->NotifyHandle
,
524 &gSimpleTextInExNotifyGuid
,
528 ASSERT_EFI_ERROR (Status
);
529 gBS
->FreePool (CurrentNotify
);
534 return EFI_NOT_FOUND
;
539 TranslateRawDataToEfiKey (
540 IN TERMINAL_DEV
*TerminalDevice
543 Step1: Turn raw data into Unicode (according to different encode).
544 Step2: Translate Unicode into key information.
545 (according to different terminal standard).
548 switch (TerminalDevice
->TerminalType
) {
553 AnsiRawDataToUnicode (TerminalDevice
);
554 UnicodeToEfiKey (TerminalDevice
);
559 // Process all the raw data in the RawFIFO,
560 // put the processed key into UnicodeFIFO.
562 VTUTF8RawDataToUnicode (TerminalDevice
);
565 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
566 // then put into EfiKeyFIFO.
568 UnicodeToEfiKey (TerminalDevice
);
576 TerminalConInWaitForKey (
583 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
584 Signal the event if there is key available
588 Event - Indicates the event that invoke this function.
590 Context - Indicates the calling context.
599 // Someone is waiting on the keystroke event, if there's
600 // a key pending, signal the event
602 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
604 if (!EFI_ERROR (TerminalConInCheckForKey (Context
))) {
606 gBS
->SignalEvent (Event
);
611 TerminalConInCheckForKey (
612 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
617 Check for a pending key in the Efi Key FIFO or Serial device buffer.
621 This - Indicates the calling context.
626 There is key pending.
629 There is no key pending.
636 TERMINAL_DEV
*TerminalDevice
;
639 EFI_SERIAL_IO_MODE
*Mode
;
640 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
641 UINTN SerialInTimeOut
;
643 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
645 SerialIo
= TerminalDevice
->SerialIo
;
646 if (SerialIo
== NULL
) {
647 return EFI_DEVICE_ERROR
;
650 // if current timeout value for serial device is not identical with
651 // the value saved in TERMINAL_DEV structure, then recalculate the
652 // timeout value again and set serial attribute according to this value.
654 Mode
= SerialIo
->Mode
;
655 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
658 if (Mode
->BaudRate
!= 0) {
659 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
662 Status
= SerialIo
->SetAttributes (
665 Mode
->ReceiveFifoDepth
,
666 (UINT32
) SerialInTimeOut
,
667 (EFI_PARITY_TYPE
) (Mode
->Parity
),
668 (UINT8
) Mode
->DataBits
,
669 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
672 if (EFI_ERROR (Status
)) {
673 TerminalDevice
->SerialInTimeOut
= 0;
675 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
679 // check whether serial buffer is empty
681 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
683 if (Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
685 // Translate all the raw data in RawFIFO into EFI Key,
686 // according to different terminal type supported.
688 TranslateRawDataToEfiKey (TerminalDevice
);
691 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
694 if (!IsEfiKeyFiFoEmpty (TerminalDevice
)) {
697 return EFI_NOT_READY
;
701 // Fetch all the keys in the serial buffer,
702 // and insert the byte stream into RawFIFO.
706 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
708 if (EFI_ERROR (Status
)) {
709 if (Status
== EFI_DEVICE_ERROR
) {
710 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
711 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
712 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError
),
713 TerminalDevice
->DevicePath
719 RawFiFoInsertOneKey (TerminalDevice
, Input
);
723 // Translate all the raw data in RawFIFO into EFI Key,
724 // according to different terminal type supported.
726 TranslateRawDataToEfiKey (TerminalDevice
);
728 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
729 return EFI_NOT_READY
;
736 GetOneKeyFromSerial (
737 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
741 Get one key out of serial buffer.
742 If serial buffer is empty, return EFI_NOT_READY;
743 if reading serial buffer encounter error, returns EFI_DEVICE_ERROR;
744 if reading serial buffer successfully, put the fetched key to
745 the parameter "Input", and return EFI_SUCCESS.
754 Status
= SerialIo
->Read (SerialIo
, &Size
, Input
);
756 if (EFI_ERROR (Status
)) {
758 if (Status
== EFI_TIMEOUT
) {
759 return EFI_NOT_READY
;
762 return EFI_DEVICE_ERROR
;
767 return EFI_NOT_READY
;
774 RawFiFoInsertOneKey (
775 TERMINAL_DEV
*TerminalDevice
,
779 Insert one byte raw data into the Raw Data FIFO.
780 If FIFO is FULL before data insertion,
781 return FALSE, and the key is lost.
786 Tail
= TerminalDevice
->RawFiFo
.Tail
;
788 if (IsRawFiFoFull (TerminalDevice
)) {
795 TerminalDevice
->RawFiFo
.Data
[Tail
] = Input
;
797 TerminalDevice
->RawFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
803 RawFiFoRemoveOneKey (
804 TERMINAL_DEV
*TerminalDevice
,
808 Remove one byte raw data out of the Raw Data FIFO.
809 If FIFO buffer is empty before remove operation,
815 Head
= TerminalDevice
->RawFiFo
.Head
;
817 if (IsRawFiFoEmpty (TerminalDevice
)) {
825 *Output
= TerminalDevice
->RawFiFo
.Data
[Head
];
827 TerminalDevice
->RawFiFo
.Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
834 TERMINAL_DEV
*TerminalDevice
837 Clarify whether FIFO buffer is empty.
840 if (TerminalDevice
->RawFiFo
.Head
== TerminalDevice
->RawFiFo
.Tail
) {
849 TERMINAL_DEV
*TerminalDevice
852 Clarify whether FIFO buffer is full.
858 Tail
= TerminalDevice
->RawFiFo
.Tail
;
859 Head
= TerminalDevice
->RawFiFo
.Head
;
861 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
870 EfiKeyFiFoInsertOneKey (
871 TERMINAL_DEV
*TerminalDevice
,
875 Insert one pre-fetched key into the FIFO buffer.
876 If FIFO buffer is FULL before key insertion,
877 return FALSE, and the key is lost.
882 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
884 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
886 // Efi Key FIFO is full
891 TerminalDevice
->EfiKeyFiFo
.Data
[Tail
] = Key
;
893 TerminalDevice
->EfiKeyFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
899 EfiKeyFiFoRemoveOneKey (
900 TERMINAL_DEV
*TerminalDevice
,
901 EFI_INPUT_KEY
*Output
904 Remove one pre-fetched key out of the FIFO buffer.
905 If FIFO buffer is empty before remove operation,
911 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
913 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
917 Output
->ScanCode
= SCAN_NULL
;
918 Output
->UnicodeChar
= 0;
922 *Output
= TerminalDevice
->EfiKeyFiFo
.Data
[Head
];
924 TerminalDevice
->EfiKeyFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
931 TERMINAL_DEV
*TerminalDevice
934 Clarify whether FIFO buffer is empty.
937 if (TerminalDevice
->EfiKeyFiFo
.Head
== TerminalDevice
->EfiKeyFiFo
.Tail
) {
946 TERMINAL_DEV
*TerminalDevice
949 Clarify whether FIFO buffer is full.
955 Tail
= TerminalDevice
->EfiKeyFiFo
.Tail
;
956 Head
= TerminalDevice
->EfiKeyFiFo
.Head
;
958 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
967 UnicodeFiFoInsertOneKey (
968 TERMINAL_DEV
*TerminalDevice
,
972 Insert one pre-fetched key into the FIFO buffer.
973 If FIFO buffer is FULL before key insertion,
974 return FALSE, and the key is lost.
979 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
981 if (IsUnicodeFiFoFull (TerminalDevice
)) {
983 // Unicode FIFO is full
988 TerminalDevice
->UnicodeFiFo
.Data
[Tail
] = Input
;
990 TerminalDevice
->UnicodeFiFo
.Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
996 UnicodeFiFoRemoveOneKey (
997 TERMINAL_DEV
*TerminalDevice
,
1001 Remove one pre-fetched key out of the FIFO buffer.
1002 If FIFO buffer is empty before remove operation,
1008 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1010 if (IsUnicodeFiFoEmpty (TerminalDevice
)) {
1018 *Output
= TerminalDevice
->UnicodeFiFo
.Data
[Head
];
1020 TerminalDevice
->UnicodeFiFo
.Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1026 IsUnicodeFiFoEmpty (
1027 TERMINAL_DEV
*TerminalDevice
1030 Clarify whether FIFO buffer is empty.
1033 if (TerminalDevice
->UnicodeFiFo
.Head
== TerminalDevice
->UnicodeFiFo
.Tail
) {
1042 TERMINAL_DEV
*TerminalDevice
1045 Clarify whether FIFO buffer is full.
1051 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1052 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1054 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1063 UnicodeFiFoGetKeyCount (
1064 TERMINAL_DEV
*TerminalDevice
1070 Tail
= TerminalDevice
->UnicodeFiFo
.Tail
;
1071 Head
= TerminalDevice
->UnicodeFiFo
.Head
;
1074 return (UINT8
) (Tail
- Head
);
1076 return (UINT8
) (Tail
+ FIFO_MAX_NUMBER
+ 1 - Head
);
1082 UnicodeToEfiKeyFlushState (
1083 IN TERMINAL_DEV
*TerminalDevice
1088 if (TerminalDevice
->InputState
& INPUT_STATE_ESC
) {
1089 Key
.ScanCode
= SCAN_ESC
;
1090 Key
.UnicodeChar
= 0;
1091 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1094 if (TerminalDevice
->InputState
& INPUT_STATE_CSI
) {
1095 Key
.ScanCode
= SCAN_NULL
;
1096 Key
.UnicodeChar
= CSI
;
1097 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1100 if (TerminalDevice
->InputState
& INPUT_STATE_LEFTOPENBRACKET
) {
1101 Key
.ScanCode
= SCAN_NULL
;
1102 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1103 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1106 if (TerminalDevice
->InputState
& INPUT_STATE_O
) {
1107 Key
.ScanCode
= SCAN_NULL
;
1108 Key
.UnicodeChar
= 'O';
1109 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1112 if (TerminalDevice
->InputState
& INPUT_STATE_2
) {
1113 Key
.ScanCode
= SCAN_NULL
;
1114 Key
.UnicodeChar
= '2';
1115 EfiKeyFiFoInsertOneKey (TerminalDevice
, Key
);
1119 TerminalDevice
->TwoSecondTimeOut
,
1124 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1129 IN TERMINAL_DEV
*TerminalDevice
1132 Routine Description:
1134 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1135 can be read through the Simple Input Protocol. The table below shows the keyboard
1136 input mappings that this function supports. If the ESC sequence listed in one of the
1137 columns is presented, then it is translated into the coorespoding EFI Scan Code. If a
1138 matching sequence is not found, then the raw key strokes are converted into EFI Keys.
1140 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1141 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1142 converted into EFI Keys.
1144 There is one special input sequence that will force the system to reset.
1145 This is ESC R ESC r ESC R.
1149 TerminaDevice : The terminal device to use to translate raw input into EFI Keys
1155 Symbols used in table below
1156 ===========================
1162 +=========+======+===========+==========+==========+
1163 | | EFI | EFI 1.10 | | |
1164 | | Scan | | VT100+ | |
1165 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1166 +=========+======+===========+==========+==========+
1167 | NULL | 0x00 | | | |
1168 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1169 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1170 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1171 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1172 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1173 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1174 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1175 | | | ESC [ L | | ESC [ L |
1176 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1177 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1179 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1181 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1182 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1183 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1184 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1185 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1186 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1187 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1188 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1189 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1190 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1191 | Escape | 0x17 | ESC | ESC | ESC |
1192 | F11 | 0x15 | | ESC ! | |
1193 | F12 | 0x16 | | ESC @ | |
1194 +=========+======+===========+==========+==========+
1198 ESC R ESC r ESC R = Reset System
1203 EFI_STATUS TimerStatus
;
1206 BOOLEAN SetDefaultResetState
;
1208 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1210 if (!EFI_ERROR (TimerStatus
)) {
1211 UnicodeToEfiKeyFlushState (TerminalDevice
);
1212 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1215 while (!IsUnicodeFiFoEmpty(TerminalDevice
)) {
1217 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1219 // Check to see if the 2 second timer has expired
1221 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1222 if (!EFI_ERROR (TimerStatus
)) {
1223 UnicodeToEfiKeyFlushState (TerminalDevice
);
1224 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1229 // Fetch one Unicode character from the Unicode FIFO
1231 UnicodeFiFoRemoveOneKey (TerminalDevice
,&UnicodeChar
);
1233 SetDefaultResetState
= TRUE
;
1235 switch (TerminalDevice
->InputState
) {
1236 case INPUT_STATE_DEFAULT
:
1240 case INPUT_STATE_ESC
:
1242 if (UnicodeChar
== LEFTOPENBRACKET
) {
1243 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1244 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1248 if (UnicodeChar
== 'O' && TerminalDevice
->TerminalType
== VT100Type
) {
1249 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1250 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1254 Key
.ScanCode
= SCAN_NULL
;
1256 if (TerminalDevice
->TerminalType
== VT100PlusType
||
1257 TerminalDevice
->TerminalType
== VTUTF8Type
) {
1258 switch (UnicodeChar
) {
1260 Key
.ScanCode
= SCAN_F1
;
1263 Key
.ScanCode
= SCAN_F2
;
1266 Key
.ScanCode
= SCAN_F3
;
1269 Key
.ScanCode
= SCAN_F4
;
1272 Key
.ScanCode
= SCAN_F5
;
1275 Key
.ScanCode
= SCAN_F6
;
1278 Key
.ScanCode
= SCAN_F7
;
1281 Key
.ScanCode
= SCAN_F8
;
1284 Key
.ScanCode
= SCAN_F9
;
1287 Key
.ScanCode
= SCAN_F10
;
1290 Key
.ScanCode
= SCAN_F11
;
1293 Key
.ScanCode
= SCAN_F12
;
1296 Key
.ScanCode
= SCAN_HOME
;
1299 Key
.ScanCode
= SCAN_END
;
1302 Key
.ScanCode
= SCAN_INSERT
;
1305 Key
.ScanCode
= SCAN_DELETE
;
1308 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1311 Key
.ScanCode
= SCAN_PAGE_UP
;
1318 switch (UnicodeChar
) {
1320 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1321 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1322 SetDefaultResetState
= FALSE
;
1323 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_r
) {
1324 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1326 Key
.ScanCode
= SCAN_NULL
;
1329 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1330 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_r
;
1331 SetDefaultResetState
= FALSE
;
1333 Key
.ScanCode
= SCAN_NULL
;
1339 if (SetDefaultResetState
) {
1340 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1343 if (Key
.ScanCode
!= SCAN_NULL
) {
1344 Key
.UnicodeChar
= 0;
1345 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1346 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1347 UnicodeToEfiKeyFlushState (TerminalDevice
);
1351 UnicodeToEfiKeyFlushState (TerminalDevice
);
1355 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1357 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1359 Key
.ScanCode
= SCAN_NULL
;
1361 if (TerminalDevice
->TerminalType
== VT100Type
) {
1362 switch (UnicodeChar
) {
1364 Key
.ScanCode
= SCAN_F1
;
1367 Key
.ScanCode
= SCAN_F2
;
1370 Key
.ScanCode
= SCAN_F3
;
1373 Key
.ScanCode
= SCAN_F4
;
1376 Key
.ScanCode
= SCAN_F5
;
1379 Key
.ScanCode
= SCAN_F6
;
1382 Key
.ScanCode
= SCAN_F7
;
1385 Key
.ScanCode
= SCAN_F8
;
1388 Key
.ScanCode
= SCAN_F9
;
1391 Key
.ScanCode
= SCAN_F10
;
1398 if (Key
.ScanCode
!= SCAN_NULL
) {
1399 Key
.UnicodeChar
= 0;
1400 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1401 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1402 UnicodeToEfiKeyFlushState (TerminalDevice
);
1406 UnicodeToEfiKeyFlushState (TerminalDevice
);
1410 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1412 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1414 Key
.ScanCode
= SCAN_NULL
;
1416 if (TerminalDevice
->TerminalType
== PcAnsiType
||
1417 TerminalDevice
->TerminalType
== VT100Type
||
1418 TerminalDevice
->TerminalType
== VT100PlusType
||
1419 TerminalDevice
->TerminalType
== VTUTF8Type
) {
1420 switch (UnicodeChar
) {
1422 Key
.ScanCode
= SCAN_UP
;
1425 Key
.ScanCode
= SCAN_DOWN
;
1428 Key
.ScanCode
= SCAN_RIGHT
;
1431 Key
.ScanCode
= SCAN_LEFT
;
1434 if (TerminalDevice
->TerminalType
== PcAnsiType
||
1435 TerminalDevice
->TerminalType
== VT100Type
) {
1436 Key
.ScanCode
= SCAN_HOME
;
1440 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1441 Key
.ScanCode
= SCAN_END
;
1445 if (TerminalDevice
->TerminalType
== VT100Type
) {
1446 Key
.ScanCode
= SCAN_END
;
1451 if (TerminalDevice
->TerminalType
== PcAnsiType
||
1452 TerminalDevice
->TerminalType
== VT100Type
) {
1453 Key
.ScanCode
= SCAN_INSERT
;
1457 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1458 Key
.ScanCode
= SCAN_DELETE
;
1462 if (TerminalDevice
->TerminalType
== VT100Type
) {
1463 Key
.ScanCode
= SCAN_DELETE
;
1464 } else if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1465 Key
.ScanCode
= SCAN_F4
;
1469 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1470 Key
.ScanCode
= SCAN_PAGE_UP
;
1474 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1475 Key
.ScanCode
= SCAN_F10
;
1478 if (TerminalDevice
->TerminalType
== VT100Type
) {
1479 Key
.ScanCode
= SCAN_PAGE_UP
;
1483 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1484 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1488 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1489 Key
.ScanCode
= SCAN_F9
;
1492 if (TerminalDevice
->TerminalType
== VT100Type
) {
1493 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1497 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1498 Key
.ScanCode
= SCAN_F1
;
1502 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1503 Key
.ScanCode
= SCAN_F2
;
1507 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1508 Key
.ScanCode
= SCAN_F3
;
1512 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1513 Key
.ScanCode
= SCAN_F5
;
1517 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1518 Key
.ScanCode
= SCAN_F6
;
1522 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1523 Key
.ScanCode
= SCAN_F7
;
1527 if (TerminalDevice
->TerminalType
== PcAnsiType
) {
1528 Key
.ScanCode
= SCAN_F8
;
1536 if (Key
.ScanCode
!= SCAN_NULL
) {
1537 Key
.UnicodeChar
= 0;
1538 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);
1539 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1540 UnicodeToEfiKeyFlushState (TerminalDevice
);
1544 UnicodeToEfiKeyFlushState (TerminalDevice
);
1551 // Invalid state. This should never happen.
1555 UnicodeToEfiKeyFlushState (TerminalDevice
);
1560 if (UnicodeChar
== ESC
) {
1561 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
1564 if (UnicodeChar
== CSI
) {
1565 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
1568 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1569 Status
= gBS
->SetTimer(
1570 TerminalDevice
->TwoSecondTimeOut
,
1574 ASSERT_EFI_ERROR (Status
);
1578 if (SetDefaultResetState
) {
1579 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1582 if (UnicodeChar
== DEL
) {
1583 Key
.ScanCode
= SCAN_DELETE
;
1584 Key
.UnicodeChar
= 0;
1586 Key
.ScanCode
= SCAN_NULL
;
1587 Key
.UnicodeChar
= UnicodeChar
;
1590 EfiKeyFiFoInsertOneKey (TerminalDevice
,Key
);