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