]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
MdeModulePkg UsbKbDxe: Execute key notify func at TPL_CALLBACK
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / KeyBoard.c
index fe6121985c4e3a5a9bc9a6c979244228518bb617..91913d4e54e75ac9f76be0585134c4f9e4d62c07 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Helper functions for USB Keyboard Driver.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2016, 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
@@ -79,6 +79,7 @@ USB_KEYBOARD_LAYOUT_PACK_BIN  mUsbKeyboardLayoutBin = {
     {EfiKeyD11,        '[',      '{',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
     {EfiKeyD12,        ']',      '}',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
     {EfiKeyD13,        '\\',     '|',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
+    {EfiKeyC12,        '\\',     '|',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
     {EfiKeyC10,        ';',      ':',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
     {EfiKeyC11,        '\'',     '"',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
     {EfiKeyE0,         '`',      '~',  0, 0,  EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},\r
@@ -296,10 +297,17 @@ UINT8 ModifierValueToEfiScanCodeConvertionTable[] = {
   SCAN_F10,        // EFI_FUNCTION_KEY_TEN_MODIFIER\r
   SCAN_F11,        // EFI_FUNCTION_KEY_ELEVEN_MODIFIER\r
   SCAN_F12,        // EFI_FUNCTION_KEY_TWELVE_MODIFIER\r
+  //\r
+  // For Partial Keystroke support\r
+  //\r
   SCAN_NULL,       // EFI_PRINT_MODIFIER\r
   SCAN_NULL,       // EFI_SYS_REQUEST_MODIFIER\r
   SCAN_NULL,       // EFI_SCROLL_LOCK_MODIFIER\r
-  SCAN_PAUSE       // EFI_PAUSE_MODIFIER\r
+  SCAN_PAUSE,      // EFI_PAUSE_MODIFIER\r
+  SCAN_NULL,       // EFI_BREAK_MODIFIER\r
+  SCAN_NULL,       // EFI_LEFT_LOGO_MODIFIER\r
+  SCAN_NULL,       // EFI_RIGHT_LOGO_MODIFER\r
+  SCAN_NULL,       // EFI_MENU_MODIFER\r
 };\r
 \r
 /**\r
@@ -507,7 +515,7 @@ FindUsbNsKey (
   LIST_ENTRY      *Link;\r
   LIST_ENTRY      *NsKeyList;\r
   USB_NS_KEY      *UsbNsKey;\r
-  \r
+\r
   NsKeyList = &UsbKeyboardDevice->NsKeyList;\r
   Link = GetFirstNode (NsKeyList);\r
   while (!IsNull (NsKeyList, Link)) {\r
@@ -780,7 +788,7 @@ InitKeyboardLayout (
     //\r
     InstallDefaultKeyboardLayout (UsbKeyboardDevice);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -801,8 +809,6 @@ InitUSBKeyboard (
 {\r
   UINT16              ConfigValue;\r
   UINT8               Protocol;\r
-  UINT8               ReportId;\r
-  UINT8               Duration;\r
   EFI_STATUS          Status;\r
   UINT32              TransferResult;\r
 \r
@@ -814,41 +820,41 @@ InitUSBKeyboard (
 \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
   //\r
   // Use the config out of the descriptor\r
   // Assumed the first config is the correct one and this is not always the case\r
   //\r
   Status = UsbGetConfiguration (\r
-             UsbKeyboardDevice->UsbIo, \r
-             &ConfigValue, \r
-             &TransferResult\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    ConfigValue = 0x01;\r
-  }\r
-  \r
-  //\r
-  // Uses default configuration to configure the USB Keyboard device.\r
-  //\r
-  Status = UsbSetConfiguration (\r
              UsbKeyboardDevice->UsbIo,\r
-             ConfigValue,\r
+             &ConfigValue,\r
              &TransferResult\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    ConfigValue = 0x01;\r
     //\r
-    // If configuration could not be set here, it means\r
-    // the keyboard interface has some errors and could\r
-    // not be initialized\r
+    // Uses default configuration to configure the USB Keyboard device.\r
     //\r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),\r
-      UsbKeyboardDevice->DevicePath\r
-      );\r
+    Status = UsbSetConfiguration (\r
+               UsbKeyboardDevice->UsbIo,\r
+               ConfigValue,\r
+               &TransferResult\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // If configuration could not be set here, it means\r
+      // the keyboard interface has some errors and could\r
+      // not be initialized\r
+      //\r
+      REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR),\r
+        UsbKeyboardDevice->DevicePath\r
+        );\r
 \r
-    return EFI_DEVICE_ERROR;\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
   }\r
 \r
   UsbGetProtocolRequest (\r
@@ -868,30 +874,13 @@ InitUSBKeyboard (
       );\r
   }\r
 \r
-  //\r
-  // ReportId is zero, which means the idle rate applies to all input reports.\r
-  //\r
-  ReportId = 0;\r
-  //\r
-  // Duration is zero, which means the duration is infinite.\r
-  // so the endpoint will inhibit reporting forever,\r
-  // and only reporting when a change is detected in the report data.\r
-  //\r
-  Duration = 0;\r
-  UsbSetIdleRequest (\r
-    UsbKeyboardDevice->UsbIo,\r
-    UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,\r
-    ReportId,\r
-    Duration\r
-    );\r
-\r
   UsbKeyboardDevice->CtrlOn     = FALSE;\r
   UsbKeyboardDevice->AltOn      = FALSE;\r
   UsbKeyboardDevice->ShiftOn    = FALSE;\r
   UsbKeyboardDevice->NumLockOn  = FALSE;\r
   UsbKeyboardDevice->CapsOn     = FALSE;\r
   UsbKeyboardDevice->ScrollOn   = FALSE;\r
-  \r
+\r
   UsbKeyboardDevice->LeftCtrlOn   = FALSE;\r
   UsbKeyboardDevice->LeftAltOn    = FALSE;\r
   UsbKeyboardDevice->LeftShiftOn  = FALSE;\r
@@ -1033,7 +1022,7 @@ KeyboardHandler (
 \r
     //\r
     // Delete & Submit this interrupt again\r
-    // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt. \r
+    // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.\r
     //\r
     UsbIo->UsbAsyncInterruptTransfer (\r
              UsbIo,\r
@@ -1207,7 +1196,9 @@ KeyboardHandler (
       // Handle repeat key\r
       //\r
       KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);\r
-      ASSERT (KeyDescriptor != NULL);\r
+      if (KeyDescriptor == NULL) {\r
+        continue;\r
+      }\r
 \r
       if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {\r
         //\r
@@ -1284,8 +1275,9 @@ USBParseKey (
     Dequeue (&UsbKeyboardDevice->UsbKeyQueue, &UsbKey, sizeof (UsbKey));\r
 \r
     KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
-    ASSERT (KeyDescriptor != NULL);\r
-\r
+    if (KeyDescriptor == NULL) {\r
+      continue;\r
+    }\r
     if (!UsbKey.Down) {\r
       //\r
       // Key is released.\r
@@ -1382,12 +1374,10 @@ USBParseKey (
     case EFI_LEFT_CONTROL_MODIFIER:\r
       UsbKeyboardDevice->LeftCtrlOn = TRUE;\r
       UsbKeyboardDevice->CtrlOn = TRUE;\r
-      continue;\r
       break;\r
     case EFI_RIGHT_CONTROL_MODIFIER:\r
       UsbKeyboardDevice->RightCtrlOn = TRUE;\r
       UsbKeyboardDevice->CtrlOn = TRUE;\r
-      continue;\r
       break;\r
 \r
     //\r
@@ -1396,12 +1386,10 @@ USBParseKey (
     case EFI_LEFT_SHIFT_MODIFIER:\r
       UsbKeyboardDevice->LeftShiftOn = TRUE;\r
       UsbKeyboardDevice->ShiftOn = TRUE;\r
-      continue;\r
       break;\r
     case EFI_RIGHT_SHIFT_MODIFIER:\r
       UsbKeyboardDevice->RightShiftOn = TRUE;\r
       UsbKeyboardDevice->ShiftOn = TRUE;\r
-      continue;\r
       break;\r
 \r
     //\r
@@ -1410,12 +1398,10 @@ USBParseKey (
     case EFI_LEFT_ALT_MODIFIER:\r
       UsbKeyboardDevice->LeftAltOn = TRUE;\r
       UsbKeyboardDevice->AltOn = TRUE;\r
-      continue;\r
       break;\r
     case EFI_RIGHT_ALT_MODIFIER:\r
       UsbKeyboardDevice->RightAltOn = TRUE;\r
       UsbKeyboardDevice->AltOn = TRUE;\r
-      continue;\r
       break;\r
 \r
     //\r
@@ -1445,7 +1431,6 @@ USBParseKey (
     case EFI_PRINT_MODIFIER:\r
     case EFI_SYS_REQUEST_MODIFIER:\r
       UsbKeyboardDevice->SysReqOn = TRUE;\r
-      continue;\r
       break;\r
 \r
     //\r
@@ -1461,7 +1446,6 @@ USBParseKey (
       //\r
       UsbKeyboardDevice->NumLockOn = (BOOLEAN) (!(UsbKeyboardDevice->NumLockOn));\r
       SetKeyLED (UsbKeyboardDevice);\r
-      continue;\r
       break;\r
 \r
     case EFI_CAPS_LOCK_MODIFIER:\r
@@ -1470,7 +1454,6 @@ USBParseKey (
       //\r
       UsbKeyboardDevice->CapsOn = (BOOLEAN) (!(UsbKeyboardDevice->CapsOn));\r
       SetKeyLED (UsbKeyboardDevice);\r
-      continue;\r
       break;\r
 \r
     case EFI_SCROLL_LOCK_MODIFIER:\r
@@ -1479,7 +1462,6 @@ USBParseKey (
       //\r
       UsbKeyboardDevice->ScrollOn = (BOOLEAN) (!(UsbKeyboardDevice->ScrollOn));\r
       SetKeyLED (UsbKeyboardDevice);\r
-      continue;\r
       break;\r
 \r
     default:\r
@@ -1529,20 +1511,15 @@ UsbKeyCodeToEfiInputKey (
   EFI_KEY_DESCRIPTOR            *KeyDescriptor;\r
   LIST_ENTRY                    *Link;\r
   LIST_ENTRY                    *NotifyList;\r
-  KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;  \r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
 \r
   //\r
-  // KeyCode must in the range of 0x4 to 0x65\r
+  // KeyCode must in the range of  [0x4, 0x65] or [0xe0, 0xe7].\r
   //\r
-  if (!USBKBD_VALID_KEYCODE (KeyCode)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if ((KeyCode - 4) >= NUMBER_OF_VALID_NON_MODIFIER_USB_KEYCODE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyCode);\r
-  ASSERT (KeyDescriptor != NULL);\r
+  if (KeyDescriptor == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 \r
   if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {\r
     //\r
@@ -1618,7 +1595,7 @@ UsbKeyCodeToEfiInputKey (
     if ((UsbKeyboardDevice->NumLockOn) && (!(UsbKeyboardDevice->ShiftOn))) {\r
       KeyData->Key.ScanCode = SCAN_NULL;\r
     } else {\r
-      KeyData->Key.UnicodeChar = 0x00;\r
+      KeyData->Key.UnicodeChar = CHAR_NULL;\r
     }\r
   }\r
 \r
@@ -1627,14 +1604,16 @@ UsbKeyCodeToEfiInputKey (
   //\r
   if (KeyData->Key.UnicodeChar == 0x1B && KeyData->Key.ScanCode == SCAN_NULL) {\r
     KeyData->Key.ScanCode = SCAN_ESC;\r
-    KeyData->Key.UnicodeChar = 0x00;\r
+    KeyData->Key.UnicodeChar = CHAR_NULL;\r
   }\r
 \r
   //\r
   // Not valid for key without both unicode key code and EFI Scan Code.\r
   //\r
   if (KeyData->Key.UnicodeChar == 0 && KeyData->Key.ScanCode == SCAN_NULL) {\r
+    if (!UsbKeyboardDevice->IsSupportPartialKey) {\r
     return EFI_NOT_READY;\r
+    }\r
   }\r
 \r
   //\r
@@ -1683,34 +1662,29 @@ UsbKeyCodeToEfiInputKey (
   if (UsbKeyboardDevice->CapsOn) {\r
     KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
   }\r
-\r
+  if (UsbKeyboardDevice->IsSupportPartialKey) {\r
+    KeyData->KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED;\r
+  }\r
   //\r
-  // Invoke notification functions if the key is registered.\r
+  // Signal KeyNotify process event if this key pressed matches any key registered.\r
   //\r
   NotifyList = &UsbKeyboardDevice->NotifyList;\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
-  // Translate the CTRL-Alpha characters to their corresponding control value\r
-  // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
-  //\r
-  if (UsbKeyboardDevice->CtrlOn) {\r
-    if (KeyData->Key.UnicodeChar >= 'a' && KeyData->Key.UnicodeChar <= 'z') {\r
-      KeyData->Key.UnicodeChar = (UINT8) (KeyData->Key.UnicodeChar - 'a' + 1);\r
-    } else if (KeyData->Key.UnicodeChar >= 'A' && KeyData->Key.UnicodeChar <= 'Z') {\r
-      KeyData->Key.UnicodeChar = (UINT8) (KeyData->Key.UnicodeChar - 'A' + 1);\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
+      //\r
+      // The key notification function needs to run at TPL_CALLBACK\r
+      // while current TPL is TPL_NOTIFY. It will be invoked in\r
+      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
+      //\r
+      Enqueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, KeyData, sizeof (*KeyData));\r
+      gBS->SignalEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
     }\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Create the queue.\r
 \r