]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
Fix the PS2 keyboard driver to call hotkey callback even no one is calling ReadKeyStroke
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdTextIn.c
index 26f1ea3de42aed608f6d27bbab2ceb9f656bd6c0..eb3c9338ce80740d2c91f5cdd0f9650046e2393e 100644 (file)
@@ -2,7 +2,7 @@
   Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces\r
   provided by Ps2KbdCtrller.c.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2011, 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
@@ -17,29 +17,66 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Ps2Keyboard.h"\r
 \r
 /**\r
-  Check keyboard for given key value.\r
+  Check whether the EFI key buffer is empty.\r
+\r
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.\r
+\r
+  @retval TRUE    The EFI key buffer is empty.\r
+  @retval FALSE   The EFI key buffer isn't empty.\r
+**/\r
+BOOLEAN\r
+IsEfikeyBufEmpty (\r
+  IN  EFI_KEY_QUEUE         *Queue\r
+  )\r
+{\r
+  return (BOOLEAN) (Queue->Head == Queue->Tail);\r
+}\r
+\r
+\r
+\r
+/**\r
+  Push one key data to the EFI key buffer.\r
+\r
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.\r
+  @param KeyData   The key data to push.\r
+**/\r
+VOID\r
+PushEfikeyBufTail (\r
+  IN  EFI_KEY_QUEUE         *Queue,\r
+  IN  EFI_KEY_DATA          *KeyData\r
+  )\r
+{\r
+  if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {\r
+    return;\r
+  }\r
   \r
-  @param  This  Point to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
+  CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));\r
+  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
+}\r
+\r
+/**\r
+  Read & remove one key data from the EFI key buffer.\r
   \r
-  @retval EFI_SUCCESS   success check keyboard value\r
-  @retval !EFI_SUCCESS  Fail to get char from keyboard\r
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.\r
+  @param KeyData   Receive the key data.\r
+\r
+  @retval EFI_SUCCESS   The key data is popped successfully.\r
+  @retval EFI_NOT_READY There is no key data available.\r
 **/\r
 EFI_STATUS\r
-KeyboardCheckForKey (\r
-  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
+PopEfikeyBufHead (\r
+  IN  EFI_KEY_QUEUE         *Queue,\r
+  OUT EFI_KEY_DATA          *KeyData\r
   )\r
 {\r
-  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
-\r
-  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
-\r
+  if (IsEfikeyBufEmpty (Queue)) {\r
+    return EFI_NOT_READY;\r
+  }\r
   //\r
-  // If ready to read next key, check it\r
+  // Retrieve and remove the values\r
   //\r
-  if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {\r
-    return KeyGetchar (ConsoleIn);\r
-  }\r
-\r
+  CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));\r
+  Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -110,9 +147,6 @@ KeyboardReadKeyStrokeWorker (
 {\r
   EFI_STATUS                            Status;\r
   EFI_TPL                               OldTpl;\r
-  LIST_ENTRY                            *Link;\r
-  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;\r
-  EFI_KEY_DATA                          OriginalKeyData;\r
   \r
   if (KeyData == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -123,58 +157,16 @@ KeyboardReadKeyStrokeWorker (
   //\r
   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
-  if (ConsoleInDev->KeyboardErr) {\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-  //\r
-  // If there's no key, just return\r
-  //\r
-  Status = KeyboardCheckForKey (&ConsoleInDev->ConIn);\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_NOT_READY;\r
-  }\r
+  KeyboardTimerHandler (NULL, ConsoleInDev);\r
   \r
-  CopyMem (&KeyData->Key, &ConsoleInDev->Key, sizeof (EFI_INPUT_KEY));\r
-\r
-  ConsoleInDev->Key.ScanCode    = SCAN_NULL;          \r
-  ConsoleInDev->Key.UnicodeChar = 0x0000;     \r
-  CopyMem (&KeyData->KeyState, &ConsoleInDev->KeyState, sizeof (EFI_KEY_STATE));\r
-                                          \r
-  ConsoleInDev->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
-  ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
-  gBS->RestoreTPL (OldTpl);\r
-  //\r
-  //Switch the control value to their original characters. In KeyGetchar() the  CTRL-Alpha characters have been switched to \r
-  // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.\r
-  //\r
-  CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
-  if (ConsoleInDev->Ctrled) {\r
-    if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
-      if (ConsoleInDev->CapsLock) {\r
-        OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'A' - 1);\r
-      } else {\r
-        OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'a' - 1);\r
-      } \r
-    }\r
-  }\r
-  //\r
-  // Invoke notification functions if exist\r
-  //\r
-  for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
-    CurrentNotify = CR (\r
-                      Link, \r
-                      KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
-                      NotifyEntry, \r
-                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
-                      );\r
-    if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
-      CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
-    }\r
+  if (ConsoleInDev->KeyboardErr) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  } else {\r
+    Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -224,11 +216,6 @@ KeyboardEfiReset (
     gBS->RestoreTPL (OldTpl);\r
     return EFI_DEVICE_ERROR;\r
   }\r
-  //\r
-  // Clear the status of ConsoleIn.Key\r
-  //\r
-  ConsoleIn->Key.ScanCode     = SCAN_NULL;\r
-  ConsoleIn->Key.UnicodeChar  = 0x0000;\r
 \r
   //\r
   // Leave critical section and return\r
@@ -304,36 +291,31 @@ KeyboardWaitForKey (
   IN  VOID                    *Context\r
   )\r
 {\r
-  EFI_TPL                 OldTpl;\r
-  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
+  EFI_TPL                     OldTpl;\r
+  KEYBOARD_CONSOLE_IN_DEV     *ConsoleIn;\r
 \r
-  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context);\r
+  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
 \r
   //\r
   // Enter critical section\r
   //\r
   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  KeyboardTimerHandler (NULL, ConsoleIn);\r
 \r
-  if (ConsoleIn->KeyboardErr) {\r
+  if (!ConsoleIn->KeyboardErr) {\r
     //\r
-    // Leave critical section and return\r
+    // Someone is waiting on the keyboard event, if there's\r
+    // a key pending, signal the event\r
     //\r
-    gBS->RestoreTPL (OldTpl);\r
-    return ;\r
-  }\r
-  //\r
-  // Someone is waiting on the keyboard event, if there's\r
-  // a key pending, signal the event\r
-  //\r
-  if (!EFI_ERROR (KeyboardCheckForKey (Context))) {\r
-    gBS->SignalEvent (Event);\r
+    if (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {\r
+      gBS->SignalEvent (Event);\r
+    }\r
   }\r
   //\r
   // Leave critical section and return\r
   //\r
   gBS->RestoreTPL (OldTpl);\r
-\r
-  return ;\r
 }\r
 \r
 /**\r
@@ -352,11 +334,7 @@ KeyboardWaitForKeyEx (
   )\r
 \r
 {\r
-  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;\r
-\r
-  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context); \r
-  KeyboardWaitForKey (Event, &ConsoleInDev->ConIn);\r
-  \r
+  KeyboardWaitForKey (Event, Context);\r
 }\r
 \r
 /**\r
@@ -378,31 +356,14 @@ KeyboardEfiResetEx (
   )\r
 \r
 {\r
-  EFI_STATUS                            Status;\r
   KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;\r
-  EFI_TPL                               OldTpl;\r
 \r
   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); \r
-  if (ConsoleInDev->KeyboardErr) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  Status = ConsoleInDev->ConIn.Reset (\r
-                                 &ConsoleInDev->ConIn, \r
-                                 ExtendedVerification\r
-                                 );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
 \r
-  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
-  ConsoleInDev->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
-  ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
-\r
-  gBS->RestoreTPL (OldTpl);  \r
-  \r
-  return EFI_SUCCESS;\r
+  return ConsoleInDev->ConIn.Reset (\r
+                               &ConsoleInDev->ConIn, \r
+                               ExtendedVerification\r
+                               );\r
 }\r
 \r
 /**\r
@@ -482,8 +443,7 @@ KeyboardSetState (
     goto Exit;\r
   }\r
 \r
-  if (((ConsoleInDev->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
-      ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
+  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
     Status = EFI_UNSUPPORTED;\r
     goto Exit;\r
   }\r
@@ -510,8 +470,6 @@ KeyboardSetState (
     Status = EFI_DEVICE_ERROR;    \r
   }\r
 \r
-  ConsoleInDev->KeyState.KeyToggleState = *KeyToggleState;\r
-  \r
 Exit:   \r
   //\r
   // Leave critical section and return\r