Update to support EFI_SIMPLE_INPUT_EX protocol
authorqhuang8 <qhuang8@de2fecce-e211-0410-80a6-f3fac2684e05>
Fri, 19 Oct 2007 02:35:29 +0000 (02:35 +0000)
committerqhuang8 <qhuang8@de2fecce-e211-0410-80a6-f3fac2684e05>
Fri, 19 Oct 2007 02:35:29 +0000 (02:35 +0000)
git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@4178 de2fecce-e211-0410-80a6-f3fac2684e05

edk2/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
edk2/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
edk2/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h
edk2/MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
edk2/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
edk2/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
edk2/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
edk2/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
edk2/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
edk2/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
edk2/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf

index 3401708..a075c0e 100644 (file)
   DebugLib\r
   PcdLib\r
   UsbLib\r
-\r
+  BaseLib\r
 \r
 [Guids]\r
   gEfiHotPlugDeviceGuid                         # ALWAYS_CONSUMED\r
-\r
+  gSimpleTextInExNotifyGuid                     # ALWAYS_CONSUMED\r
 \r
 [Protocols]\r
   gEfiUsbIoProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
   gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
   gEfiSimpleTextInProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextInputExProtocolGuid             # PROTOCOL ALWAYS_CONSUMED\r
 \r
 [FixedPcd]\r
   gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardEnable\r
index 62fec04..eee3827 100644 (file)
@@ -100,6 +100,18 @@ USBKeyboardCheckForKey (
 EFI_GUID  gEfiUsbKeyboardDriverGuid = {\r
   0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}\r
 };\r
+STATIC\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  );  \r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  );\r
+\r
 \r
 //\r
 // USB Keyboard Driver Global Variables\r
@@ -349,6 +361,27 @@ USBKeyboardDriverBindingStart (
   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
+  InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
+  \r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  USBKeyboardWaitForKey,\r
+                  UsbKeyboardDevice,\r
+                  &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_WAIT,\r
                   TPL_NOTIFY,\r
@@ -380,6 +413,8 @@ USBKeyboardDriverBindingStart (
                   &Controller,\r
                   &gEfiSimpleTextInProtocolGuid,\r
                   &UsbKeyboardDevice->SimpleInput,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &UsbKeyboardDevice->SimpleInputEx,\r
                   &gEfiHotPlugDeviceGuid,\r
                   NULL,\r
                   NULL\r
@@ -405,13 +440,15 @@ USBKeyboardDriverBindingStart (
                                             );\r
   if (EFI_ERROR (Status)) {\r
     gBS->UninstallMultipleProtocolInterfaces (\r
-          Controller,\r
-          &gEfiSimpleTextInProtocolGuid,\r
-          &UsbKeyboardDevice->SimpleInput,\r
-          &gEfiHotPlugDeviceGuid,\r
-          NULL,\r
-          NULL\r
-          );\r
+           Controller,\r
+           &gEfiSimpleTextInProtocolGuid,\r
+           &UsbKeyboardDevice->SimpleInput,\r
+           &gEfiSimpleTextInputExProtocolGuid,\r
+           &UsbKeyboardDevice->SimpleInputEx,\r
+           &gEfiHotPlugDeviceGuid,\r
+           NULL,\r
+           NULL\r
+           );\r
     gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
     gBS->FreePool (UsbKeyboardDevice);\r
     gBS->CloseProtocol (\r
@@ -442,13 +479,15 @@ USBKeyboardDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
 \r
     gBS->UninstallMultipleProtocolInterfaces (\r
-          Controller,\r
-          &gEfiSimpleTextInProtocolGuid,\r
-          &UsbKeyboardDevice->SimpleInput,\r
-          &gEfiHotPlugDeviceGuid,\r
-          NULL,\r
-          NULL\r
-          );\r
+           Controller,\r
+           &gEfiSimpleTextInProtocolGuid,\r
+           &UsbKeyboardDevice->SimpleInput,\r
+           &gEfiSimpleTextInputExProtocolGuid,\r
+           &UsbKeyboardDevice->SimpleInputEx,\r
+           &gEfiHotPlugDeviceGuid,\r
+           NULL,\r
+           NULL\r
+           );\r
     gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
     gBS->FreePool (UsbKeyboardDevice);\r
     gBS->CloseProtocol (\r
@@ -478,6 +517,27 @@ USBKeyboardDriverBindingStart (
 \r
 \r
   return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  if (UsbKeyboardDevice != NULL) {\r
+    if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
+      gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
+    }\r
+    if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+      gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
+    }\r
+    KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);    \r
+    gBS->FreePool (UsbKeyboardDevice);\r
+    UsbKeyboardDevice = NULL;\r
+  }\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiUsbIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return Status;\r
+\r
 }\r
 \r
 \r
@@ -518,7 +578,17 @@ USBKeyboardDriverBindingStop (
   if (EFI_ERROR (Status)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
-\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
   //\r
   // Get USB_KB_DEV instance.\r
   //\r
@@ -565,6 +635,8 @@ USBKeyboardDriverBindingStop (
                   Controller,\r
                   &gEfiSimpleTextInProtocolGuid,\r
                   &UsbKeyboardDevice->SimpleInput,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &UsbKeyboardDevice->SimpleInputEx,\r
                   &gEfiHotPlugDeviceGuid,\r
                   NULL,\r
                   NULL\r
@@ -575,6 +647,8 @@ USBKeyboardDriverBindingStop (
   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
 \r
   if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
     FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
@@ -586,20 +660,107 @@ USBKeyboardDriverBindingStop (
 \r
 }\r
 \r
+STATIC\r
+EFI_STATUS\r
+USBKeyboardReadKeyStrokeWorker (\r
+  IN  USB_KB_DEV                        *UsbKeyboardDevice,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
 \r
+  Arguments:\r
+    UsbKeyboardDevice     - Usb keyboard private structure.\r
+    KeyData               - A pointer to a buffer that is filled in with the keystroke \r
+                            state data for the key that was pressed.\r
 \r
-/**\r
-  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset() function.\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
 \r
-  This      The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
-  ExtendedVerification\r
-  Indicates that the driver may perform a more exhaustive\r
-  verification operation of the device during reset.\r
+--*/\r
+{\r
 \r
-  @retval EFI_SUCCESS           Success\r
-  @retval EFI_DEVICE_ERROR      Hardware Error\r
+  EFI_STATUS                        Status;\r
+  UINT8                             KeyChar;  \r
+  LIST_ENTRY                        *Link;\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *CurrentNotify;  \r
+  EFI_KEY_DATA                      OriginalKeyData;\r
 \r
-**/\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // if there is no saved ASCII byte, fetch it\r
+  // by calling USBKeyboardCheckForKey().\r
+  //\r
+  if (UsbKeyboardDevice->CurKeyChar == 0) {\r
+    Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  KeyData->Key.UnicodeChar = 0;\r
+  KeyData->Key.ScanCode    = SCAN_NULL;\r
+\r
+  KeyChar = UsbKeyboardDevice->CurKeyChar;\r
+\r
+  UsbKeyboardDevice->CurKeyChar = 0;\r
+\r
+  //\r
+  // Translate saved ASCII byte into EFI_INPUT_KEY\r
+  //\r
+  Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\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. In USBKeyCodeToEFIScanCode() 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 (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 exist\r
+  //\r
+  for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link, \r
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+                      NotifyEntry, \r
+                      USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
+      CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+  \r
+}\r
 EFI_STATUS\r
 EFIAPI\r
 USBKeyboardReset (\r
@@ -668,36 +829,20 @@ USBKeyboardReadKeyStroke (
   OUT EFI_INPUT_KEY                 *Key\r
   )\r
 {\r
-  USB_KB_DEV  *UsbKeyboardDevice;\r
-  EFI_STATUS  Status;\r
-  UINT8       KeyChar;\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
-  //\r
-  // if there is no saved ASCII byte, fetch it\r
-  // by calling USBKeyboardCheckForKey().\r
-  //\r
-  if (UsbKeyboardDevice->CurKeyChar == 0) {\r
-    Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
 \r
-  Key->UnicodeChar              = 0;\r
-  Key->ScanCode                 = SCAN_NULL;\r
-\r
-  KeyChar                       = UsbKeyboardDevice->CurKeyChar;\r
+  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
 \r
-  UsbKeyboardDevice->CurKeyChar = 0;\r
-\r
-  //\r
-  // Translate saved ASCII byte into EFI_INPUT_KEY\r
-  //\r
-  Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);\r
-\r
-  return Status;\r
+  return EFI_SUCCESS;\r
 \r
 }\r
 \r
@@ -792,3 +937,396 @@ KbdReportStatusCode (
     DevicePath\r
     );\r
 }\r
+STATIC\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  ListHead   - The list head\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Free the notify list successfully\r
+  EFI_INVALID_PARAMETER - ListHead is invalid.\r
+\r
+--*/\r
+{\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+  if (ListHead == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  while (!IsListEmpty (ListHead)) {\r
+    NotifyNode = CR (\r
+                   ListHead->ForwardLink, \r
+                   KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+                   NotifyEntry, \r
+                   USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                   );\r
+    RemoveEntryList (ListHead->ForwardLink);\r
+    gBS->FreePool (NotifyNode);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RegsiteredData    - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was registered.\r
+  InputData         - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was pressed.\r
+\r
+Returns:\r
+  TRUE              - Key be pressed matches a registered key.\r
+  FLASE             - Match failed. \r
+  \r
+--*/\r
+{\r
+  ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+  \r
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\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
+  return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions \r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  USB_KB_DEV                *UsbKeyboardDevice;\r
+  EFI_TPL                   OldTpl;\r
+  \r
+\r
+  UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+  Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
+  if (EFI_ERROR (Status)) {\r
+    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
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+{\r
+  USB_KB_DEV                        *UsbKeyboardDevice;\r
+\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+  return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
+  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+{\r
+  USB_KB_DEV                        *UsbKeyboardDevice;\r
+\r
+  if (KeyToggleState == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  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
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Update the status light\r
+  //\r
+\r
+  UsbKeyboardDevice->ScrollOn   = 0;\r
+  UsbKeyboardDevice->NumLockOn  = 0;\r
+  UsbKeyboardDevice->CapsOn     = 0;\r
\r
+  if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
+    UsbKeyboardDevice->ScrollOn = 1;\r
+  }\r
+  if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
+    UsbKeyboardDevice->NumLockOn = 1;\r
+  }\r
+  if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
+    UsbKeyboardDevice->CapsOn = 1;\r
+  }\r
+\r
+  SetKeyLED (UsbKeyboardDevice);\r
+\r
+  UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
+\r
+  return EFI_SUCCESS;\r
+  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+{\r
+  USB_KB_DEV                        *UsbKeyboardDevice;\r
+  EFI_STATUS                        Status;\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *NewNotify;\r
+  LIST_ENTRY                        *Link;\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *CurrentNotify;  \r
+\r
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+  //\r
+  for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\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 (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+        *NotifyHandle = CurrentNotify->NotifyHandle;        \r
+        return EFI_SUCCESS;\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
+  if (NewNotify == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewNotify->Signature         = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;     \r
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+  InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
+\r
+  //\r
+  // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+  //  \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &NewNotify->NotifyHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  *NotifyHandle = NewNotify->NotifyHandle;  \r
+  \r
+  return EFI_SUCCESS;\r
+  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+{\r
+  USB_KB_DEV                        *UsbKeyboardDevice;\r
+  EFI_STATUS                        Status;\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY     *CurrentNotify;\r
+  LIST_ENTRY                        *Link;\r
+\r
+  if (NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }  \r
+  \r
+  UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+  \r
+  Status = gBS->OpenProtocol (\r
+                  NotificationHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\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
+      // Remove the notification function from NotifyList and free resources\r
+      //\r
+      RemoveEntryList (&CurrentNotify->NotifyEntry);      \r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      CurrentNotify->NotifyHandle,\r
+                      &gSimpleTextInExNotifyGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      gBS->FreePool (CurrentNotify);            \r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;  \r
+}\r
+\r
index 710ec7c..bab22a3 100644 (file)
@@ -26,6 +26,7 @@ Revision History
 #include <PiDxe.h>\r
 \r
 #include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
 #include <Guid/HotPlugDevice.h>\r
 #include <Protocol/UsbIo.h>\r
 #include <Protocol/DevicePath.h>\r
@@ -40,7 +41,7 @@ Revision History
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/UsbLib.h>\r
-\r
+#include <Library/BaseLib.h>\r
 \r
 #include <IndustryStandard/Usb.h>\r
 \r
@@ -69,12 +70,22 @@ typedef struct {
 } USB_KB_BUFFER;\r
 \r
 #define USB_KB_DEV_SIGNATURE  EFI_SIGNATURE_32 ('u', 'k', 'b', 'd')\r
+#define USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'x')\r
+\r
+typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY {\r
+  UINTN                                 Signature;\r
+  EFI_HANDLE                            NotifyHandle;\r
+  EFI_KEY_DATA                          KeyData;\r
+  EFI_KEY_NOTIFY_FUNCTION               KeyNotificationFn;\r
+  LIST_ENTRY                            NotifyEntry;\r
+} KEYBOARD_CONSOLE_IN_EX_NOTIFY;\r
 typedef struct {\r
   UINTN                          Signature;\r
   EFI_DEVICE_PATH_PROTOCOL       *DevicePath;\r
   EFI_EVENT                      DelayedRecoveryEvent;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleInput;\r
-  EFI_USB_IO_PROTOCOL            *UsbIo;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;\r
+  EFI_USB_IO_PROTOCOL           *UsbIo;\r
 \r
   EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;\r
   EFI_USB_ENDPOINT_DESCRIPTOR   IntEndpointDescriptor;\r
@@ -93,7 +104,23 @@ typedef struct {
   EFI_EVENT                     RepeatTimer;\r
 \r
   EFI_UNICODE_STRING_TABLE      *ControllerNameTable;\r
-\r
+  \r
+  UINT8                         LeftCtrlOn;\r
+  UINT8                         LeftAltOn;\r
+  UINT8                         LeftShiftOn;\r
+  UINT8                         LeftLogoOn;\r
+  UINT8                         RightCtrlOn;\r
+  UINT8                         RightAltOn;\r
+  UINT8                         RightShiftOn;\r
+  UINT8                         RightLogoOn;  \r
+  UINT8                         MenuKeyOn;\r
+  UINT8                         SysReqOn;\r
+\r
+  EFI_KEY_STATE                 KeyState;\r
+  //\r
+  // Notification function list\r
+  //\r
+  LIST_ENTRY                    NotifyList;\r
 } USB_KB_DEV;\r
 \r
 //\r
@@ -103,6 +130,7 @@ extern EFI_DRIVER_BINDING_PROTOCOL   gUsbKeyboardDriverBinding;
 extern EFI_COMPONENT_NAME_PROTOCOL   gUsbKeyboardComponentName;\r
 extern EFI_COMPONENT_NAME2_PROTOCOL  gUsbKeyboardComponentName2;\r
 extern EFI_GUID                      gEfiUsbKeyboardDriverGuid;\r
+extern EFI_GUID                      gSimpleTextInExNotifyGuid;\r
 \r
 VOID\r
 KbdReportStatusCode (\r
@@ -113,6 +141,9 @@ KbdReportStatusCode (
 \r
 #define USB_KB_DEV_FROM_THIS(a) \\r
     CR(a, USB_KB_DEV, SimpleInput, USB_KB_DEV_SIGNATURE)\r
+#define TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS(a) \\r
+    CR(a, USB_KB_DEV, SimpleInputEx, USB_KB_DEV_SIGNATURE)\r
+\r
 \r
 #define MOD_CONTROL_L           0x01\r
 #define MOD_CONTROL_R           0x10\r
@@ -128,7 +159,7 @@ typedef struct {
   UINT8 Key;\r
 } KB_MODIFIER;\r
 \r
-#define USB_KEYCODE_MAX_MAKE      0x64\r
+#define USB_KEYCODE_MAX_MAKE      0x7E\r
 \r
 #define USBKBD_VALID_KEYCODE(key) ((UINT8) (key) > 3)\r
 \r
@@ -138,4 +169,137 @@ typedef struct {
   UINT8 ScrollLock : 1;\r
   UINT8 Resrvd : 5;\r
 } LED_MAP;\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+USBKeyboardUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+;\r
+\r
 #endif\r
+\r
index 9ad1bce..87179a4 100644 (file)
@@ -94,8 +94,8 @@ UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
   { SCAN_F8,        0x00,     0x00 },     // 0x41\r
   { SCAN_F9,        0x00,     0x00 },     // 0x42\r
   { SCAN_F10,       0x00,     0x00 },     // 0x43\r
-  { SCAN_F11,      0x00,     0x00 },     // 0x44   F11\r
-  { SCAN_F12,      0x00,     0x00 },     // 0x45   F12\r
+  { SCAN_F11,       0x00,     0x00 },     // 0x44   F11\r
+  { SCAN_F12,       0x00,     0x00 },     // 0x45   F12\r
   { SCAN_NULL,      0x00,     0x00 },     // 0x46   PrintScreen\r
   { SCAN_NULL,      0x00,     0x00 },     // 0x47   Scroll Lock\r
   { SCAN_NULL,      0x00,     0x00 },     // 0x48   Pause\r
@@ -129,7 +129,22 @@ UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
   { SCAN_NULL,      '\\',     '|' },      // 0x64 Keyboard Non-US \ and |\r
   { SCAN_NULL,      0x00,     0x00 },     // 0x65 Keyboard Application\r
   { SCAN_NULL,      0x00,     0x00 },     // 0x66 Keyboard Power\r
-  { SCAN_NULL,      '=' ,     '='  }      // 0x67 Keypad =\r
+  { SCAN_NULL,      '=' ,     '='  },     // 0x67 Keypad =\r
+  { SCAN_F13,       0x00,     0x00 },     // 0x68\r
+  { SCAN_F14,       0x00,     0x00 },     // 0x69\r
+  { SCAN_F15,       0x00,     0x00 },     // 0x6A  \r
+  { SCAN_F16,       0x00,     0x00 },     // 0x6B  \r
+  { SCAN_F17,       0x00,     0x00 },     // 0x6C\r
+  { SCAN_F18,       0x00,     0x00 },     // 0x6D\r
+  { SCAN_F19,       0x00,     0x00 },     // 0x6E\r
+  { SCAN_F20,       0x00,     0x00 },     // 0x6F\r
+  { SCAN_F21,       0x00,     0x00 },     // 0x70\r
+  { SCAN_F22,       0x00,     0x00 },     // 0x71\r
+  { SCAN_F23,       0x00,     0x00 },     // 0x72\r
+  { SCAN_F24,       0x00,     0x00 },     // 0x73\r
+  { SCAN_MUTE,      0x00,     0x00 },     // 0x7F\r
+  { SCAN_VOLUME_UP, 0x00,     0x00 },     // 0x80\r
+  { SCAN_VOLUME_DOWN, 0x00,   0x00 },     // 0x81\r
 };\r
 \r
 STATIC KB_MODIFIER  KB_Mod[8] = {\r
@@ -140,7 +155,7 @@ STATIC KB_MODIFIER  KB_Mod[8] = {
   { MOD_ALT_L,      0xe2 }, // 11100010\r
   { MOD_ALT_R,      0xe6 }, // 11100110\r
   { MOD_WIN_L,      0xe3 }, // 11100011\r
-  { MOD_WIN_R,      0xe7 }  // 11100111\r
+  { MOD_WIN_R,      0xe7 }, // 11100111 \r
 };\r
 \r
 \r
@@ -286,6 +301,17 @@ InitUSBKeyboard (
   UsbKeyboardDevice->NumLockOn  = 0;\r
   UsbKeyboardDevice->CapsOn     = 0;\r
   UsbKeyboardDevice->ScrollOn   = 0;\r
+  \r
+  UsbKeyboardDevice->LeftCtrlOn   = 0;\r
+  UsbKeyboardDevice->LeftAltOn    = 0;\r
+  UsbKeyboardDevice->LeftShiftOn  = 0;  \r
+  UsbKeyboardDevice->LeftLogoOn   = 0;  \r
+  UsbKeyboardDevice->RightCtrlOn  = 0;\r
+  UsbKeyboardDevice->RightAltOn   = 0;\r
+  UsbKeyboardDevice->RightShiftOn = 0;  \r
+  UsbKeyboardDevice->RightLogoOn  = 0;  \r
+  UsbKeyboardDevice->MenuKeyOn    = 0;\r
+  UsbKeyboardDevice->SysReqOn     = 0;  \r
 \r
   //\r
   // Sync the initial state of lights\r
@@ -675,21 +701,65 @@ USBParseKey (
     if (!UsbKey.Down) {\r
       switch (UsbKey.KeyCode) {\r
 \r
+      //\r
+      // CTRL release\r
+      //\r
       case 0xe0:\r
+        UsbKeyboardDevice->LeftCtrlOn = 0;\r
+        UsbKeyboardDevice->CtrlOn = 0;\r
+        break;\r
       case 0xe4:\r
+        UsbKeyboardDevice->RightCtrlOn = 0;\r
         UsbKeyboardDevice->CtrlOn = 0;\r
         break;\r
 \r
+      //\r
+      // Shift release\r
+      //\r
       case 0xe1:\r
+        UsbKeyboardDevice->LeftShiftOn = 0;\r
+        UsbKeyboardDevice->ShiftOn = 0;\r
+        break;\r
       case 0xe5:\r
+        UsbKeyboardDevice->RightShiftOn = 0;\r
         UsbKeyboardDevice->ShiftOn = 0;\r
         break;\r
 \r
+      //\r
+      // Alt release\r
+      //\r
       case 0xe2:\r
+        UsbKeyboardDevice->LeftAltOn = 0;\r
+        UsbKeyboardDevice->AltOn = 0;\r
+        break;\r
       case 0xe6:\r
+        UsbKeyboardDevice->RightAltOn = 0;\r
         UsbKeyboardDevice->AltOn = 0;\r
         break;\r
 \r
+      //\r
+      // Logo release\r
+      //\r
+     case 0xe3:\r
+        UsbKeyboardDevice->LeftLogoOn = 0;\r
+        break;\r
+      case 0xe7:\r
+        UsbKeyboardDevice->RightLogoOn = 0;\r
+        break;\r
+\r
+      //\r
+      // Menu key (App/Apps) release\r
+      //\r
+      case 0x65:\r
+        UsbKeyboardDevice->MenuKeyOn = 0;\r
+        break;\r
+\r
+      //\r
+      // SysReq release\r
+      //\r
+      case 0x46:\r
+        UsbKeyboardDevice->SysReqOn = 0;\r
+        break;\r
       default:\r
         break;\r
       }\r
@@ -703,51 +773,95 @@ USBParseKey (
     switch (UsbKey.KeyCode) {\r
 \r
     case 0xe0:\r
+      UsbKeyboardDevice->LeftCtrlOn = 1;\r
+      UsbKeyboardDevice->CtrlOn = 1;\r
+      continue;      \r
+      break;\r
     case 0xe4:\r
+      UsbKeyboardDevice->RightCtrlOn = 1;\r
       UsbKeyboardDevice->CtrlOn = 1;\r
       continue;\r
       break;\r
 \r
+    //\r
+    // Shift press\r
+    //\r
     case 0xe1:\r
+      UsbKeyboardDevice->LeftShiftOn = 1;\r
+      UsbKeyboardDevice->ShiftOn = 1;\r
+      continue;\r
+      break;\r
     case 0xe5:\r
+      UsbKeyboardDevice->RightShiftOn = 1;      \r
       UsbKeyboardDevice->ShiftOn = 1;\r
       continue;\r
       break;\r
 \r
+    //\r
+    // Alt press\r
+    //\r
     case 0xe2:\r
+      UsbKeyboardDevice->LeftAltOn = 1;\r
+      UsbKeyboardDevice->AltOn = 1;\r
+      continue;\r
+      break;\r
     case 0xe6:\r
+      UsbKeyboardDevice->RightAltOn = 1;      \r
       UsbKeyboardDevice->AltOn = 1;\r
       continue;\r
       break;\r
 \r
+    //\r
+    // Logo press\r
+    //\r
     case 0xe3:\r
+      UsbKeyboardDevice->LeftLogoOn = 1;\r
+      continue;      \r
+      break;\r
     case 0xe7:\r
+      UsbKeyboardDevice->RightLogoOn = 1;\r
       continue;\r
       break;\r
 \r
-    case 0x53:\r
-      UsbKeyboardDevice->NumLockOn ^= 1;\r
     //\r
-    // Turn on the NumLock light on KB\r
+    // Menu key (App/Apps) press\r
+    //\r
+    case 0x65:\r
+      UsbKeyboardDevice->MenuKeyOn = 1;\r
+      continue;      \r
+      break;\r
+\r
+    //\r
+    // SysReq press\r
     //\r
+    case 0x46:\r
+      UsbKeyboardDevice->SysReqOn = 1;\r
+      continue;      \r
+      break;\r
+\r
+    case 0x53:\r
+      UsbKeyboardDevice->NumLockOn ^= 1;\r
+      //\r
+      // Turn on the NumLock light on KB\r
+      //\r
       SetKeyLED (UsbKeyboardDevice);\r
       continue;\r
       break;\r
 \r
     case 0x39:\r
       UsbKeyboardDevice->CapsOn ^= 1;\r
-    //\r
-    // Turn on the CapsLock light on KB\r
-    //\r
+      //\r
+      // Turn on the CapsLock light on KB\r
+      //\r
       SetKeyLED (UsbKeyboardDevice);\r
       continue;\r
       break;\r
 \r
     case 0x47:\r
       UsbKeyboardDevice->ScrollOn ^= 1;\r
-    //\r
-    // Turn on the ScrollLock light on KB\r
-    //\r
+      //\r
+      // Turn on the ScrollLock light on KB\r
+      //\r
       SetKeyLED (UsbKeyboardDevice);\r
       continue;\r
       break;\r
@@ -757,18 +871,14 @@ USBParseKey (
     // keys are not valid EFI key\r
     //\r
 \r
-    case 0x46:\r
-    //\r
-    // fall through\r
     //\r
+    // PrintScreen/SysRq key and Application key\r
+    // Should be handled by UEFI2.1 compliant code\r
+\r
     case 0x48:\r
     //\r
     // fall through\r
     //\r
-    case 0x65:\r
-    //\r
-    // fall through\r
-    //\r
     case 0x66:\r
     //\r
     // fall through\r
@@ -834,11 +944,26 @@ USBKeyCodeToEFIScanCode (
     return EFI_NOT_READY;\r
   }\r
 \r
+  //\r
+  // Undefined entries from 0x74 to 0x7E\r
+  //\r
+  if (KeyChar > USB_KEYCODE_MAX_MAKE) {\r
+    Index = (UINT8) (Index - 11);\r
+  }\r
+\r
   Key->ScanCode = KeyConvertionTable[Index][0];\r
 \r
   if (UsbKeyboardDevice->ShiftOn) {\r
 \r
     Key->UnicodeChar = KeyConvertionTable[Index][2];\r
+    //\r
+    // 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 (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
+      UsbKeyboardDevice->LeftShiftOn = 0;\r
+      UsbKeyboardDevice->RightShiftOn = 0;\r
+    }\r
 \r
   } else {\r
 \r
@@ -885,6 +1010,51 @@ USBKeyCodeToEFIScanCode (
     return EFI_NOT_READY;\r
   }\r
 \r
+\r
+  //\r
+  // Save Shift/Toggle state\r
+  //\r
+  if (UsbKeyboardDevice->LeftCtrlOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightCtrlOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftAltOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightAltOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftShiftOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightShiftOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->LeftLogoOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->RightLogoOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->MenuKeyOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
+  }\r
+  if (UsbKeyboardDevice->SysReqOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
+  }  \r
+\r
+  if (UsbKeyboardDevice->ScrollOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
+  }\r
+  if (UsbKeyboardDevice->NumLockOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
+  }\r
+  if (UsbKeyboardDevice->CapsOn == 1) {\r
+    UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 \r
 }\r
index dc391e3..93edf82 100644 (file)
@@ -43,6 +43,21 @@ STATIC TEXT_IN_SPLITTER_PRIVATE_DATA  mConIn = {
   0,\r
   (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
   0,\r
+  {\r
+    ConSplitterTextInResetEx,\r
+    ConSplitterTextInReadKeyStrokeEx,\r
+    (EFI_EVENT) NULL,\r
+    ConSplitterTextInSetState,\r
+    ConSplitterTextInRegisterKeyNotify,\r
+    ConSplitterTextInUnregisterKeyNotify\r
+  },\r
+  0,\r
+  (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
+  0,\r
+  {\r
+    (struct _LIST_ENTRY     *) NULL,\r
+    (struct _LIST_ENTRY     *) NULL\r
+  },\r
 \r
   {\r
     ConSplitterSimplePointerReset,\r
@@ -367,6 +382,8 @@ Returns:
                     &mConIn.VirtualHandle,\r
                     &gEfiSimpleTextInProtocolGuid,\r
                     &mConIn.TextIn,\r
+                    &gEfiSimpleTextInputExProtocolGuid,\r
+                    &mConIn.TextInEx,\r
                     &gEfiSimplePointerProtocolGuid,\r
                     &mConIn.SimplePointer,\r
                     &gEfiPrimaryConsoleInDeviceGuid,\r
@@ -514,6 +531,30 @@ Returns:
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Buffer for Simple Text Input Ex Protocol\r
+  //  \r
+  Status = ConSplitterGrowBuffer (\r
+             sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+             &ConInPrivate->TextInExListCount,\r
+             (VOID **) &ConInPrivate->TextInExList\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  ConSplitterTextInWaitForKey,\r
+                  ConInPrivate,\r
+                  &ConInPrivate->TextInEx.WaitForKeyEx\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  InitializeListHead (&ConInPrivate->NotifyList); \r
+\r
+\r
   ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
 \r
   Status = ConSplitterGrowBuffer (\r
@@ -898,6 +939,7 @@ Returns:
 {\r
   EFI_STATUS                     Status;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
 \r
   //\r
   // Start ConSplitter on ControllerHandle, and create the virtual\r
@@ -915,6 +957,23 @@ Returns:
     return Status;\r
   }\r
 \r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  (VOID **) &TextInEx,\r
+                  This->DriverBindingHandle,\r
+                  mConIn.VirtualHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }  \r
+\r
   return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
 }\r
 \r
@@ -1195,10 +1254,29 @@ Returns:
   EFI_STATUS                     Status;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
 \r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
   if (NumberOfChildren == 0) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  (VOID **) &TextInEx,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  \r
   Status = ConSplitterStop (\r
             This,\r
             ControllerHandle,\r
@@ -1512,6 +1590,66 @@ Returns:
   return EFI_NOT_FOUND;\r
 }\r
 \r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // If the TextInEx List is full, enlarge it by calling growbuffer().\r
+  //\r
+  if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+    Status = ConSplitterGrowBuffer (\r
+              sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+              &Private->TextInExListCount,\r
+              (VOID **) &Private->TextInExList\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // Add the new text-in device data structure into the Text In List.\r
+  //\r
+  Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
+  Private->CurrentNumberOfExConsoles++;\r
+\r
+  //\r
+  // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
+  //\r
+  gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+{\r
+  UINTN Index;\r
+  //\r
+  // Remove the specified text-in device data structure from the Text In List,\r
+  // and rearrange the remaining data structures in the Text In List.\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    if (Private->TextInExList[Index] == TextInEx) {\r
+      for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+        Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
+      }\r
+\r
+      Private->CurrentNumberOfExConsoles--;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
 EFI_STATUS\r
 ConSplitterSimplePointerAddDevice (\r
   IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,\r
@@ -2760,6 +2898,433 @@ Returns:
   }\r
 }\r
 \r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RegsiteredData    - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was registered.\r
+  InputData         - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was pressed.\r
+\r
+Returns:\r
+  TRUE              - Key be pressed matches a registered key.\r
+  FLASE             - Match failed. \r
+  \r
+--*/\r
+{\r
+  ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+  \r
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\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
+  return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_STATUS                    ReturnStatus;\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  UINTN                         Index;\r
+\r
+  Private                       = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  Private->KeyEventSignalState  = FALSE;\r
+\r
+  //\r
+  // return the worst status met\r
+  //\r
+  for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->Reset (\r
+                                             Private->TextInExList[Index],\r
+                                             ExtendedVerification\r
+                                             );\r
+    if (EFI_ERROR (Status)) {\r
+      ReturnStatus = Status;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  EFI_KEY_DATA                  CurrentKeyData;\r
+\r
+  \r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+  if (Private->PasswordEnabled) {\r
+    //\r
+    // If StdIn Locked return not ready\r
+    //\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Private->KeyEventSignalState = FALSE;\r
+\r
+  KeyData->Key.UnicodeChar  = 0;\r
+  KeyData->Key.ScanCode     = SCAN_NULL;\r
+\r
+  //\r
+  // if no physical console input device exists, return EFI_NOT_READY;\r
+  // if any physical console input device has key input,\r
+  // return the key and EFI_SUCCESS.\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
+                                          Private->TextInExList[Index],\r
+                                          &CurrentKeyData\r
+                                          );\r
+    if (!EFI_ERROR (Status)) {\r
+      CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_READY;  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+\r
+  if (KeyToggleState == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // if no physical console input device exists, return EFI_SUCCESS;\r
+  // otherwise return the status of setting state of physical console input device\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->SetState (\r
+                                             Private->TextInExList[Index],\r
+                                             KeyToggleState\r
+                                             );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;  \r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY    *NewNotify;\r
+  LIST_ENTRY                    *Link;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY    *CurrentNotify;  \r
+  \r
+\r
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // if no physical console input device exists, \r
+  // return EFI_SUCCESS directly.\r
+  //\r
+  if (Private->CurrentNumberOfExConsoles <= 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+  //\r
+  for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link, \r
+                      TEXT_IN_EX_SPLITTER_NOTIFY, \r
+                      NotifyEntry, \r
+                      TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+        *NotifyHandle = CurrentNotify->NotifyHandle;        \r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Allocate resource to save the notification function\r
+  //  \r
+  NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
+  if (NewNotify == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+  if (NewNotify->NotifyHandleList == NULL) {\r
+    gBS->FreePool (NewNotify);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  NewNotify->Signature         = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;     \r
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+  \r
+  //\r
+  // Return the wrong status of registering key notify of \r
+  // physical console input device if meet problems\r
+  //\r
+  for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+    Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
+                                             Private->TextInExList[Index],\r
+                                             KeyData,\r
+                                             KeyNotificationFunction,\r
+                                             &NewNotify->NotifyHandleList[Index]\r
+                                             );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePool (NewNotify->NotifyHandleList);\r
+      gBS->FreePool (NewNotify);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+  //  \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &NewNotify->NotifyHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+  \r
+  *NotifyHandle                = NewNotify->NotifyHandle;  \r
+  \r
+  return EFI_SUCCESS;  \r
+  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+{\r
+  TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  TEXT_IN_EX_SPLITTER_NOTIFY    *CurrentNotify;\r
+  LIST_ENTRY                    *Link;            \r
+\r
+  if (NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  NotificationHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // if no physical console input device exists, \r
+  // return EFI_SUCCESS directly.\r
+  //\r
+  if (Private->CurrentNumberOfExConsoles <= 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
+    if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+      for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+        Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
+                                                 Private->TextInExList[Index], \r
+                                                 CurrentNotify->NotifyHandleList[Index]\r
+                                                 );\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }        \r
+      }\r
+      RemoveEntryList (&CurrentNotify->NotifyEntry);      \r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      CurrentNotify->NotifyHandle,\r
+                      &gSimpleTextInExNotifyGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      gBS->FreePool (CurrentNotify->NotifyHandleList);\r
+      gBS->FreePool (CurrentNotify);\r
+      return EFI_SUCCESS;      \r
+    }    \r
+  }\r
+\r
+  return EFI_NOT_FOUND;    \r
+  \r
+}\r
+\r
+\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 ConSplitterSimplePointerReset (\r
index 2bcf5a2..4a71bb6 100644 (file)
@@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SimpleTextOut.h>\r
 #include <Guid/ConsoleInDevice.h>\r
 #include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
 #include <Protocol/ConsoleControl.h>\r
 #include <Guid/StandardErrorDevice.h>\r
 #include <Guid/ConsoleOutDevice.h>\r
@@ -53,6 +54,8 @@ extern EFI_DRIVER_BINDING_PROTOCOL  gConSplitterStdErrDriverBinding;
 extern EFI_COMPONENT_NAME_PROTOCOL  gConSplitterStdErrComponentName;\r
 extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterStdErrComponentName2;\r
 \r
+extern EFI_GUID                     gSimpleTextInExNotifyGuid;\r
+\r
 // These definitions were in the old Hii protocol, but are not in the new UEFI\r
 // version. So they are defined locally.\r
 #define UNICODE_NARROW_CHAR   0xFFF0\r
@@ -76,6 +79,16 @@ typedef struct {
 //\r
 #define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'p')\r
 \r
+#define TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'n')\r
+\r
+typedef struct _TEXT_IN_EX_SPLITTER_NOTIFY {\r
+  UINTN                                 Signature;\r
+  EFI_HANDLE                            *NotifyHandleList;\r
+  EFI_HANDLE                            NotifyHandle;\r
+  EFI_KEY_DATA                          KeyData;\r
+  EFI_KEY_NOTIFY_FUNCTION               KeyNotificationFn;\r
+  LIST_ENTRY                            NotifyEntry;\r
+} TEXT_IN_EX_SPLITTER_NOTIFY;\r
 typedef struct {\r
   UINT64                         Signature;\r
   EFI_HANDLE                     VirtualHandle;\r
@@ -85,6 +98,13 @@ typedef struct {
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL **TextInList;\r
   UINTN                          TextInListCount;\r
 \r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL TextInEx;\r
+  UINTN                             CurrentNumberOfExConsoles;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **TextInExList;\r
+  UINTN                             TextInExListCount;\r
+  LIST_ENTRY                        NotifyList;    \r
+\r
+\r
   EFI_SIMPLE_POINTER_PROTOCOL    SimplePointer;\r
   EFI_SIMPLE_POINTER_MODE        SimplePointerMode;\r
   UINTN                          CurrentNumberOfPointers;\r
@@ -114,6 +134,19 @@ typedef struct {
       SimplePointer,                                              \\r
       TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE                     \\r
       )\r
+#define TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      TEXT_IN_SPLITTER_PRIVATE_DATA, \\r
+      TextInEx, \\r
+      TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \\r
+      )\r
+\r
+#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS(a) \\r
+  CR (a, \\r
+      TEXT_IN_SPLITTER_PRIVATE_DATA, \\r
+      AbsolutePointer, \\r
+      TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \\r
+      )\r
 \r
 //\r
 // Private data for the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL splitter\r
@@ -770,7 +803,151 @@ ConSplitterTextInReadKeyStroke (
   OUT EFI_INPUT_KEY                      *Key\r
   )\r
 ;\r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+  IN  TEXT_IN_SPLITTER_PRIVATE_DATA         *Private,\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TextInEx\r
+  )\r
+;\r
+\r
+//\r
+// Simple Text Input Ex protocol function prototypes\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+;\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+;\r
 VOID\r
 EFIAPI\r
 ConSplitterTextInWaitForKey (\r
@@ -945,10 +1122,10 @@ ConSpliterConsoleControlSetMode (
 EFI_STATUS\r
 EFIAPI\r
 ConSpliterGraphicsOutputQueryMode (\r
-  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL                 *This,\r
-  IN  UINT32                                   ModeNumber,\r
-  OUT UINTN                                       *SizeOfInfo,\r
-  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION     **Info\r
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,\r
+  IN  UINT32                            ModeNumber,\r
+  OUT UINTN                              *SizeOfInfo,\r
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info\r
   )\r
 ;\r
 \r
index c7e4079..9a781a5 100644 (file)
   gEfiPrimaryConsoleOutDeviceGuid               # ALWAYS_PRODUCED\r
   gEfiPrimaryConsoleInDeviceGuid                # ALWAYS_PRODUCED\r
   gEfiPrimaryStandardErrorDeviceGuid            # ALWAYS_PRODUCED\r
+  gSimpleTextInExNotifyGuid                     # ALWAYS_PRODUCED\r
 \r
 [Protocols]\r
   gEfiConsoleControlProtocolGuid                # PROTOCOL ALWAYS_PRODUCED\r
   gEfiSimplePointerProtocolGuid                 # PROTOCOL ALWAYS_PRODUCED\r
   gEfiSimpleTextInProtocolGuid                  # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiSimpleTextInputExProtocolGuid             # PROTOCOL ALWAYS_PRODUCED\r
   gEfiSimpleTextOutProtocolGuid                 # PROTOCOL ALWAYS_PRODUCED\r
   gEfiGraphicsOutputProtocolGuid                # PROTOCOL ALWAYS_PRODUCED\r
   gEfiUgaDrawProtocolGuid                       # PROTOCOL ALWAYS_PRODUCED\r
index 4e2f650..aaeca12 100644 (file)
@@ -22,6 +22,12 @@ Revision History:
 \r
 #include "Terminal.h"\r
 \r
+STATIC\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  );  \r
+\r
 //\r
 // Globals\r
 //\r
@@ -94,7 +100,19 @@ TERMINAL_DEV  gTerminalDevTemplate = {
   NULL, \r
   INPUT_STATE_DEFAULT,\r
   RESET_STATE_DEFAULT,\r
-  FALSE\r
+  FALSE,\r
+  {   // SimpleTextInputEx\r
+    TerminalConInResetEx,\r
+    TerminalConInReadKeyStrokeEx,\r
+    NULL,\r
+    TerminalConInSetState,\r
+    TerminalConInRegisterKeyNotify,\r
+    TerminalConInUnregisterKeyNotify,\r
+  },\r
+  {\r
+    NULL,\r
+    NULL,\r
+  }\r
 };\r
 \r
 \r
@@ -381,6 +399,19 @@ TerminalDriverBindingStart (
   TerminalDevice->TerminalType  = TerminalType;\r
   TerminalDevice->SerialIo      = SerialIo;\r
 \r
+  InitializeListHead (&TerminalDevice->NotifyList);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  TerminalConInWaitForKeyEx,\r
+                  &TerminalDevice->SimpleInputEx,\r
+                  &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
+\r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_WAIT,\r
                   TPL_NOTIFY,\r
@@ -391,7 +422,6 @@ TerminalDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     goto Error;\r
   }\r
-\r
   //\r
   // initialize the FIFO buffer used for accommodating\r
   // the pre-read pending characters\r
@@ -405,6 +435,7 @@ TerminalDriverBindingStart (
   // keystroke response performance issue\r
   //\r
   Mode            = TerminalDevice->SerialIo->Mode;\r
+\r
   SerialInTimeOut = 0;\r
   if (Mode->BaudRate != 0) {\r
     SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
@@ -578,6 +609,8 @@ TerminalDriverBindingStart (
                   TerminalDevice->DevicePath,\r
                   &gEfiSimpleTextInProtocolGuid,\r
                   &TerminalDevice->SimpleInput,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &TerminalDevice->SimpleInputEx,\r
                   &gEfiSimpleTextOutProtocolGuid,\r
                   &TerminalDevice->SimpleTextOutput,\r
                   NULL\r
@@ -655,6 +688,12 @@ Error:
         gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
       }\r
 \r
+      if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
+        gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+      }\r
+\r
+      TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
+\r
       if (TerminalDevice->ControllerNameTable != NULL) {\r
         FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
       }\r
@@ -809,6 +848,8 @@ TerminalDriverBindingStop (
                       ChildHandleBuffer[Index],\r
                       &gEfiSimpleTextInProtocolGuid,\r
                       &TerminalDevice->SimpleInput,\r
+                      &gEfiSimpleTextInputExProtocolGuid,\r
+                      &TerminalDevice->SimpleInputEx,\r
                       &gEfiSimpleTextOutProtocolGuid,\r
                       &TerminalDevice->SimpleTextOutput,\r
                       &gEfiDevicePathProtocolGuid,\r
@@ -851,6 +892,8 @@ TerminalDriverBindingStop (
 \r
         gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
         gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
+        gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
+        TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
         FreePool (TerminalDevice->DevicePath);\r
         FreePool (TerminalDevice);\r
       }\r
@@ -868,6 +911,47 @@ TerminalDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
+STATIC\r
+EFI_STATUS\r
+TerminalFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  ListHead   - The list head\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Free the notify list successfully\r
+  EFI_INVALID_PARAMETER - ListHead is invalid.\r
+\r
+--*/\r
+{\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+  if (ListHead == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  while (!IsListEmpty (ListHead)) {\r
+    NotifyNode = CR (\r
+                   ListHead->ForwardLink, \r
+                   TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+                   NotifyEntry, \r
+                   TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                   );\r
+    RemoveEntryList (ListHead->ForwardLink);\r
+    gBS->FreePool (NotifyNode);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
 VOID\r
 TerminalUpdateConsoleDevVariable (\r
   IN CHAR16                    *VariableName,\r
index 0ae1c43..b352c66 100644 (file)
@@ -30,6 +30,7 @@ Revision History
 #include <Guid/GlobalVariable.h>\r
 #include <Protocol/DevicePath.h>\r
 #include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
 #include <Guid/HotPlugDevice.h>\r
 #include <Guid/PcAnsi.h>\r
 #include <Library/DebugLib.h>\r
@@ -42,7 +43,7 @@ Revision History
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/PcdLib.h>\r
-\r
+#include <Library/BaseLib.h>\r
 \r
 \r
 #define RAW_FIFO_MAX_NUMBER 256\r
@@ -68,6 +69,15 @@ typedef struct {
 \r
 #define TERMINAL_DEV_SIGNATURE  EFI_SIGNATURE_32 ('t', 'm', 'n', 'l')\r
 \r
+#define TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'e', 'n')\r
+\r
+typedef struct _TERMINAL_CONSOLE_IN_EX_NOTIFY {\r
+  UINTN                                 Signature;\r
+  EFI_HANDLE                            NotifyHandle;\r
+  EFI_KEY_DATA                          KeyData;\r
+  EFI_KEY_NOTIFY_FUNCTION               KeyNotificationFn;\r
+  LIST_ENTRY                            NotifyEntry;\r
+} TERMINAL_CONSOLE_IN_EX_NOTIFY;\r
 typedef struct {\r
   UINTN                               Signature;\r
   EFI_HANDLE                          Handle;\r
@@ -94,6 +104,8 @@ typedef struct {
   // to indicate whether the Esc could be sent or not.\r
   //\r
   BOOLEAN                             OutputEscChar;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL   SimpleInputEx;\r
+  LIST_ENTRY                          NotifyList;\r
 } TERMINAL_DEV;\r
 \r
 #define INPUT_STATE_DEFAULT               0x00\r
@@ -109,6 +121,7 @@ typedef struct {
 \r
 #define TERMINAL_CON_IN_DEV_FROM_THIS(a)  CR (a, TERMINAL_DEV, SimpleInput, TERMINAL_DEV_SIGNATURE)\r
 #define TERMINAL_CON_OUT_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleTextOutput, TERMINAL_DEV_SIGNATURE)\r
+#define TERMINAL_CON_IN_EX_DEV_FROM_THIS(a)  CR (a, TERMINAL_DEV, SimpleInputEx, TERMINAL_DEV_SIGNATURE)\r
 \r
 typedef union {\r
   UINT8 Utf8_1;\r
@@ -153,6 +166,7 @@ extern EFI_DRIVER_BINDING_PROTOCOL   gTerminalDriverBinding;
 extern EFI_COMPONENT_NAME_PROTOCOL   gTerminalComponentName;\r
 extern EFI_COMPONENT_NAME2_PROTOCOL  gTerminalComponentName2;\r
 \r
+extern EFI_GUID                      gSimpleTextInExNotifyGuid;\r
 //\r
 // Prototypes\r
 //\r
@@ -180,6 +194,169 @@ TerminalConInReadKeyStroke (
   )\r
 ;\r
 \r
+\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RegsiteredData    - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was registered.\r
+  InputData         - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was pressed.\r
+\r
+Returns:\r
+  TRUE              - Key be pressed matches a registered key.\r
+  FLASE             - Match failed. \r
+  \r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+TerminalConInWaitForKeyEx (\r
+  IN  EFI_EVENT       Event,\r
+  IN  VOID            *Context\r
+  )\r
+;  \r
+//\r
+// Simple Text Input Ex protocol prototypes\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+;\r
+\r
 VOID\r
 EFIAPI\r
 TerminalConInWaitForKey (\r
index 2d76e38..4b3eb37 100644 (file)
@@ -1,6 +1,6 @@
 /**@file\r
-       Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
-       \r
+  Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
+  \r
 Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
 All rights reserved. This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
@@ -15,6 +15,78 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Terminal.h"\r
 \r
 \r
+STATIC\r
+EFI_STATUS\r
+ReadKeyStrokeWorker (\r
+  IN  TERMINAL_DEV *TerminalDevice,\r
+  OUT EFI_KEY_DATA *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    TerminalDevice        - Terminal driver private structure\r
+    KeyData               - A pointer to a buffer that is filled in with the keystroke \r
+                            state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  LIST_ENTRY                      *Link;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
+\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }  \r
+\r
+  //\r
+  // Initialize *Key to nonsense value.\r
+  //\r
+  KeyData->Key.ScanCode    = SCAN_NULL;\r
+  KeyData->Key.UnicodeChar = 0;\r
+\r
+  Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  KeyData->KeyState.KeyShiftState  = 0;\r
+  KeyData->KeyState.KeyToggleState = 0;\r
+\r
+  //\r
+  // Invoke notification functions if exist\r
+  //\r
+  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+                      NotifyEntry, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+      CurrentNotify->KeyNotificationFn (KeyData);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 TerminalConInReset (\r
@@ -111,28 +183,358 @@ TerminalConInReadKeyStroke (
 {\r
   TERMINAL_DEV  *TerminalDevice;\r
   EFI_STATUS    Status;\r
+  EFI_KEY_DATA  KeyData;\r
 \r
-  //\r
-  // Initialize *Key to nonsense value.\r
-  //\r
-  Key->ScanCode     = SCAN_NULL;\r
-  Key->UnicodeChar  = 0;\r
   //\r
   //  get TERMINAL_DEV from "This" parameter.\r
   //\r
   TerminalDevice  = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
 \r
-  Status          = TerminalConInCheckForKey (This);\r
+  Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);\r
   if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_READY;\r
+    return Status;\r
+  }\r
+\r
+  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  RegsiteredData    - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was registered.\r
+  InputData         - A pointer to a buffer that is filled in with the keystroke \r
+                      state data for the key that was pressed.\r
+\r
+Returns:\r
+  TRUE              - Key be pressed matches a registered key.\r
+  FLASE             - Match failed. \r
+  \r
+--*/\r
+{\r
+  ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+  \r
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||\r
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+    return FALSE;  \r
+  }      \r
+  \r
+  return TRUE;\r
+}\r
+\r
+\r
+VOID\r
+EFIAPI\r
+TerminalConInWaitForKeyEx (\r
+  IN  EFI_EVENT       Event,\r
+  IN  VOID            *Context\r
+  )\r
+/*++\r
+  Routine Description:\r
+  \r
+    Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
+    Signal the event if there is key available     \r
+  \r
+  Arguments:\r
+  \r
+    Event - Indicates the event that invoke this function.\r
+    \r
+    Context - Indicates the calling context.\r
+        \r
+  Returns:\r
+  \r
+    N/A\r
+                \r
+--*/\r
+{\r
+  TERMINAL_DEV            *TerminalDevice;\r
+  \r
+  TerminalDevice  = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);\r
+\r
+  TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reset the input device and optionaly run diagnostics\r
+\r
+  Arguments:\r
+    This                 - Protocol instance pointer.\r
+    ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The device was reset.\r
+    EFI_DEVICE_ERROR      - The device is not functioning properly and could \r
+                            not be reset.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS              Status;\r
+  TERMINAL_DEV            *TerminalDevice;\r
+\r
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+  Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  EfiKeyFiFoRemoveOneKey (TerminalDevice, Key);\r
+  return EFI_SUCCESS;\r
+  \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Reads the next keystroke from the input device. The WaitForKey Event can \r
+    be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+  Arguments:\r
+    This       - Protocol instance pointer.\r
+    KeyData    - A pointer to a buffer that is filled in with the keystroke \r
+                 state data for the key that was pressed.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The keystroke information was returned.\r
+    EFI_NOT_READY         - There was no keystroke data availiable.\r
+    EFI_DEVICE_ERROR      - The keystroke information was not returned due to \r
+                            hardware errors.\r
+    EFI_INVALID_PARAMETER - KeyData is NULL.                        \r
+\r
+--*/\r
+{\r
+  TERMINAL_DEV                    *TerminalDevice;\r
+\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }  \r
+\r
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+  return ReadKeyStrokeWorker (TerminalDevice, KeyData);\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set certain state for the input device.\r
+\r
+  Arguments:\r
+    This                  - Protocol instance pointer.\r
+    KeyToggleState        - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+                            state for the input device.\r
+                          \r
+  Returns:                \r
+    EFI_SUCCESS           - The device state was set successfully.\r
+    EFI_DEVICE_ERROR      - The device is not functioning correctly and could \r
+                            not have the setting adjusted.\r
+    EFI_UNSUPPORTED       - The device does not have the ability to set its state.\r
+    EFI_INVALID_PARAMETER - KeyToggleState is NULL.                       \r
+\r
+--*/   \r
+{\r
+  if (KeyToggleState == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
+}\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInRegisterKeyNotify (\r
+  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
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Register a notification function for a particular keystroke for the input device.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.\r
+    KeyData                 - A pointer to a buffer that is filled in with the keystroke \r
+                              information data for the key that was pressed.\r
+    KeyNotificationFunction - Points to the function to be called when the key \r
+                              sequence is typed specified by KeyData.                        \r
+    NotifyHandle            - Points to the unique handle assigned to the registered notification.                          \r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was registered successfully.\r
+    EFI_OUT_OF_RESOURCES    - Unable to allocate resources for necesssary data structures.\r
+    EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.                       \r
+                              \r
+--*/   \r
+{\r
+  EFI_STATUS                      Status;\r
+  TERMINAL_DEV                    *TerminalDevice;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *NewNotify;\r
+  LIST_ENTRY                      *Link;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;  \r
+\r
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+  //\r
+  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+                      NotifyEntry, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+        *NotifyHandle = CurrentNotify->NotifyHandle;        \r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Allocate resource to save the notification function\r
+  //  \r
+  NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));\r
+  if (NewNotify == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }  \r
+\r
+  NewNotify->Signature         = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;     \r
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+  InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
+  //\r
+  // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+  //  \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &NewNotify->NotifyHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  *NotifyHandle                = NewNotify->NotifyHandle;  \r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+TerminalConInUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_HANDLE                         NotificationHandle\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Remove a registered notification function from a particular keystroke.\r
+\r
+  Arguments:\r
+    This                    - Protocol instance pointer.    \r
+    NotificationHandle      - The handle of the notification function being unregistered.\r
+\r
+  Returns:\r
+    EFI_SUCCESS             - The notification function was unregistered successfully.\r
+    EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.\r
+    EFI_NOT_FOUND           - Can not find the matching entry in database.  \r
+                              \r
+--*/   \r
+{\r
+  EFI_STATUS                      Status;\r
+  TERMINAL_DEV                    *TerminalDevice;\r
+  LIST_ENTRY                      *Link;\r
+  TERMINAL_CONSOLE_IN_EX_NOTIFY   *CurrentNotify;\r
+\r
+  if (NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  } \r
+  \r
+  Status = gBS->OpenProtocol (\r
+                  NotificationHandle,\r
+                  &gSimpleTextInExNotifyGuid,\r
+                  NULL,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
+\r
+  for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY, \r
+                      NotifyEntry, \r
+                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+      //\r
+      // Remove the notification function from NotifyList and free resources\r
+      //\r
+      RemoveEntryList (&CurrentNotify->NotifyEntry);      \r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      CurrentNotify->NotifyHandle,\r
+                      &gSimpleTextInExNotifyGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+      gBS->FreePool (CurrentNotify);            \r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  \r
+  return EFI_NOT_FOUND;  \r
+}\r
+\r
+\r
 VOID\r
 TranslateRawDataToEfiKey (\r
   IN  TERMINAL_DEV      *TerminalDevice\r
@@ -787,7 +1189,9 @@ Symbols used in table below
 | F9      | 0x13 | ESC [ U   | ESC 9    | ESC O p  |\r
 | F10     | 0x14 | ESC [ V   | ESC 0    | ESC O M  |\r
 | Escape  | 0x17 | ESC       | ESC      | ESC      |\r
-+=========+======+===========+==========+=========+\r
+| F11     | 0x15 |           | ESC !    |          |\r
+| F12     | 0x16 |           | ESC @    |          |\r
++=========+======+===========+==========+==========+\r
 \r
 Special Mappings\r
 ================\r
@@ -882,6 +1286,12 @@ ESC R ESC r ESC R = Reset System
         case '0': \r
           Key.ScanCode = SCAN_F10;        \r
           break;\r
+        case '!':\r
+          Key.ScanCode = SCAN_F11;\r
+          break;\r
+        case '@':\r
+          Key.ScanCode = SCAN_F12;\r
+          break;          \r
         case 'h': \r
           Key.ScanCode = SCAN_HOME;       \r
           break;\r
@@ -1150,6 +1560,10 @@ ESC R ESC r ESC R = Reset System
     if (UnicodeChar == ESC) {\r
       TerminalDevice->InputState = INPUT_STATE_ESC;\r
     }\r
+\r
+    if (UnicodeChar == CSI) {\r
+      TerminalDevice->InputState = INPUT_STATE_CSI;\r
+    }\r
     \r
     if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
       Status = gBS->SetTimer(\r
index 2e279f2..7844686 100644 (file)
@@ -58,6 +58,7 @@
   UefiDriverEntryPoint\r
   DebugLib\r
   PcdLib\r
+  BaseLib\r
 \r
 [Guids]\r
   gEfiGlobalVariableGuid                        # SOMETIMES_CONSUMED L"ErrOutDev"\r
   gEfiVT100Guid                                 # SOMETIMES_CONSUMED\r
   gEfiVT100PlusGuid                             # SOMETIMES_CONSUMED\r
   gEfiPcAnsiGuid                                # SOMETIMES_CONSUMED\r
-\r
+  gSimpleTextInExNotifyGuid                     # SOMETIMES_CONSUMED\r
 \r
 [Protocols]\r
   gEfiHotPlugDeviceGuid                         # PROTOCOL SOMETIMES_CONSUMED\r
   gEfiSerialIoProtocolGuid                      # PROTOCOL TO_START\r
   gEfiDevicePathProtocolGuid                    # PROTOCOL TO_START\r
   gEfiSimpleTextInProtocolGuid                  # PROTOCOL BY_START\r
+  gEfiSimpleTextInputExProtocolGuid             # PROTOCOL BY_START\r
   gEfiSimpleTextOutProtocolGuid                 # PROTOCOL BY_START\r
 \r
 [Pcd]\r