]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
1. Add Partial Keystroke Support in UsbKb drivers. See the Uefi2.3.1a chapter 11.2
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / EfiKey.c
index fa1c7e076b9886d8c092fa5ec26c46ddc0a5df0a..c576b70f46656c1abe614050172ef080a6cc4640 100644 (file)
@@ -259,9 +259,9 @@ USBKeyboardDriverBindingStart (
   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
@@ -546,7 +546,7 @@ USBKeyboardDriverBindingStop (
 \r
   DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
   DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
-  \r
+\r
   FreePool (UsbKeyboardDevice);\r
 \r
   return Status;\r
@@ -676,14 +676,25 @@ USBKeyboardReadKeyStroke (
 \r
   UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
 \r
-  Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\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
+    // SimpleTextIn Protocol doesn't support partial keystroke;\r
+    //\r
+    if (KeyData.Key.ScanCode == CHAR_NULL && KeyData.Key.UnicodeChar == SCAN_NULL) {\r
+      continue;\r
+    }\r
+    CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+    return EFI_SUCCESS;\r
   }\r
-\r
-  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
 \r
@@ -703,15 +714,42 @@ USBKeyboardWaitForKey (
   )\r
 {\r
   USB_KB_DEV  *UsbKeyboardDevice;\r
+  EFI_KEY_DATA KeyData;\r
+  EFI_TPL      OldTpl;\r
 \r
   UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
 \r
-  if (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+  //\r
+  // Enter critical section\r
+  //  \r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  //\r
+  // WaitforKey doesn't suppor 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
     gBS->SignalEvent (Event);\r
+    break;\r
   }\r
+  //\r
+  // Leave critical section and return\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
 }\r
 \r
 /**\r
@@ -733,7 +771,7 @@ USBKeyboardTimerHandler (
   EFI_KEY_DATA                  KeyData;\r
 \r
   UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
-  \r
+\r
   //\r
   // Fetch raw data from the USB keyboard buffer,\r
   // and translate it into USB keycode.\r
@@ -783,7 +821,7 @@ KbdFreeNotifyList (
     RemoveEntryList (Link);\r
     FreePool (NotifyNode);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -804,29 +842,29 @@ IsKeyRegistered (
   )\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
+    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
+    return FALSE;\r
+  }\r
   if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
       RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
-    return FALSE;    \r
-  }     \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
   Resets the input device hardware.\r
@@ -867,6 +905,9 @@ USBKeyboardResetEx (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  UsbKeyboardDevice->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
+  UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+\r
   return EFI_SUCCESS;\r
 \r
 }\r
@@ -901,7 +942,7 @@ USBKeyboardReadKeyStrokeEx (
   UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
 \r
   return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
-  \r
+\r
 }\r
 \r
 /**\r
@@ -933,7 +974,8 @@ USBKeyboardSetState (
 \r
   UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
 \r
-  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
+  if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
+      ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -944,7 +986,8 @@ USBKeyboardSetState (
   UsbKeyboardDevice->ScrollOn   = FALSE;\r
   UsbKeyboardDevice->NumLockOn  = FALSE;\r
   UsbKeyboardDevice->CapsOn     = FALSE;\r
\r
+  UsbKeyboardDevice->IsSupportPartialKey = FALSE;\r
+\r
   if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
     UsbKeyboardDevice->ScrollOn = TRUE;\r
   }\r
@@ -954,11 +997,16 @@ USBKeyboardSetState (
   if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
     UsbKeyboardDevice->CapsOn = TRUE;\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
 /**\r
@@ -989,7 +1037,7 @@ USBKeyboardRegisterKeyNotify (
   KEYBOARD_CONSOLE_IN_EX_NOTIFY     *NewNotify;\r
   LIST_ENTRY                        *Link;\r
   LIST_ENTRY                        *NotifyList;\r
-  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *CurrentNotify;  \r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *CurrentNotify;\r
 \r
   if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1001,43 +1049,43 @@ 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
     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->NotifyHandle;\r
         return EFI_SUCCESS;\r
       }\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Allocate resource to save the notification function\r
-  //  \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
 \r
-  *NotifyHandle = NewNotify->NotifyHandle;  \r
-  \r
+  *NotifyHandle = NewNotify->NotifyHandle;\r
+\r
   return EFI_SUCCESS;\r
-  \r
+\r
 }\r
 \r
 /**\r
@@ -1064,14 +1112,14 @@ USBKeyboardUnregisterKeyNotify (
 \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
+  }\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
@@ -1080,18 +1128,18 @@ USBKeyboardUnregisterKeyNotify (
        !IsNull (NotifyList, Link);\r
        Link = GetNextNode (NotifyList, Link)) {\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
+                      );\r
     if (CurrentNotify->NotifyHandle == 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
@@ -1099,6 +1147,6 @@ USBKeyboardUnregisterKeyNotify (
   //\r
   // Cannot find the matching entry in database.\r
   //\r
-  return EFI_INVALID_PARAMETER;  \r
+  return EFI_INVALID_PARAMETER;\r
 }\r
 \r