DebugLib\r
PcdLib\r
UsbLib\r
-\r
+ BaseLib\r
\r
[Guids]\r
gEfiHotPlugDeviceGuid # ALWAYS_CONSUMED\r
-\r
+ gSimpleTextInExNotifyGuid # ALWAYS_CONSUMED\r
\r
[Protocols]\r
gEfiUsbIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
\r
[FixedPcd]\r
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardEnable\r
EFI_GUID gEfiUsbKeyboardDriverGuid = {\r
0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}\r
};\r
+STATIC\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ ); \r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ );\r
+\r
\r
//\r
// USB Keyboard Driver Global Variables\r
UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
+\r
+ UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;\r
+ UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;\r
+ UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;\r
+ UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;\r
+ UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; \r
+ \r
+ InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
+ \r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ USBKeyboardWaitForKey,\r
+ UsbKeyboardDevice,\r
+ &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
&Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
&UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
&gEfiHotPlugDeviceGuid,\r
NULL,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiSimpleTextInProtocolGuid,\r
- &UsbKeyboardDevice->SimpleInput,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
+ &gEfiHotPlugDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
gBS->FreePool (UsbKeyboardDevice);\r
gBS->CloseProtocol (\r
if (EFI_ERROR (Status)) {\r
\r
gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiSimpleTextInProtocolGuid,\r
- &UsbKeyboardDevice->SimpleInput,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
+ &gEfiHotPlugDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
gBS->FreePool (UsbKeyboardDevice);\r
gBS->CloseProtocol (\r
\r
\r
return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+ if (UsbKeyboardDevice != NULL) {\r
+ if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
+ }\r
+ if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
+ }\r
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
+ gBS->FreePool (UsbKeyboardDevice);\r
+ UsbKeyboardDevice = NULL;\r
+ }\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ return Status;\r
+\r
}\r
\r
\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
}\r
-\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
//\r
// Get USB_KB_DEV instance.\r
//\r
Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
&UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
&gEfiHotPlugDeviceGuid,\r
NULL,\r
NULL\r
gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);\r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); \r
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
\r
if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
\r
}\r
\r
+STATIC\r
+EFI_STATUS\r
+USBKeyboardReadKeyStrokeWorker (\r
+ IN USB_KB_DEV *UsbKeyboardDevice,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
\r
+ Arguments:\r
+ UsbKeyboardDevice - Usb keyboard private structure.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
\r
-/**\r
- Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset() function.\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
\r
- This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
- ExtendedVerification\r
- Indicates that the driver may perform a more exhaustive\r
- verification operation of the device during reset.\r
+--*/\r
+{\r
\r
- @retval EFI_SUCCESS Success\r
- @retval EFI_DEVICE_ERROR Hardware Error\r
+ EFI_STATUS Status;\r
+ UINT8 KeyChar; \r
+ LIST_ENTRY *Link;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ EFI_KEY_DATA OriginalKeyData;\r
\r
-**/\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // if there is no saved ASCII byte, fetch it\r
+ // by calling USBKeyboardCheckForKey().\r
+ //\r
+ if (UsbKeyboardDevice->CurKeyChar == 0) {\r
+ Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ KeyData->Key.UnicodeChar = 0;\r
+ KeyData->Key.ScanCode = SCAN_NULL;\r
+\r
+ KeyChar = UsbKeyboardDevice->CurKeyChar;\r
+\r
+ UsbKeyboardDevice->CurKeyChar = 0;\r
+\r
+ //\r
+ // Translate saved ASCII byte into EFI_INPUT_KEY\r
+ //\r
+ Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));\r
+ \r
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+\r
+ //\r
+ //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to \r
+ // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.\r
+ //\r
+ CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+ if (UsbKeyboardDevice->CtrlOn) {\r
+ if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
+ if (UsbKeyboardDevice->CapsOn) {\r
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
+ } else {\r
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
+ } \r
+ }\r
+ }\r
+ \r
+ //\r
+ // Invoke notification functions if exist\r
+ //\r
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
+ CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ \r
+}\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReset (\r
OUT EFI_INPUT_KEY *Key\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_STATUS Status;\r
- UINT8 KeyChar;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_STATUS Status;\r
+ EFI_KEY_DATA KeyData;\r
\r
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
\r
- //\r
- // if there is no saved ASCII byte, fetch it\r
- // by calling USBKeyboardCheckForKey().\r
- //\r
- if (UsbKeyboardDevice->CurKeyChar == 0) {\r
- Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
- Key->UnicodeChar = 0;\r
- Key->ScanCode = SCAN_NULL;\r
-\r
- KeyChar = UsbKeyboardDevice->CurKeyChar;\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
\r
- UsbKeyboardDevice->CurKeyChar = 0;\r
-\r
- //\r
- // Translate saved ASCII byte into EFI_INPUT_KEY\r
- //\r
- Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);\r
-\r
- return Status;\r
+ return EFI_SUCCESS;\r
\r
}\r
\r
DevicePath\r
);\r
}\r
+STATIC\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ ListHead - The list head\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Free the notify list successfully\r
+ EFI_INVALID_PARAMETER - ListHead is invalid.\r
+\r
+--*/\r
+{\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+ if (ListHead == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ while (!IsListEmpty (ListHead)) {\r
+ NotifyNode = CR (\r
+ ListHead->ForwardLink, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ RemoveEntryList (ListHead->ForwardLink);\r
+ gBS->FreePool (NotifyNode);\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE; \r
+ } \r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions \r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_TPL OldTpl;\r
+ \r
+\r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+ Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+ return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+{\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+ if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
+ ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Update the status light\r
+ //\r
+\r
+ UsbKeyboardDevice->ScrollOn = 0;\r
+ UsbKeyboardDevice->NumLockOn = 0;\r
+ UsbKeyboardDevice->CapsOn = 0;\r
+ \r
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
+ UsbKeyboardDevice->ScrollOn = 1;\r
+ }\r
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
+ UsbKeyboardDevice->NumLockOn = 1;\r
+ }\r
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
+ UsbKeyboardDevice->CapsOn = 1;\r
+ }\r
+\r
+ SetKeyLED (UsbKeyboardDevice);\r
+\r
+ UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
+\r
+ return EFI_SUCCESS;\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+{\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Allocate resource to save the notification function\r
+ // \r
+ NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+ InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
+\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+ \r
+ return EFI_SUCCESS;\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+{\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ \r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ ); \r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ //\r
+ // Remove the notification function from NotifyList and free resources\r
+ //\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify); \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND; \r
+}\r
+\r
#include <PiDxe.h>\r
\r
#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
#include <Guid/HotPlugDevice.h>\r
#include <Protocol/UsbIo.h>\r
#include <Protocol/DevicePath.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/UsbLib.h>\r
-\r
+#include <Library/BaseLib.h>\r
\r
#include <IndustryStandard/Usb.h>\r
\r
} USB_KB_BUFFER;\r
\r
#define USB_KB_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'd')\r
+#define USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'x')\r
+\r
+typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY {\r
+ UINTN Signature;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;\r
+ LIST_ENTRY NotifyEntry;\r
+} KEYBOARD_CONSOLE_IN_EX_NOTIFY;\r
typedef struct {\r
UINTN Signature;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
EFI_EVENT DelayedRecoveryEvent;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleInput;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
\r
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
EFI_USB_ENDPOINT_DESCRIPTOR IntEndpointDescriptor;\r
EFI_EVENT RepeatTimer;\r
\r
EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
-\r
+ \r
+ UINT8 LeftCtrlOn;\r
+ UINT8 LeftAltOn;\r
+ UINT8 LeftShiftOn;\r
+ UINT8 LeftLogoOn;\r
+ UINT8 RightCtrlOn;\r
+ UINT8 RightAltOn;\r
+ UINT8 RightShiftOn;\r
+ UINT8 RightLogoOn; \r
+ UINT8 MenuKeyOn;\r
+ UINT8 SysReqOn;\r
+\r
+ EFI_KEY_STATE KeyState;\r
+ //\r
+ // Notification function list\r
+ //\r
+ LIST_ENTRY NotifyList;\r
} USB_KB_DEV;\r
\r
//\r
extern EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName;\r
extern EFI_COMPONENT_NAME2_PROTOCOL gUsbKeyboardComponentName2;\r
extern EFI_GUID gEfiUsbKeyboardDriverGuid;\r
+extern EFI_GUID gSimpleTextInExNotifyGuid;\r
\r
VOID\r
KbdReportStatusCode (\r
\r
#define USB_KB_DEV_FROM_THIS(a) \\r
CR(a, USB_KB_DEV, SimpleInput, USB_KB_DEV_SIGNATURE)\r
+#define TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS(a) \\r
+ CR(a, USB_KB_DEV, SimpleInputEx, USB_KB_DEV_SIGNATURE)\r
+\r
\r
#define MOD_CONTROL_L 0x01\r
#define MOD_CONTROL_R 0x10\r
UINT8 Key;\r
} KB_MODIFIER;\r
\r
-#define USB_KEYCODE_MAX_MAKE 0x64\r
+#define USB_KEYCODE_MAX_MAKE 0x7E\r
\r
#define USBKBD_VALID_KEYCODE(key) ((UINT8) (key) > 3)\r
\r
UINT8 ScrollLock : 1;\r
UINT8 Resrvd : 5;\r
} LED_MAP;\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+;\r
+\r
#endif\r
+\r
{ SCAN_F8, 0x00, 0x00 }, // 0x41\r
{ SCAN_F9, 0x00, 0x00 }, // 0x42\r
{ SCAN_F10, 0x00, 0x00 }, // 0x43\r
- { SCAN_F11, 0x00, 0x00 }, // 0x44 F11\r
- { SCAN_F12, 0x00, 0x00 }, // 0x45 F12\r
+ { SCAN_F11, 0x00, 0x00 }, // 0x44 F11\r
+ { SCAN_F12, 0x00, 0x00 }, // 0x45 F12\r
{ SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen\r
{ SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock\r
{ SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause\r
{ SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |\r
{ SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application\r
{ SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power\r
- { SCAN_NULL, '=' , '=' } // 0x67 Keypad =\r
+ { SCAN_NULL, '=' , '=' }, // 0x67 Keypad =\r
+ { SCAN_F13, 0x00, 0x00 }, // 0x68\r
+ { SCAN_F14, 0x00, 0x00 }, // 0x69\r
+ { SCAN_F15, 0x00, 0x00 }, // 0x6A \r
+ { SCAN_F16, 0x00, 0x00 }, // 0x6B \r
+ { SCAN_F17, 0x00, 0x00 }, // 0x6C\r
+ { SCAN_F18, 0x00, 0x00 }, // 0x6D\r
+ { SCAN_F19, 0x00, 0x00 }, // 0x6E\r
+ { SCAN_F20, 0x00, 0x00 }, // 0x6F\r
+ { SCAN_F21, 0x00, 0x00 }, // 0x70\r
+ { SCAN_F22, 0x00, 0x00 }, // 0x71\r
+ { SCAN_F23, 0x00, 0x00 }, // 0x72\r
+ { SCAN_F24, 0x00, 0x00 }, // 0x73\r
+ { SCAN_MUTE, 0x00, 0x00 }, // 0x7F\r
+ { SCAN_VOLUME_UP, 0x00, 0x00 }, // 0x80\r
+ { SCAN_VOLUME_DOWN, 0x00, 0x00 }, // 0x81\r
};\r
\r
STATIC KB_MODIFIER KB_Mod[8] = {\r
{ MOD_ALT_L, 0xe2 }, // 11100010\r
{ MOD_ALT_R, 0xe6 }, // 11100110\r
{ MOD_WIN_L, 0xe3 }, // 11100011\r
- { MOD_WIN_R, 0xe7 } // 11100111\r
+ { MOD_WIN_R, 0xe7 }, // 11100111 \r
};\r
\r
\r
UsbKeyboardDevice->NumLockOn = 0;\r
UsbKeyboardDevice->CapsOn = 0;\r
UsbKeyboardDevice->ScrollOn = 0;\r
+ \r
+ UsbKeyboardDevice->LeftCtrlOn = 0;\r
+ UsbKeyboardDevice->LeftAltOn = 0;\r
+ UsbKeyboardDevice->LeftShiftOn = 0; \r
+ UsbKeyboardDevice->LeftLogoOn = 0; \r
+ UsbKeyboardDevice->RightCtrlOn = 0;\r
+ UsbKeyboardDevice->RightAltOn = 0;\r
+ UsbKeyboardDevice->RightShiftOn = 0; \r
+ UsbKeyboardDevice->RightLogoOn = 0; \r
+ UsbKeyboardDevice->MenuKeyOn = 0;\r
+ UsbKeyboardDevice->SysReqOn = 0; \r
\r
//\r
// Sync the initial state of lights\r
if (!UsbKey.Down) {\r
switch (UsbKey.KeyCode) {\r
\r
+ //\r
+ // CTRL release\r
+ //\r
case 0xe0:\r
+ UsbKeyboardDevice->LeftCtrlOn = 0;\r
+ UsbKeyboardDevice->CtrlOn = 0;\r
+ break;\r
case 0xe4:\r
+ UsbKeyboardDevice->RightCtrlOn = 0;\r
UsbKeyboardDevice->CtrlOn = 0;\r
break;\r
\r
+ //\r
+ // Shift release\r
+ //\r
case 0xe1:\r
+ UsbKeyboardDevice->LeftShiftOn = 0;\r
+ UsbKeyboardDevice->ShiftOn = 0;\r
+ break;\r
case 0xe5:\r
+ UsbKeyboardDevice->RightShiftOn = 0;\r
UsbKeyboardDevice->ShiftOn = 0;\r
break;\r
\r
+ //\r
+ // Alt release\r
+ //\r
case 0xe2:\r
+ UsbKeyboardDevice->LeftAltOn = 0;\r
+ UsbKeyboardDevice->AltOn = 0;\r
+ break;\r
case 0xe6:\r
+ UsbKeyboardDevice->RightAltOn = 0;\r
UsbKeyboardDevice->AltOn = 0;\r
break;\r
\r
+ //\r
+ // Logo release\r
+ //\r
+ case 0xe3:\r
+ UsbKeyboardDevice->LeftLogoOn = 0;\r
+ break;\r
+ case 0xe7:\r
+ UsbKeyboardDevice->RightLogoOn = 0;\r
+ break;\r
+\r
+ //\r
+ // Menu key (App/Apps) release\r
+ //\r
+ case 0x65:\r
+ UsbKeyboardDevice->MenuKeyOn = 0;\r
+ break;\r
+\r
+ //\r
+ // SysReq release\r
+ //\r
+ case 0x46:\r
+ UsbKeyboardDevice->SysReqOn = 0;\r
+ break;\r
default:\r
break;\r
}\r
switch (UsbKey.KeyCode) {\r
\r
case 0xe0:\r
+ UsbKeyboardDevice->LeftCtrlOn = 1;\r
+ UsbKeyboardDevice->CtrlOn = 1;\r
+ continue; \r
+ break;\r
case 0xe4:\r
+ UsbKeyboardDevice->RightCtrlOn = 1;\r
UsbKeyboardDevice->CtrlOn = 1;\r
continue;\r
break;\r
\r
+ //\r
+ // Shift press\r
+ //\r
case 0xe1:\r
+ UsbKeyboardDevice->LeftShiftOn = 1;\r
+ UsbKeyboardDevice->ShiftOn = 1;\r
+ continue;\r
+ break;\r
case 0xe5:\r
+ UsbKeyboardDevice->RightShiftOn = 1; \r
UsbKeyboardDevice->ShiftOn = 1;\r
continue;\r
break;\r
\r
+ //\r
+ // Alt press\r
+ //\r
case 0xe2:\r
+ UsbKeyboardDevice->LeftAltOn = 1;\r
+ UsbKeyboardDevice->AltOn = 1;\r
+ continue;\r
+ break;\r
case 0xe6:\r
+ UsbKeyboardDevice->RightAltOn = 1; \r
UsbKeyboardDevice->AltOn = 1;\r
continue;\r
break;\r
\r
+ //\r
+ // Logo press\r
+ //\r
case 0xe3:\r
+ UsbKeyboardDevice->LeftLogoOn = 1;\r
+ continue; \r
+ break;\r
case 0xe7:\r
+ UsbKeyboardDevice->RightLogoOn = 1;\r
continue;\r
break;\r
\r
- case 0x53:\r
- UsbKeyboardDevice->NumLockOn ^= 1;\r
//\r
- // Turn on the NumLock light on KB\r
+ // Menu key (App/Apps) press\r
+ //\r
+ case 0x65:\r
+ UsbKeyboardDevice->MenuKeyOn = 1;\r
+ continue; \r
+ break;\r
+\r
+ //\r
+ // SysReq press\r
//\r
+ case 0x46:\r
+ UsbKeyboardDevice->SysReqOn = 1;\r
+ continue; \r
+ break;\r
+\r
+ case 0x53:\r
+ UsbKeyboardDevice->NumLockOn ^= 1;\r
+ //\r
+ // Turn on the NumLock light on KB\r
+ //\r
SetKeyLED (UsbKeyboardDevice);\r
continue;\r
break;\r
\r
case 0x39:\r
UsbKeyboardDevice->CapsOn ^= 1;\r
- //\r
- // Turn on the CapsLock light on KB\r
- //\r
+ //\r
+ // Turn on the CapsLock light on KB\r
+ //\r
SetKeyLED (UsbKeyboardDevice);\r
continue;\r
break;\r
\r
case 0x47:\r
UsbKeyboardDevice->ScrollOn ^= 1;\r
- //\r
- // Turn on the ScrollLock light on KB\r
- //\r
+ //\r
+ // Turn on the ScrollLock light on KB\r
+ //\r
SetKeyLED (UsbKeyboardDevice);\r
continue;\r
break;\r
// keys are not valid EFI key\r
//\r
\r
- case 0x46:\r
- //\r
- // fall through\r
//\r
+ // PrintScreen/SysRq key and Application key\r
+ // Should be handled by UEFI2.1 compliant code\r
+\r
case 0x48:\r
//\r
// fall through\r
//\r
- case 0x65:\r
- //\r
- // fall through\r
- //\r
case 0x66:\r
//\r
// fall through\r
return EFI_NOT_READY;\r
}\r
\r
+ //\r
+ // Undefined entries from 0x74 to 0x7E\r
+ //\r
+ if (KeyChar > USB_KEYCODE_MAX_MAKE) {\r
+ Index = (UINT8) (Index - 11);\r
+ }\r
+\r
Key->ScanCode = KeyConvertionTable[Index][0];\r
\r
if (UsbKeyboardDevice->ShiftOn) {\r
\r
Key->UnicodeChar = KeyConvertionTable[Index][2];\r
+ //\r
+ // Need not return associated shift state if a class of printable characters that\r
+ // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
+ //\r
+ if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
+ UsbKeyboardDevice->LeftShiftOn = 0;\r
+ UsbKeyboardDevice->RightShiftOn = 0;\r
+ }\r
\r
} else {\r
\r
return EFI_NOT_READY;\r
}\r
\r
+\r
+ //\r
+ // Save Shift/Toggle state\r
+ //\r
+ if (UsbKeyboardDevice->LeftCtrlOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->RightCtrlOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->LeftAltOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->RightAltOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->LeftShiftOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->RightShiftOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->LeftLogoOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->RightLogoOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->MenuKeyOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
+ }\r
+ if (UsbKeyboardDevice->SysReqOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
+ } \r
+\r
+ if (UsbKeyboardDevice->ScrollOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+ }\r
+ if (UsbKeyboardDevice->NumLockOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
+ }\r
+ if (UsbKeyboardDevice->CapsOn == 1) {\r
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+ }\r
+\r
return EFI_SUCCESS;\r
\r
}\r
0,\r
(EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
0,\r
+ {\r
+ ConSplitterTextInResetEx,\r
+ ConSplitterTextInReadKeyStrokeEx,\r
+ (EFI_EVENT) NULL,\r
+ ConSplitterTextInSetState,\r
+ ConSplitterTextInRegisterKeyNotify,\r
+ ConSplitterTextInUnregisterKeyNotify\r
+ },\r
+ 0,\r
+ (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
+ 0,\r
+ {\r
+ (struct _LIST_ENTRY *) NULL,\r
+ (struct _LIST_ENTRY *) NULL\r
+ },\r
\r
{\r
ConSplitterSimplePointerReset,\r
&mConIn.VirtualHandle,\r
&gEfiSimpleTextInProtocolGuid,\r
&mConIn.TextIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &mConIn.TextInEx,\r
&gEfiSimplePointerProtocolGuid,\r
&mConIn.SimplePointer,\r
&gEfiPrimaryConsoleInDeviceGuid,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Buffer for Simple Text Input Ex Protocol\r
+ // \r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &ConInPrivate->TextInExListCount,\r
+ (VOID **) &ConInPrivate->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ ConSplitterTextInWaitForKey,\r
+ ConInPrivate,\r
+ &ConInPrivate->TextInEx.WaitForKeyEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InitializeListHead (&ConInPrivate->NotifyList); \r
+\r
+\r
ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
\r
Status = ConSplitterGrowBuffer (\r
{\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
return Status;\r
}\r
\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ mConIn.VirtualHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+\r
return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
}\r
\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
if (NumberOfChildren == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ \r
Status = ConSplitterStop (\r
This,\r
ControllerHandle,\r
return EFI_NOT_FOUND;\r
}\r
\r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If the TextInEx List is full, enlarge it by calling growbuffer().\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &Private->TextInExListCount,\r
+ (VOID **) &Private->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // Add the new text-in device data structure into the Text In List.\r
+ //\r
+ Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
+ Private->CurrentNumberOfExConsoles++;\r
+\r
+ //\r
+ // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
+ //\r
+ gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ UINTN Index;\r
+ //\r
+ // Remove the specified text-in device data structure from the Text In List,\r
+ // and rearrange the remaining data structures in the Text In List.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ if (Private->TextInExList[Index] == TextInEx) {\r
+ for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+ Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
+ }\r
+\r
+ Private->CurrentNumberOfExConsoles--;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
EFI_STATUS\r
ConSplitterSimplePointerAddDevice (\r
IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
}\r
}\r
\r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE; \r
+ } \r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN Index;\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ //\r
+ // return the worst status met\r
+ //\r
+ for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->Reset (\r
+ Private->TextInExList[Index],\r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_KEY_DATA CurrentKeyData;\r
+\r
+ \r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+ if (Private->PasswordEnabled) {\r
+ //\r
+ // If StdIn Locked return not ready\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ KeyData->Key.UnicodeChar = 0;\r
+ KeyData->Key.ScanCode = SCAN_NULL;\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_NOT_READY;\r
+ // if any physical console input device has key input,\r
+ // return the key and EFI_SUCCESS.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
+ Private->TextInExList[Index],\r
+ &CurrentKeyData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_READY; \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_SUCCESS;\r
+ // otherwise return the status of setting state of physical console input device\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->SetState (\r
+ Private->TextInExList[Index],\r
+ KeyToggleState\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS; \r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; \r
+ \r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, \r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ TEXT_IN_EX_SPLITTER_NOTIFY, \r
+ NotifyEntry, \r
+ TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Allocate resource to save the notification function\r
+ // \r
+ NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+ if (NewNotify->NotifyHandleList == NULL) {\r
+ gBS->FreePool (NewNotify);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE; \r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+ \r
+ //\r
+ // Return the wrong status of registering key notify of \r
+ // physical console input device if meet problems\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ KeyData,\r
+ KeyNotificationFunction,\r
+ &NewNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (NewNotify->NotifyHandleList);\r
+ gBS->FreePool (NewNotify);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ \r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+ \r
+ return EFI_SUCCESS; \r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
+ LIST_ENTRY *Link; \r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, \r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
+ Private->TextInExList[Index], \r
+ CurrentNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+ }\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify->NotifyHandleList);\r
+ gBS->FreePool (CurrentNotify);\r
+ return EFI_SUCCESS; \r
+ } \r
+ }\r
+\r
+ return EFI_NOT_FOUND; \r
+ \r
+}\r
+\r
+\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterSimplePointerReset (\r
#include <Protocol/SimpleTextOut.h>\r
#include <Guid/ConsoleInDevice.h>\r
#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
#include <Protocol/ConsoleControl.h>\r
#include <Guid/StandardErrorDevice.h>\r
#include <Guid/ConsoleOutDevice.h>\r
extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName;\r
extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterStdErrComponentName2;\r
\r
+extern EFI_GUID gSimpleTextInExNotifyGuid;\r
+\r
// These definitions were in the old Hii protocol, but are not in the new UEFI\r
// version. So they are defined locally.\r
#define UNICODE_NARROW_CHAR 0xFFF0\r
//\r
#define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'p')\r
\r
+#define TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'n')\r
+\r
+typedef struct _TEXT_IN_EX_SPLITTER_NOTIFY {\r
+ UINTN Signature;\r
+ EFI_HANDLE *NotifyHandleList;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;\r
+ LIST_ENTRY NotifyEntry;\r
+} TEXT_IN_EX_SPLITTER_NOTIFY;\r
typedef struct {\r
UINT64 Signature;\r
EFI_HANDLE VirtualHandle;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL **TextInList;\r
UINTN TextInListCount;\r
\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL TextInEx;\r
+ UINTN CurrentNumberOfExConsoles;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **TextInExList;\r
+ UINTN TextInExListCount;\r
+ LIST_ENTRY NotifyList; \r
+\r
+\r
EFI_SIMPLE_POINTER_PROTOCOL SimplePointer;\r
EFI_SIMPLE_POINTER_MODE SimplePointerMode;\r
UINTN CurrentNumberOfPointers;\r
SimplePointer, \\r
TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \\r
)\r
+#define TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA, \\r
+ TextInEx, \\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \\r
+ )\r
+\r
+#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS(a) \\r
+ CR (a, \\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA, \\r
+ AbsolutePointer, \\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \\r
+ )\r
\r
//\r
// Private data for the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL splitter\r
OUT EFI_INPUT_KEY *Key\r
)\r
;\r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+;\r
+\r
+//\r
+// Simple Text Input Ex protocol function prototypes\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+;\r
\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+;\r
VOID\r
EFIAPI\r
ConSplitterTextInWaitForKey (\r
EFI_STATUS\r
EFIAPI\r
ConSpliterGraphicsOutputQueryMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber,\r
- OUT UINTN *SizeOfInfo,\r
- OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber,\r
+ OUT UINTN *SizeOfInfo,\r
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
)\r
;\r
\r
gEfiPrimaryConsoleOutDeviceGuid # ALWAYS_PRODUCED\r
gEfiPrimaryConsoleInDeviceGuid # ALWAYS_PRODUCED\r
gEfiPrimaryStandardErrorDeviceGuid # ALWAYS_PRODUCED\r
+ gSimpleTextInExNotifyGuid # ALWAYS_PRODUCED\r
\r
[Protocols]\r
gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
gEfiSimplePointerProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
\r
#include "Terminal.h"\r
\r
+STATIC\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ ); \r
+\r
//\r
// Globals\r
//\r
NULL, \r
INPUT_STATE_DEFAULT,\r
RESET_STATE_DEFAULT,\r
- FALSE\r
+ FALSE,\r
+ { // SimpleTextInputEx\r
+ TerminalConInResetEx,\r
+ TerminalConInReadKeyStrokeEx,\r
+ NULL,\r
+ TerminalConInSetState,\r
+ TerminalConInRegisterKeyNotify,\r
+ TerminalConInUnregisterKeyNotify,\r
+ },\r
+ {\r
+ NULL,\r
+ NULL,\r
+ }\r
};\r
\r
\r
TerminalDevice->TerminalType = TerminalType;\r
TerminalDevice->SerialIo = SerialIo;\r
\r
+ InitializeListHead (&TerminalDevice->NotifyList);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ TerminalConInWaitForKeyEx,\r
+ &TerminalDevice->SimpleInputEx,\r
+ &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
-\r
//\r
// initialize the FIFO buffer used for accommodating\r
// the pre-read pending characters\r
// keystroke response performance issue\r
//\r
Mode = TerminalDevice->SerialIo->Mode;\r
+\r
SerialInTimeOut = 0;\r
if (Mode->BaudRate != 0) {\r
SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
TerminalDevice->DevicePath,\r
&gEfiSimpleTextInProtocolGuid,\r
&TerminalDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &TerminalDevice->SimpleInputEx,\r
&gEfiSimpleTextOutProtocolGuid,\r
&TerminalDevice->SimpleTextOutput,\r
NULL\r
gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
}\r
\r
+ if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+ }\r
+\r
+ TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+\r
if (TerminalDevice->ControllerNameTable != NULL) {\r
FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
}\r
ChildHandleBuffer[Index],\r
&gEfiSimpleTextInProtocolGuid,\r
&TerminalDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &TerminalDevice->SimpleInputEx,\r
&gEfiSimpleTextOutProtocolGuid,\r
&TerminalDevice->SimpleTextOutput,\r
&gEfiDevicePathProtocolGuid,\r
\r
gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
+ gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+ TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
FreePool (TerminalDevice->DevicePath);\r
FreePool (TerminalDevice);\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+STATIC\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+ IN OUT LIST_ENTRY *ListHead\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ ListHead - The list head\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Free the notify list successfully\r
+ EFI_INVALID_PARAMETER - ListHead is invalid.\r
+\r
+--*/\r
+{\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+ if (ListHead == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ while (!IsListEmpty (ListHead)) {\r
+ NotifyNode = CR (\r
+ ListHead->ForwardLink, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ RemoveEntryList (ListHead->ForwardLink);\r
+ gBS->FreePool (NotifyNode);\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
VOID\r
TerminalUpdateConsoleDevVariable (\r
IN CHAR16 *VariableName,\r
#include <Guid/GlobalVariable.h>\r
#include <Protocol/DevicePath.h>\r
#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
#include <Guid/HotPlugDevice.h>\r
#include <Guid/PcAnsi.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/PcdLib.h>\r
-\r
+#include <Library/BaseLib.h>\r
\r
\r
#define RAW_FIFO_MAX_NUMBER 256\r
\r
#define TERMINAL_DEV_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'n', 'l')\r
\r
+#define TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'e', 'n')\r
+\r
+typedef struct _TERMINAL_CONSOLE_IN_EX_NOTIFY {\r
+ UINTN Signature;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;\r
+ LIST_ENTRY NotifyEntry;\r
+} TERMINAL_CONSOLE_IN_EX_NOTIFY;\r
typedef struct {\r
UINTN Signature;\r
EFI_HANDLE Handle;\r
// to indicate whether the Esc could be sent or not.\r
//\r
BOOLEAN OutputEscChar;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;\r
+ LIST_ENTRY NotifyList;\r
} TERMINAL_DEV;\r
\r
#define INPUT_STATE_DEFAULT 0x00\r
\r
#define TERMINAL_CON_IN_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInput, TERMINAL_DEV_SIGNATURE)\r
#define TERMINAL_CON_OUT_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleTextOutput, TERMINAL_DEV_SIGNATURE)\r
+#define TERMINAL_CON_IN_EX_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInputEx, TERMINAL_DEV_SIGNATURE)\r
\r
typedef union {\r
UINT8 Utf8_1;\r
extern EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName;\r
extern EFI_COMPONENT_NAME2_PROTOCOL gTerminalComponentName2;\r
\r
+extern EFI_GUID gSimpleTextInExNotifyGuid;\r
//\r
// Prototypes\r
//\r
)\r
;\r
\r
+\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+TerminalConInWaitForKeyEx (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+; \r
+//\r
+// Simple Text Input Ex protocol prototypes\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+;\r
+\r
VOID\r
EFIAPI\r
TerminalConInWaitForKey (\r
/**@file\r
- Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
- \r
+ Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
+ \r
Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
All rights reserved. This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
#include "Terminal.h"\r
\r
\r
+STATIC\r
+EFI_STATUS\r
+ReadKeyStrokeWorker (\r
+ IN TERMINAL_DEV *TerminalDevice,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ TerminalDevice - Terminal driver private structure\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ //\r
+ // Initialize *Key to nonsense value.\r
+ //\r
+ KeyData->Key.ScanCode = SCAN_NULL;\r
+ KeyData->Key.UnicodeChar = 0;\r
+\r
+ Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ KeyData->KeyState.KeyShiftState = 0;\r
+ KeyData->KeyState.KeyToggleState = 0;\r
+\r
+ //\r
+ // Invoke notification functions if exist\r
+ //\r
+ for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ CurrentNotify->KeyNotificationFn (KeyData);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
EFI_STATUS\r
EFIAPI\r
TerminalConInReset (\r
{\r
TERMINAL_DEV *TerminalDevice;\r
EFI_STATUS Status;\r
+ EFI_KEY_DATA KeyData;\r
\r
- //\r
- // Initialize *Key to nonsense value.\r
- //\r
- Key->ScanCode = SCAN_NULL;\r
- Key->UnicodeChar = 0;\r
//\r
// get TERMINAL_DEV from "This" parameter.\r
//\r
TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
\r
- Status = TerminalConInCheckForKey (This);\r
+ Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);\r
if (EFI_ERROR (Status)) {\r
- return EFI_NOT_READY;\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+}\r
+\r
+\r
+VOID\r
+EFIAPI\r
+TerminalConInWaitForKeyEx (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+ Routine Description:\r
+ \r
+ Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
+ Signal the event if there is key available \r
+ \r
+ Arguments:\r
+ \r
+ Event - Indicates the event that invoke this function.\r
+ \r
+ Context - Indicates the calling context.\r
+ \r
+ Returns:\r
+ \r
+ N/A\r
+ \r
+--*/\r
+{\r
+ TERMINAL_DEV *TerminalDevice;\r
+ \r
+ TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);\r
+\r
+ TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ TERMINAL_DEV *TerminalDevice;\r
+\r
+ TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+ Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- EfiKeyFiFoRemoveOneKey (TerminalDevice, Key);\r
+ return EFI_SUCCESS;\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ TERMINAL_DEV *TerminalDevice;\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+ return ReadKeyStrokeWorker (TerminalDevice, KeyData);\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+{\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
return EFI_SUCCESS;\r
+}\r
\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+{\r
+ EFI_STATUS Status;\r
+ TERMINAL_DEV *TerminalDevice;\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate resource to save the notification function\r
+ // \r
+ NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } \r
+\r
+ NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+ InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+{\r
+ EFI_STATUS Status;\r
+ TERMINAL_DEV *TerminalDevice;\r
+ LIST_ENTRY *Link;\r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ \r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+ for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ //\r
+ // Remove the notification function from NotifyList and free resources\r
+ //\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify); \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ return EFI_NOT_FOUND; \r
+}\r
+\r
+\r
VOID\r
TranslateRawDataToEfiKey (\r
IN TERMINAL_DEV *TerminalDevice\r
| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |\r
| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |\r
| Escape | 0x17 | ESC | ESC | ESC |\r
-+=========+======+===========+==========+=========+\r
+| F11 | 0x15 | | ESC ! | |\r
+| F12 | 0x16 | | ESC @ | |\r
++=========+======+===========+==========+==========+\r
\r
Special Mappings\r
================\r
case '0': \r
Key.ScanCode = SCAN_F10; \r
break;\r
+ case '!':\r
+ Key.ScanCode = SCAN_F11;\r
+ break;\r
+ case '@':\r
+ Key.ScanCode = SCAN_F12;\r
+ break; \r
case 'h': \r
Key.ScanCode = SCAN_HOME; \r
break;\r
if (UnicodeChar == ESC) {\r
TerminalDevice->InputState = INPUT_STATE_ESC;\r
}\r
+\r
+ if (UnicodeChar == CSI) {\r
+ TerminalDevice->InputState = INPUT_STATE_CSI;\r
+ }\r
\r
if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
Status = gBS->SetTimer(\r
UefiDriverEntryPoint\r
DebugLib\r
PcdLib\r
+ BaseLib\r
\r
[Guids]\r
gEfiGlobalVariableGuid # SOMETIMES_CONSUMED L"ErrOutDev"\r
gEfiVT100Guid # SOMETIMES_CONSUMED\r
gEfiVT100PlusGuid # SOMETIMES_CONSUMED\r
gEfiPcAnsiGuid # SOMETIMES_CONSUMED\r
-\r
+ gSimpleTextInExNotifyGuid # SOMETIMES_CONSUMED\r
\r
[Protocols]\r
gEfiHotPlugDeviceGuid # PROTOCOL SOMETIMES_CONSUMED\r
gEfiSerialIoProtocolGuid # PROTOCOL TO_START\r
gEfiDevicePathProtocolGuid # PROTOCOL TO_START\r
gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START\r
gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START\r
\r
[Pcd]\r