summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c')
-rw-r--r--MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c634
1 files changed, 586 insertions, 48 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
index 62fec041c3..eee3827c23 100644
--- a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
+++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
@@ -100,6 +100,18 @@ USBKeyboardCheckForKey (
EFI_GUID gEfiUsbKeyboardDriverGuid = {
0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}
};
+STATIC
+EFI_STATUS
+KbdFreeNotifyList (
+ IN OUT LIST_ENTRY *ListHead
+ );
+STATIC
+BOOLEAN
+IsKeyRegistered (
+ IN EFI_KEY_DATA *RegsiteredData,
+ IN EFI_KEY_DATA *InputData
+ );
+
//
// USB Keyboard Driver Global Variables
@@ -349,6 +361,27 @@ USBKeyboardDriverBindingStart (
UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
+
+ UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;
+ UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;
+ UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;
+ UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;
+ UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;
+
+ InitializeListHead (&UsbKeyboardDevice->NotifyList);
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ USBKeyboardWaitForKey,
+ UsbKeyboardDevice,
+ &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
@@ -380,6 +413,8 @@ USBKeyboardDriverBindingStart (
&Controller,
&gEfiSimpleTextInProtocolGuid,
&UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
&gEfiHotPlugDeviceGuid,
NULL,
NULL
@@ -405,13 +440,15 @@ USBKeyboardDriverBindingStart (
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSimpleTextInProtocolGuid,
- &UsbKeyboardDevice->SimpleInput,
- &gEfiHotPlugDeviceGuid,
- NULL,
- NULL
- );
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
gBS->FreePool (UsbKeyboardDevice);
gBS->CloseProtocol (
@@ -442,13 +479,15 @@ USBKeyboardDriverBindingStart (
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSimpleTextInProtocolGuid,
- &UsbKeyboardDevice->SimpleInput,
- &gEfiHotPlugDeviceGuid,
- NULL,
- NULL
- );
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
gBS->FreePool (UsbKeyboardDevice);
gBS->CloseProtocol (
@@ -478,6 +517,27 @@ USBKeyboardDriverBindingStart (
return EFI_SUCCESS;
+
+ErrorExit:
+ if (UsbKeyboardDevice != NULL) {
+ if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
+ }
+ if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
+ }
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
+ gBS->FreePool (UsbKeyboardDevice);
+ UsbKeyboardDevice = NULL;
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+
}
@@ -518,7 +578,17 @@ USBKeyboardDriverBindingStop (
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
-
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextInputExProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
//
// Get USB_KB_DEV instance.
//
@@ -565,6 +635,8 @@ USBKeyboardDriverBindingStop (
Controller,
&gEfiSimpleTextInProtocolGuid,
&UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
&gEfiHotPlugDeviceGuid,
NULL,
NULL
@@ -575,6 +647,8 @@ USBKeyboardDriverBindingStop (
gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
if (UsbKeyboardDevice->ControllerNameTable != NULL) {
FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
@@ -586,20 +660,107 @@ USBKeyboardDriverBindingStop (
}
+STATIC
+EFI_STATUS
+USBKeyboardReadKeyStrokeWorker (
+ IN USB_KB_DEV *UsbKeyboardDevice,
+ OUT EFI_KEY_DATA *KeyData
+ )
+/*++
+
+ Routine Description:
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+ Arguments:
+ UsbKeyboardDevice - Usb keyboard private structure.
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
-/**
- Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset() function.
+ Returns:
+ EFI_SUCCESS - The keystroke information was returned.
+ EFI_NOT_READY - There was no keystroke data availiable.
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to
+ hardware errors.
+ EFI_INVALID_PARAMETER - KeyData is NULL.
- This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
- ExtendedVerification
- Indicates that the driver may perform a more exhaustive
- verification operation of the device during reset.
+--*/
+{
- @retval EFI_SUCCESS Success
- @retval EFI_DEVICE_ERROR Hardware Error
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+ LIST_ENTRY *Link;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+ EFI_KEY_DATA OriginalKeyData;
-**/
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if there is no saved ASCII byte, fetch it
+ // by calling USBKeyboardCheckForKey().
+ //
+ if (UsbKeyboardDevice->CurKeyChar == 0) {
+ Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ KeyData->Key.UnicodeChar = 0;
+ KeyData->Key.ScanCode = SCAN_NULL;
+
+ KeyChar = UsbKeyboardDevice->CurKeyChar;
+
+ UsbKeyboardDevice->CurKeyChar = 0;
+
+ //
+ // Translate saved ASCII byte into EFI_INPUT_KEY
+ //
+ Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));
+
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
+
+ //
+ //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to
+ // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
+ //
+ CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));
+ if (UsbKeyboardDevice->CtrlOn) {
+ if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {
+ if (UsbKeyboardDevice->CapsOn) {
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);
+ } else {
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);
+ }
+ }
+ }
+
+ //
+ // Invoke notification functions if exist
+ //
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) {
+ CurrentNotify->KeyNotificationFn (&OriginalKeyData);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
EFI_STATUS
EFIAPI
USBKeyboardReset (
@@ -668,36 +829,20 @@ USBKeyboardReadKeyStroke (
OUT EFI_INPUT_KEY *Key
)
{
- USB_KB_DEV *UsbKeyboardDevice;
- EFI_STATUS Status;
- UINT8 KeyChar;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ EFI_KEY_DATA KeyData;
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
- //
- // if there is no saved ASCII byte, fetch it
- // by calling USBKeyboardCheckForKey().
- //
- if (UsbKeyboardDevice->CurKeyChar == 0) {
- Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
- Key->UnicodeChar = 0;
- Key->ScanCode = SCAN_NULL;
-
- KeyChar = UsbKeyboardDevice->CurKeyChar;
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
- UsbKeyboardDevice->CurKeyChar = 0;
-
- //
- // Translate saved ASCII byte into EFI_INPUT_KEY
- //
- Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);
-
- return Status;
+ return EFI_SUCCESS;
}
@@ -792,3 +937,396 @@ KbdReportStatusCode (
DevicePath
);
}
+STATIC
+EFI_STATUS
+KbdFreeNotifyList (
+ IN OUT LIST_ENTRY *ListHead
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ ListHead - The list head
+
+Returns:
+
+ EFI_SUCCESS - Free the notify list successfully
+ EFI_INVALID_PARAMETER - ListHead is invalid.
+
+--*/
+{
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
+
+ if (ListHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ while (!IsListEmpty (ListHead)) {
+ NotifyNode = CR (
+ ListHead->ForwardLink,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ RemoveEntryList (ListHead->ForwardLink);
+ gBS->FreePool (NotifyNode);
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+BOOLEAN
+IsKeyRegistered (
+ IN EFI_KEY_DATA *RegsiteredData,
+ IN EFI_KEY_DATA *InputData
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was registered.
+ InputData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+Returns:
+ TRUE - Key be pressed matches a registered key.
+ FLASE - Match failed.
+
+--*/
+{
+ ASSERT (RegsiteredData != NULL && InputData != NULL);
+
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
+ return FALSE;
+ }
+
+ //
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
+ //
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
+ return FALSE;
+ }
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+//
+// Simple Text Input Ex protocol functions
+//
+EFI_STATUS
+EFIAPI
+USBKeyboardResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset the input device and optionaly run diagnostics
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - Driver may perform diagnostics on reset.
+
+ Returns:
+ EFI_SUCCESS - The device was reset.
+ EFI_DEVICE_ERROR - The device is not functioning properly and could
+ not be reset.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_TPL OldTpl;
+
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ )
+/*++
+
+ Routine Description:
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existance of a keystroke via WaitForEvent () call.
+
+ Arguments:
+ This - Protocol instance pointer.
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
+
+ Returns:
+ EFI_SUCCESS - The keystroke information was returned.
+ EFI_NOT_READY - There was no keystroke data availiable.
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to
+ hardware errors.
+ EFI_INVALID_PARAMETER - KeyData is NULL.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ )
+/*++
+
+ Routine Description:
+ Set certain state for the input device.
+
+ Arguments:
+ This - Protocol instance pointer.
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
+ state for the input device.
+
+ Returns:
+ EFI_SUCCESS - The device state was set successfully.
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could
+ not have the setting adjusted.
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ if (KeyToggleState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
+ ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Update the status light
+ //
+
+ UsbKeyboardDevice->ScrollOn = 0;
+ UsbKeyboardDevice->NumLockOn = 0;
+ UsbKeyboardDevice->CapsOn = 0;
+
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
+ UsbKeyboardDevice->ScrollOn = 1;
+ }
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
+ UsbKeyboardDevice->NumLockOn = 1;
+ }
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
+ UsbKeyboardDevice->CapsOn = 1;
+ }
+
+ SetKeyLED (UsbKeyboardDevice);
+
+ UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+ )
+/*++
+
+ Routine Description:
+ Register a notification function for a particular keystroke for the input device.
+
+ Arguments:
+ This - Protocol instance pointer.
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ information data for the key that was pressed.
+ KeyNotificationFunction - Points to the function to be called when the key
+ sequence is typed specified by KeyData.
+ NotifyHandle - Points to the unique handle assigned to the registered notification.
+
+ Returns:
+ EFI_SUCCESS - The notification function was registered successfully.
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
+ LIST_ENTRY *Link;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ //
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
+ //
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
+ *NotifyHandle = CurrentNotify->NotifyHandle;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Allocate resource to save the notification function
+ //
+ NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
+ if (NewNotify == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
+ InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);
+
+ //
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewNotify->NotifyHandle,
+ &gSimpleTextInExNotifyGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *NotifyHandle = NewNotify->NotifyHandle;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ )
+/*++
+
+ Routine Description:
+ Remove a registered notification function from a particular keystroke.
+
+ Arguments:
+ This - Protocol instance pointer.
+ NotificationHandle - The handle of the notification function being unregistered.
+
+ Returns:
+ EFI_SUCCESS - The notification function was unregistered successfully.
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
+ EFI_NOT_FOUND - Can not find the matching entry in database.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+ LIST_ENTRY *Link;
+
+ if (NotificationHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ Status = gBS->OpenProtocol (
+ NotificationHandle,
+ &gSimpleTextInExNotifyGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {
+ //
+ // Remove the notification function from NotifyList and free resources
+ //
+ RemoveEntryList (&CurrentNotify->NotifyEntry);
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ CurrentNotify->NotifyHandle,
+ &gSimpleTextInExNotifyGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ gBS->FreePool (CurrentNotify);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+