USB Keyboard Driver that manages USB keyboard and produces Simple Text Input\r
Protocol and Simple Text Input Ex Protocol.\r
\r
-Copyright (c) 2004 - 2010, Intel Corporation\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
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
//\r
// USB Keyboard Driver Global Variables\r
//\r
-EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {\r
USBKeyboardDriverBindingSupported,\r
USBKeyboardDriverBindingStart,\r
USBKeyboardDriverBindingStop,\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardDriverBindingEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
+ EFI_STATUS Status;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
\r
//\r
// Check if USB I/O Protocol is attached on the controller handle.\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo,\r
+ (VOID **)&UsbIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- UINT8 EndpointNumber;\r
- EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;\r
- UINT8 Index;\r
- UINT8 EndpointAddr;\r
- UINT8 PollingInterval;\r
- UINT8 PacketSize;\r
- BOOLEAN Found;\r
-\r
+ EFI_STATUS Status;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ UINT8 EndpointNumber;\r
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;\r
+ UINT8 Index;\r
+ UINT8 EndpointAddr;\r
+ UINT8 PollingInterval;\r
+ UINT8 PacketSize;\r
+ BOOLEAN Found;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
//\r
// Open USB I/O Protocol\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo,\r
+ (VOID **)&UsbIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto ErrorExit1;\r
}\r
\r
UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
- (VOID **) &UsbKeyboardDevice->DevicePath,\r
+ (VOID **)&UsbKeyboardDevice->DevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
if (EFI_ERROR (Status)) {\r
goto ErrorExit;\r
}\r
+\r
//\r
// Report that the USB keyboard is being enabled\r
//\r
EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;\r
\r
//\r
- // Traverse endpoints to find interrupt endpoint\r
+ // Traverse endpoints to find interrupt endpoint IN\r
//\r
Found = FALSE;\r
for (Index = 0; Index < EndpointNumber; Index++) {\r
-\r
UsbIo->UsbGetEndpointDescriptor (\r
UsbIo,\r
Index,\r
&EndpointDescriptor\r
);\r
\r
- if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {\r
+ if (((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) &&\r
+ ((EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) != 0))\r
+ {\r
//\r
// We only care interrupt endpoint here\r
//\r
- CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
+ CopyMem (&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));\r
Found = TRUE;\r
break;\r
}\r
\r
if (!Found) {\r
//\r
+ // Report Status Code to indicate that there is no USB keyboard\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED)\r
+ );\r
+ //\r
// No interrupt endpoint found, then return unsupported.\r
//\r
Status = EFI_UNSUPPORTED;\r
goto ErrorExit;\r
}\r
\r
- UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
- UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
- UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED),\r
+ UsbKeyboardDevice->DevicePath\r
+ );\r
+\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
+\r
InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
- \r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ USBKeyboardTimerHandler,\r
+ UsbKeyboardDevice,\r
+ &UsbKeyboardDevice->TimerEvent\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
goto ErrorExit;\r
}\r
\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ UsbKeyboardDevice,\r
+ &UsbKeyboardDevice->KeyNotifyProcessEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
//\r
// Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
// for the USB keyboard device.\r
}\r
\r
UsbKeyboardDevice->ControllerHandle = Controller;\r
- Status = InitKeyboardLayout (UsbKeyboardDevice);\r
+ Status = InitKeyboardLayout (UsbKeyboardDevice);\r
if (EFI_ERROR (Status)) {\r
gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiSimpleTextInProtocolGuid,\r
- &UsbKeyboardDevice->SimpleInput,\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- &UsbKeyboardDevice->SimpleInputEx,\r
- NULL\r
- );\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
+ NULL\r
+ );\r
goto ErrorExit;\r
}\r
\r
-\r
//\r
// Reset USB Keyboard Device exhaustively.\r
//\r
- Status = UsbKeyboardDevice->SimpleInput.Reset (\r
- &UsbKeyboardDevice->SimpleInput,\r
- TRUE\r
- );\r
+ Status = UsbKeyboardDevice->SimpleInputEx.Reset (\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
+ TRUE\r
+ );\r
if (EFI_ERROR (Status)) {\r
gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
//\r
EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
- PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
+ PacketSize = (UINT8)(UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
\r
Status = UsbIo->UsbAsyncInterruptTransfer (\r
UsbIo,\r
FALSE\r
);\r
\r
+ gBS->RestoreTPL (OldTpl);\r
return EFI_SUCCESS;\r
\r
-//\r
-// Error handler\r
-//\r
+ //\r
+ // Error handler\r
+ //\r
ErrorExit:\r
if (UsbKeyboardDevice != NULL) {\r
+ if (UsbKeyboardDevice->TimerEvent != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
+ }\r
+\r
if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
}\r
+\r
if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
}\r
+\r
+ if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
+ }\r
+\r
if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {\r
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
}\r
+\r
FreePool (UsbKeyboardDevice);\r
UsbKeyboardDevice = NULL;\r
}\r
+\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiUsbIoProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
- return Status;\r
\r
-}\r
+ErrorExit1:\r
+ gBS->RestoreTPL (OldTpl);\r
\r
+ return Status;\r
+}\r
\r
/**\r
Stop the USB keyboard device handled by this driver.\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
- (VOID **) &SimpleInput,\r
+ (VOID **)&SimpleInput,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
//\r
// Free all resources.\r
//\r
+ gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\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
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);\r
\r
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
}\r
\r
+ DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
+ DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
+ DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify);\r
+\r
FreePool (UsbKeyboardDevice);\r
\r
return Status;\r
data for the key that was pressed.\r
\r
@retval EFI_SUCCESS The keystroke information was returned.\r
- @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_NOT_READY There was no keystroke data available.\r
@retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
hardware errors.\r
@retval EFI_INVALID_PARAMETER KeyData is NULL.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
USBKeyboardReadKeyStrokeWorker (\r
- IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
- OUT EFI_KEY_DATA *KeyData\r
+ IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
+ OUT EFI_KEY_DATA *KeyData\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 KeyCode; \r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NotifyList;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
- EFI_KEY_DATA OriginalKeyData;\r
-\r
if (KeyData == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- //\r
- // If there is no saved USB keycode, fetch it\r
- // by calling USBKeyboardCheckForKey().\r
- //\r
- if (UsbKeyboardDevice->CurKeyCode == 0) {\r
- Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_READY;\r
- }\r
- }\r
-\r
- KeyData->Key.UnicodeChar = 0;\r
- KeyData->Key.ScanCode = SCAN_NULL;\r
-\r
- //\r
- // Store the current keycode and clear it.\r
- //\r
- KeyCode = UsbKeyboardDevice->CurKeyCode;\r
- UsbKeyboardDevice->CurKeyCode = 0;\r
-\r
- //\r
- // Translate saved USB keycode into EFI_INPUT_KEY\r
- //\r
- Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData->Key);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+ InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
+ return EFI_NOT_READY;\r
}\r
\r
- //\r
- // Get current state of various toggled attributes as well as input modifier values,\r
- // and set them as valid.\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.\r
- // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to \r
- // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),\r
- // 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 the key is registered.\r
- //\r
- NotifyList = &UsbKeyboardDevice->NotifyList;\r
- for (Link = GetFirstNode (NotifyList);\r
- !IsNull (NotifyList, Link);\r
- Link = GetNextNode (NotifyList, Link)) {\r
- CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
- CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
- }\r
- }\r
+ Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData));\r
\r
return EFI_SUCCESS;\r
}\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReset (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
)\r
{\r
- EFI_STATUS Status;\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
\r
//\r
// Clear the key buffer of this USB keyboard\r
//\r
- InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
- UsbKeyboardDevice->CurKeyCode = 0;\r
+ InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
+ InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
+ InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));\r
\r
return EFI_SUCCESS;\r
}\r
// Exhaustive reset\r
//\r
Status = InitUSBKeyboard (UsbKeyboardDevice);\r
- UsbKeyboardDevice->CurKeyCode = 0;\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Reads the next keystroke from the input device.\r
\r
information for the key that was pressed.\r
\r
@retval EFI_SUCCESS The keystroke information was returned.\r
- @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_NOT_READY There was no keystroke data available.\r
@retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
hardware errors.\r
\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReadKeyStroke (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- OUT EFI_INPUT_KEY *Key\r
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
+ OUT EFI_INPUT_KEY *Key\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_STATUS Status;\r
- EFI_KEY_DATA KeyData;\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
- Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ //\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
+ //\r
+ while (1) {\r
+ Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ //\r
+ // SimpleTextIn Protocol doesn't support partial keystroke;\r
+ //\r
+ if ((KeyData.Key.ScanCode == CHAR_NULL) && (KeyData.Key.UnicodeChar == SCAN_NULL)) {\r
+ continue;\r
+ }\r
\r
- return EFI_SUCCESS;\r
-}\r
+ //\r
+ // Translate the CTRL-Alpha characters to their corresponding control value\r
+ // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) {\r
+ KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'a' + 1);\r
+ } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) {\r
+ KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'A' + 1);\r
+ }\r
+ }\r
\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
\r
/**\r
Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
VOID\r
EFIAPI\r
USBKeyboardWaitForKey (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_TPL OldTpl;\r
\r
- UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
+ UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
\r
- if (UsbKeyboardDevice->CurKeyCode == 0) {\r
- if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {\r
- //\r
- // If no pending key, simply return.\r
- //\r
- return ;\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // WaitforKey doesn't support the partial key.\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
+ //\r
+ while (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+ //\r
+ // If there is pending key, signal the event.\r
+ //\r
+ CopyMem (\r
+ &KeyData,\r
+ UsbKeyboardDevice->EfiKeyQueue.Buffer[UsbKeyboardDevice->EfiKeyQueue.Head],\r
+ sizeof (EFI_KEY_DATA)\r
+ );\r
+ if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {\r
+ Dequeue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (EFI_KEY_DATA));\r
+ continue;\r
}\r
+\r
+ gBS->SignalEvent (Event);\r
+ break;\r
}\r
+\r
//\r
- // If there is pending key, signal the event.\r
+ // Leave critical section and return\r
//\r
- gBS->SignalEvent (Event);\r
+ gBS->RestoreTPL (OldTpl);\r
}\r
\r
-\r
/**\r
- Check whether there is key pending in the keyboard buffer.\r
-\r
- @param UsbKeyboardDevice The USB_KB_DEV instance.\r
-\r
- @retval EFI_SUCCESS There is pending key to read.\r
- @retval EFI_NOT_READY No pending key to read.\r
+ Timer handler to convert the key from USB.\r
\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
**/\r
-EFI_STATUS\r
+VOID\r
EFIAPI\r
-USBKeyboardCheckForKey (\r
- IN OUT USB_KB_DEV *UsbKeyboardDevice\r
+USBKeyboardTimerHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 KeyCode;\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ UINT8 KeyCode;\r
+ EFI_KEY_DATA KeyData;\r
+\r
+ UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
\r
//\r
// Fetch raw data from the USB keyboard buffer,\r
//\r
Status = USBParseKey (UsbKeyboardDevice, &KeyCode);\r
if (EFI_ERROR (Status)) {\r
- return EFI_NOT_READY;\r
+ return;\r
}\r
\r
- UsbKeyboardDevice->CurKeyCode = KeyCode;\r
- return EFI_SUCCESS;\r
+ //\r
+ // Translate saved USB keycode into EFI_INPUT_KEY\r
+ //\r
+ Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Insert to the EFI Key queue\r
+ //\r
+ Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData));\r
}\r
\r
/**\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
KbdFreeNotifyList (\r
- IN OUT LIST_ENTRY *NotifyList\r
+ IN OUT LIST_ENTRY *NotifyList\r
)\r
{\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
- LIST_ENTRY *Link;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+ LIST_ENTRY *Link;\r
\r
if (NotifyList == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
while (!IsListEmpty (NotifyList)) {\r
- Link = GetFirstNode (NotifyList);\r
+ Link = GetFirstNode (NotifyList);\r
NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
RemoveEntryList (Link);\r
FreePool (NotifyNode);\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
@param InputData A pointer to keystroke data for the key that was pressed.\r
\r
@retval TRUE Key pressed matches a registered key.\r
- @retval FLASE Key pressed does not matches a registered key.\r
+ @retval FALSE Key pressed does not matches a registered key.\r
\r
**/\r
BOOLEAN\r
-EFIAPI\r
IsKeyRegistered (\r
IN EFI_KEY_DATA *RegsiteredData,\r
IN EFI_KEY_DATA *InputData\r
)\r
{\r
ASSERT (RegsiteredData != NULL && InputData != NULL);\r
- \r
+\r
if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
- (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
- return FALSE; \r
- } \r
- \r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar))\r
+ {\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
+ if ((RegsiteredData->KeyState.KeyShiftState != 0) &&\r
+ (RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState))\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((RegsiteredData->KeyState.KeyToggleState != 0) &&\r
+ (RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState))\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
return TRUE;\r
}\r
\r
//\r
-// Simple Text Input Ex protocol functions \r
+// Simple Text Input Ex protocol functions\r
//\r
+\r
/**\r
Resets the input device hardware.\r
\r
IN BOOLEAN ExtendedVerification\r
)\r
{\r
- EFI_STATUS Status;\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_TPL OldTpl;\r
- \r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
\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
/**\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReadKeyStrokeEx (\r
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- OUT EFI_KEY_DATA *KeyData\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
if (KeyData == NULL) {\r
return EFI_INVALID_PARAMETER;\r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
\r
return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
- \r
}\r
\r
/**\r
IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
if (KeyToggleState == NULL) {\r
return EFI_INVALID_PARAMETER;\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
+ ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID))\r
+ {\r
return EFI_UNSUPPORTED;\r
}\r
\r
// Update the status light\r
//\r
\r
- UsbKeyboardDevice->ScrollOn = FALSE;\r
- UsbKeyboardDevice->NumLockOn = FALSE;\r
- UsbKeyboardDevice->CapsOn = FALSE;\r
- \r
+ UsbKeyboardDevice->ScrollOn = FALSE;\r
+ UsbKeyboardDevice->NumLockOn = FALSE;\r
+ UsbKeyboardDevice->CapsOn = FALSE;\r
+ UsbKeyboardDevice->IsSupportPartialKey = FALSE;\r
+\r
if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
UsbKeyboardDevice->ScrollOn = TRUE;\r
}\r
+\r
if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
UsbKeyboardDevice->NumLockOn = TRUE;\r
}\r
+\r
if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
UsbKeyboardDevice->CapsOn = TRUE;\r
}\r
\r
+ if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
+ UsbKeyboardDevice->IsSupportPartialKey = TRUE;\r
+ }\r
+\r
SetKeyLED (UsbKeyboardDevice);\r
\r
UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
\r
return EFI_SUCCESS;\r
- \r
}\r
\r
/**\r
Register a notification function for a particular keystroke for the input device.\r
\r
@param This Protocol instance pointer.\r
- @param KeyData A pointer to a buffer that is filled in with the keystroke\r
- information data for the key that was pressed.\r
+ @param KeyData A pointer to a buffer that is filled in with\r
+ the keystroke information for the key that was\r
+ pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
+ and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
+ keystroke will trigger a notification of the KeyNotificationFunction.\r
@param KeyNotificationFunction Points to the function to be called when the key\r
- sequence is typed specified by KeyData.\r
+ sequence is typed specified by KeyData. This notification function\r
+ should be called at <=TPL_CALLBACK.\r
@param NotifyHandle Points to the unique handle assigned to the registered notification.\r
\r
@retval EFI_SUCCESS The notification function was registered successfully.\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
+ OUT VOID **NotifyHandle\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NotifyList;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
\r
- if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ if ((KeyData == NULL) || (NotifyHandle == NULL) || (KeyNotificationFunction == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
//\r
NotifyList = &UsbKeyboardDevice->NotifyList;\r
- \r
+\r
for (Link = GetFirstNode (NotifyList);\r
!IsNull (NotifyList, Link);\r
- Link = GetNextNode (NotifyList, Link)) {\r
+ Link = GetNextNode (NotifyList, Link))\r
+ {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \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 (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
- *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ *NotifyHandle = CurrentNotify;\r
return EFI_SUCCESS;\r
}\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
+ //\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->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
- NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
\r
+ *NotifyHandle = NewNotify;\r
\r
- *NotifyHandle = NewNotify->NotifyHandle; \r
- \r
return EFI_SUCCESS;\r
- \r
}\r
\r
/**\r
EFIAPI\r
USBKeyboardUnregisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- IN EFI_HANDLE NotificationHandle\r
+ IN VOID *NotificationHandle\r
)\r
{\r
- USB_KB_DEV *UsbKeyboardDevice;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NotifyList;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
\r
if (NotificationHandle == NULL) {\r
return EFI_INVALID_PARAMETER;\r
- } \r
+ }\r
\r
- if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
- return EFI_INVALID_PARAMETER;\r
- } \r
- \r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
- \r
+\r
//\r
// Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
//\r
NotifyList = &UsbKeyboardDevice->NotifyList;\r
for (Link = GetFirstNode (NotifyList);\r
!IsNull (NotifyList, Link);\r
- Link = GetNextNode (NotifyList, Link)) {\r
+ Link = GetNextNode (NotifyList, Link))\r
+ {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \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
+ if (CurrentNotify == NotificationHandle) {\r
//\r
// Remove the notification function from NotifyList and free resources\r
//\r
- RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ RemoveEntryList (&CurrentNotify->NotifyEntry);\r
\r
- FreePool (CurrentNotify); \r
+ FreePool (CurrentNotify);\r
return EFI_SUCCESS;\r
}\r
}\r
//\r
// Cannot find the matching entry in database.\r
//\r
- return EFI_INVALID_PARAMETER; \r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
+/**\r
+ Process key notify.\r
+\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ UsbKeyboardDevice = (USB_KB_DEV *)Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &UsbKeyboardDevice->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (KeyData));\r
+ //\r
+ // Leave critical section\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+ CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r