]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / EfiKey.c
index 278c2da19a474d1b3c8dd39b3d9c51c9afa5347d..e889f422bbf748fbf2db945a0e4a5f434b78aca8 100644 (file)
@@ -2,14 +2,8 @@
   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. All rights reserved.<BR>\r
-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
@@ -19,7 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\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
@@ -43,11 +37,11 @@ EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
 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
@@ -76,13 +70,13 @@ USBKeyboardDriverBindingEntryPoint (
 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
@@ -90,7 +84,7 @@ USBKeyboardDriverBindingSupported (
   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
@@ -139,22 +133,22 @@ USBKeyboardDriverBindingSupported (
 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
-  EFI_TPL                       OldTpl;\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
@@ -163,7 +157,7 @@ USBKeyboardDriverBindingStart (
   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
@@ -181,7 +175,7 @@ USBKeyboardDriverBindingStart (
   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
@@ -190,6 +184,7 @@ USBKeyboardDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     goto ErrorExit;\r
   }\r
+\r
   //\r
   // Report that the USB keyboard is being enabled\r
   //\r
@@ -221,22 +216,23 @@ USBKeyboardDriverBindingStart (
   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
@@ -244,24 +240,52 @@ USBKeyboardDriverBindingStart (
 \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
@@ -285,6 +309,17 @@ USBKeyboardDriverBindingStart (
     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
@@ -305,27 +340,26 @@ USBKeyboardDriverBindingStart (
   }\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->SimpleInputEx.Reset (\r
-                                            &UsbKeyboardDevice->SimpleInputEx,\r
-                                            TRUE\r
-                                            );\r
+                                              &UsbKeyboardDevice->SimpleInputEx,\r
+                                              TRUE\r
+                                              );\r
   if (EFI_ERROR (Status)) {\r
     gBS->UninstallMultipleProtocolInterfaces (\r
            Controller,\r
@@ -343,7 +377,7 @@ USBKeyboardDriverBindingStart (
   //\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
@@ -386,24 +420,36 @@ USBKeyboardDriverBindingStart (
   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
@@ -415,10 +461,8 @@ ErrorExit1:
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
-\r
 }\r
 \r
-\r
 /**\r
   Stop the USB keyboard device handled by this driver.\r
 \r
@@ -437,20 +481,20 @@ ErrorExit1:
 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
@@ -513,11 +557,13 @@ USBKeyboardDriverBindingStop (
   //\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
@@ -526,6 +572,10 @@ USBKeyboardDriverBindingStop (
     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
@@ -539,7 +589,7 @@ USBKeyboardDriverBindingStop (
                                   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
@@ -547,89 +597,22 @@ USBKeyboardDriverBindingStop (
 \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
+  if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+    ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+    InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
+    return EFI_NOT_READY;\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
-  }\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
@@ -652,12 +635,12 @@ USBKeyboardReadKeyStrokeWorker (
 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
@@ -680,8 +663,9 @@ USBKeyboardReset (
     //\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
@@ -690,7 +674,6 @@ USBKeyboardReset (
   // Exhaustive reset\r
   //\r
   Status = InitUSBKeyboard (UsbKeyboardDevice);\r
-  UsbKeyboardDevice->CurKeyCode = 0;\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
@@ -698,7 +681,6 @@ USBKeyboardReset (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Reads the next keystroke from the input device.\r
 \r
@@ -707,7 +689,7 @@ USBKeyboardReset (
                                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
@@ -715,26 +697,50 @@ USBKeyboardReset (
 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
@@ -747,46 +753,70 @@ USBKeyboardReadKeyStroke (
 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
@@ -794,11 +824,21 @@ USBKeyboardCheckForKey (
   //\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
@@ -811,24 +851,24 @@ USBKeyboardCheckForKey (
 \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
@@ -839,41 +879,45 @@ KbdFreeNotifyList (
   @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
@@ -903,10 +947,8 @@ USBKeyboardResetEx (
   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
@@ -915,13 +957,10 @@ USBKeyboardResetEx (
     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
@@ -941,11 +980,11 @@ USBKeyboardResetEx (
 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
@@ -954,7 +993,6 @@ USBKeyboardReadKeyStrokeEx (
   UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
 \r
   return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
-  \r
 }\r
 \r
 /**\r
@@ -978,7 +1016,7 @@ USBKeyboardSetState (
   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
@@ -987,7 +1025,8 @@ USBKeyboardSetState (
   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
@@ -995,36 +1034,46 @@ USBKeyboardSetState (
   // 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
@@ -1038,16 +1087,16 @@ USBKeyboardRegisterKeyNotify (
   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
@@ -1057,43 +1106,41 @@ USBKeyboardRegisterKeyNotify (
   // 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
@@ -1110,44 +1157,41 @@ EFI_STATUS
 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
@@ -1155,6 +1199,55 @@ USBKeyboardUnregisterKeyNotify (
   //\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