]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c
MdeModulePkg/UsbKb: fix shell edit cannot read '!@#$%^&*' characters
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / KeyBoard.c
index ee774ff35fb699149634490f9ed8b2d21f7c5d12..b3b5fb9ff4c49136dcd679f28357592054ee1c94 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Helper functions for USB Keyboard Driver.\r
 \r
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2018, 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
@@ -808,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
@@ -821,6 +820,7 @@ 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
@@ -874,23 +874,6 @@ 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
@@ -1213,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
@@ -1290,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
@@ -1498,6 +1484,65 @@ USBParseKey (
   return EFI_NOT_READY;\r
 }\r
 \r
+/**\r
+  Initialize the key state.\r
+\r
+  @param  UsbKeyboardDevice     The USB_KB_DEV instance.\r
+  @param  KeyState              A pointer to receive the key state information.\r
+**/\r
+VOID\r
+InitializeKeyState (\r
+  IN  USB_KB_DEV           *UsbKeyboardDevice,\r
+  OUT EFI_KEY_STATE        *KeyState\r
+  )\r
+{\r
+  KeyState->KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
+  KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+\r
+  if (UsbKeyboardDevice->LeftCtrlOn) {\r
+    KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightCtrlOn) {\r
+    KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftAltOn) {\r
+    KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightAltOn) {\r
+    KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftShiftOn) {\r
+    KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightShiftOn) {\r
+    KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftLogoOn) {\r
+    KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightLogoOn) {\r
+    KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->MenuKeyOn) {\r
+    KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->SysReqOn) {\r
+    KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
+  }\r
+\r
+  if (UsbKeyboardDevice->ScrollOn) {\r
+    KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+  }\r
+  if (UsbKeyboardDevice->NumLockOn) {\r
+    KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
+  }\r
+  if (UsbKeyboardDevice->CapsOn) {\r
+    KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+  }\r
+  if (UsbKeyboardDevice->IsSupportPartialKey) {\r
+    KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;\r
+  }\r
+}\r
 \r
 /**\r
   Converts USB Keycode ranging from 0x4 to 0x65 to EFI_INPUT_KEY.\r
@@ -1531,7 +1576,9 @@ UsbKeyCodeToEfiInputKey (
   // KeyCode must in the range of  [0x4, 0x65] or [0xe0, 0xe7].\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
@@ -1568,7 +1615,8 @@ UsbKeyCodeToEfiInputKey (
       // Need not return associated shift state if a class of printable characters that\r
       // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
       //\r
-      if ((KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) != 0) {\r
+      if ((KeyDescriptor->Unicode != CHAR_NULL) && (KeyDescriptor->ShiftedUnicode != CHAR_NULL) &&\r
+          (KeyDescriptor->Unicode != KeyDescriptor->ShiftedUnicode)) {\r
         UsbKeyboardDevice->LeftShiftOn = FALSE;\r
         UsbKeyboardDevice->RightShiftOn = FALSE;\r
       }\r
@@ -1631,67 +1679,28 @@ UsbKeyCodeToEfiInputKey (
   //\r
   // Save Shift/Toggle state\r
   //\r
-  KeyData->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
-  KeyData->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+  InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
 \r
-  if (UsbKeyboardDevice->LeftCtrlOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->RightCtrlOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->LeftAltOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->RightAltOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->LeftShiftOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->RightShiftOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->LeftLogoOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->RightLogoOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->MenuKeyOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
-  }\r
-  if (UsbKeyboardDevice->SysReqOn) {\r
-    KeyData->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
-  }\r
-\r
-  if (UsbKeyboardDevice->ScrollOn) {\r
-    KeyData->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
-  }\r
-  if (UsbKeyboardDevice->NumLockOn) {\r
-    KeyData->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
-  }\r
-  if (UsbKeyboardDevice->CapsOn) {\r
-    KeyData->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\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
+      // 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