]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmbeddedPkg/Drivers: add virtual keyboard driver
authorHaojian Zhuang <haojian.zhuang@linaro.org>
Thu, 8 Mar 2018 13:28:22 +0000 (21:28 +0800)
committerLeif Lindholm <leif.lindholm@linaro.org>
Mon, 30 Apr 2018 16:58:14 +0000 (17:58 +0100)
This driver is used to simulate a keyboard. For example, user
could read GPIO setting or data from RAM address. If the value
matches the expected pattern, it could trigger a key pressed
event.

User needs to implement hooks of PLATFORM_VIRTUAL_KBD_PROTOCOL.
There're 4 hooks in this protocol.
Register(): Quote the interface that user needs. For example, user
needs to locate GPIO protocol if he wants to simulate a GPIO value
as a key.
Reset(): Do the initialization before reading value.
Query(): Read value. If the value matches the expected pattern,
trigger a key pressed event.
Clear(): Clean the value if necessary.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c [new file with mode: 0644]
EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h [new file with mode: 0644]
EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c [new file with mode: 0644]
EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h [new file with mode: 0644]
EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf [new file with mode: 0644]
EmbeddedPkg/EmbeddedPkg.dec
EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h [new file with mode: 0644]

diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..9ba706c
--- /dev/null
@@ -0,0 +1,188 @@
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "VirtualKeyboard.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName = {\r
+  VirtualKeyboardComponentNameGetDriverName,\r
+  VirtualKeyboardComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {\r
+  {\r
+    "eng;en",\r
+    L"Virtual Keyboard Driver"\r
+  },\r
+  {\r
+    "zh-CHS",\r
+    L"虚拟键盘驱动程序"\r
+  },\r
+  {\r
+    NULL,\r
+    NULL\r
+  }\r
+};\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mVirtualKeyboardDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gVirtualKeyboardComponentName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h
new file mode 100644 (file)
index 0000000..94bef28
--- /dev/null
@@ -0,0 +1,154 @@
+/** @file\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_\r
+#define _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_\r
+\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gVirtualKeyboardComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gVirtualKeyboardComponentName2;\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+\r
+\r
+#endif\r
diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c
new file mode 100644 (file)
index 0000000..6609bc8
--- /dev/null
@@ -0,0 +1,1149 @@
+/** @file\r
+  VirtualKeyboard driver\r
+\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "VirtualKeyboard.h"\r
+\r
+//\r
+// RAM Keyboard Driver Binding Protocol Instance\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {\r
+  VirtualKeyboardDriverBindingSupported,\r
+  VirtualKeyboardDriverBindingStart,\r
+  VirtualKeyboardDriverBindingStop,\r
+  0x10,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+//\r
+// EFI Driver Binding Protocol Functions\r
+//\r
+\r
+/**\r
+  Check whether the driver supports this device.\r
+\r
+  @param  This                   The Udriver binding protocol.\r
+  @param  Controller             The controller handle to check.\r
+  @param  RemainingDevicePath    The remaining device path.\r
+\r
+  @retval EFI_SUCCESS            The driver supports this controller.\r
+  @retval other                  This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  PLATFORM_VIRTUAL_KBD_PROTOCOL   *PlatformVirtual;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gPlatformVirtualKeyboardProtocolGuid,\r
+                  (VOID **) &PlatformVirtual,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gPlatformVirtualKeyboardProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Starts the device with this driver.\r
+\r
+  @param  This                   The driver binding instance.\r
+  @param  Controller             Handle of device to bind driver to.\r
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
+                                 device to start.\r
+\r
+  @retval EFI_SUCCESS            The controller is controlled by the driver.\r
+  @retval Other                  This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  VIRTUAL_KEYBOARD_DEV                      *VirtualKeyboardPrivate;\r
+  PLATFORM_VIRTUAL_KBD_PROTOCOL             *PlatformVirtual;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gPlatformVirtualKeyboardProtocolGuid,\r
+                  (VOID **) &PlatformVirtual,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate the private device structure\r
+  //\r
+  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV));\r
+  if (VirtualKeyboardPrivate == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Initialize the private device structure\r
+  //\r
+  VirtualKeyboardPrivate->Signature                  = VIRTUAL_KEYBOARD_DEV_SIGNATURE;\r
+  VirtualKeyboardPrivate->Handle                     = Controller;\r
+  VirtualKeyboardPrivate->PlatformVirtual            = PlatformVirtual;\r
+  VirtualKeyboardPrivate->Queue.Front                = 0;\r
+  VirtualKeyboardPrivate->Queue.Rear                 = 0;\r
+  VirtualKeyboardPrivate->QueueForNotify.Front       = 0;\r
+  VirtualKeyboardPrivate->QueueForNotify.Rear        = 0;\r
+\r
+  VirtualKeyboardPrivate->SimpleTextIn.Reset         = VirtualKeyboardReset;\r
+  VirtualKeyboardPrivate->SimpleTextIn.ReadKeyStroke = VirtualKeyboardReadKeyStroke;\r
+\r
+  VirtualKeyboardPrivate->SimpleTextInputEx.Reset               = VirtualKeyboardResetEx;\r
+  VirtualKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx     = VirtualKeyboardReadKeyStrokeEx;\r
+  VirtualKeyboardPrivate->SimpleTextInputEx.SetState            = VirtualKeyboardSetState;\r
+\r
+  VirtualKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify   = VirtualKeyboardRegisterKeyNotify;\r
+  VirtualKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = VirtualKeyboardUnregisterKeyNotify;\r
+  InitializeListHead (&VirtualKeyboardPrivate->NotifyList);\r
+\r
+  Status = PlatformVirtual->Register ();\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Report that the keyboard is being enabled\r
+  //\r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE\r
+    );\r
+\r
+  //\r
+  // Setup the WaitForKey event\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  VirtualKeyboardWaitForKey,\r
+                  &(VirtualKeyboardPrivate->SimpleTextIn),\r
+                  &((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey)\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    (VirtualKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;\r
+    goto Done;\r
+  }\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  VirtualKeyboardWaitForKeyEx,\r
+                  &(VirtualKeyboardPrivate->SimpleTextInputEx),\r
+                  &(VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Setup a periodic timer, used for reading keystrokes at a fixed interval\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  VirtualKeyboardTimerHandler,\r
+                  VirtualKeyboardPrivate,\r
+                  &VirtualKeyboardPrivate->TimerEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  Status = gBS->SetTimer (\r
+                  VirtualKeyboardPrivate->TimerEvent,\r
+                  TimerPeriodic,\r
+                  KEYBOARD_TIMER_INTERVAL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  KeyNotifyProcessHandler,\r
+                  VirtualKeyboardPrivate,\r
+                  &VirtualKeyboardPrivate->KeyNotifyProcessEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Reset the keyboard device\r
+  //\r
+  Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset (\r
+                                     &VirtualKeyboardPrivate->SimpleTextInputEx,\r
+                                     FALSE\r
+                                     );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));\r
+    goto Done;\r
+  }\r
+  //\r
+  // Install protocol interfaces for the keyboard device.\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Controller,\r
+                  &gEfiSimpleTextInProtocolGuid,\r
+                  &VirtualKeyboardPrivate->SimpleTextIn,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &VirtualKeyboardPrivate->SimpleTextInputEx,\r
+                  NULL\r
+                  );\r
+\r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    if (VirtualKeyboardPrivate != NULL) {\r
+      if ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {\r
+        gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey);\r
+      }\r
+\r
+      if ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {\r
+        gBS->CloseEvent (\r
+               (VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx\r
+               );\r
+      }\r
+\r
+      if (VirtualKeyboardPrivate->KeyNotifyProcessEvent != NULL) {\r
+        gBS->CloseEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);\r
+      }\r
+\r
+      VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList);\r
+\r
+      if (VirtualKeyboardPrivate->TimerEvent != NULL) {\r
+        gBS->CloseEvent (VirtualKeyboardPrivate->TimerEvent);\r
+      }\r
+      FreePool (VirtualKeyboardPrivate);\r
+    }\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gPlatformVirtualKeyboardProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Stop the device handled by this driver.\r
+\r
+  @param  This                   The driver binding protocol.\r
+  @param  Controller             The controller to release.\r
+  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.\r
+  @param  ChildHandleBuffer      The array of child handle.\r
+\r
+  @retval EFI_SUCCESS            The device was stopped.\r
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a\r
+                                 device error.\r
+  @retval Others                 Fail to uninstall protocols attached on the\r
+                                 device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Enqueue the key.\r
+\r
+  @param  Queue                 The queue to be enqueued.\r
+  @param  KeyData               The key data to be enqueued.\r
+\r
+  @retval EFI_NOT_READY         The queue is full.\r
+  @retval EFI_SUCCESS           Successfully enqueued the key data.\r
+\r
+**/\r
+EFI_STATUS\r
+Enqueue (\r
+  IN SIMPLE_QUEUE         *Queue,\r
+  IN EFI_KEY_DATA         *KeyData\r
+  )\r
+{\r
+  if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));\r
+  Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Dequeue the key.\r
+\r
+  @param  Queue                 The queue to be dequeued.\r
+  @param  KeyData               The key data to be dequeued.\r
+\r
+  @retval EFI_NOT_READY         The queue is empty.\r
+  @retval EFI_SUCCESS           Successfully dequeued the key data.\r
+\r
+**/\r
+EFI_STATUS\r
+Dequeue (\r
+  IN SIMPLE_QUEUE         *Queue,\r
+  IN EFI_KEY_DATA         *KeyData\r
+  )\r
+{\r
+  if (Queue->Front == Queue->Rear) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));\r
+  Queue->Front  = (Queue->Front + 1) % QUEUE_MAX_COUNT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether the queue is empty.\r
+\r
+  @param  Queue                 The queue to be checked.\r
+\r
+  @retval EFI_NOT_READY         The queue is empty.\r
+  @retval EFI_SUCCESS           The queue is not empty.\r
+\r
+**/\r
+EFI_STATUS\r
+CheckQueue (\r
+  IN SIMPLE_QUEUE         *Queue\r
+  )\r
+{\r
+  if (Queue->Front == Queue->Rear) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check key buffer to get the key stroke status.\r
+\r
+  @param  This         Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS  A key is being pressed now.\r
+  @retval Other        No key is now pressed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardCheckForKey (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This\r
+  )\r
+{\r
+  VIRTUAL_KEYBOARD_DEV     *VirtualKeyboardPrivate;\r
+\r
+  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  return CheckQueue (&VirtualKeyboardPrivate->Queue);\r
+}\r
+\r
+/**\r
+  Free keyboard notify list.\r
+\r
+  @param  ListHead   The list head\r
+\r
+  @retval EFI_SUCCESS           Free the notify list successfully\r
+  @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+VirtualKeyboardFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  )\r
+{\r
+  VIRTUAL_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
+                   VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                   NotifyEntry,\r
+                   VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                   );\r
+    RemoveEntryList (ListHead->ForwardLink);\r
+    gBS->FreePool (NotifyNode);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Judge whether is a registed key\r
+\r
+  @param RegsiteredData       A pointer to a buffer that is filled in with\r
+                              the keystroke state data for the key that was\r
+                              registered.\r
+  @param InputData            A pointer to a buffer that is filled in with\r
+                              the keystroke state data for the key that was\r
+                              pressed.\r
+\r
+  @retval TRUE                Key be pressed matches a registered key.\r
+  @retval FLASE               Match failed.\r
+\r
+**/\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\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\r
+  // 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
+  Event notification function for SIMPLE_TEXT_IN.WaitForKey event\r
+  Signal the event if there is key available\r
+\r
+  @param Event    the event object\r
+  @param Context  waitting context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardWaitForKey (\r
+  IN  EFI_EVENT               Event,\r
+  IN  VOID                    *Context\r
+  )\r
+{\r
+  //\r
+  // Stall 1ms to give a chance to let other driver interrupt this routine\r
+  // for their timer event.\r
+  // e.g. UI setup or Shell, other drivers which are driven by timer event\r
+  // will have a bad performance during this period,\r
+  // e.g. usb keyboard driver.\r
+  // Add a stall period can greatly increate other driver performance during\r
+  // the WaitForKey is recursivly invoked. 1ms delay will make little impact\r
+  // to the thunk keyboard driver, and user can not feel the delay at all when\r
+  // input.\r
+  //\r
+  gBS->Stall (1000);\r
+  //\r
+  // Use TimerEvent callback function to check whether there's any key pressed\r
+  //\r
+  VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context));\r
+\r
+  if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) {\r
+    gBS->SignalEvent (Event);\r
+  }\r
+}\r
+\r
+/**\r
+  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
+  event. Signal the event if there is key available\r
+\r
+  @param Event    event object\r
+  @param Context  waiting context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardWaitForKeyEx (\r
+  IN  EFI_EVENT               Event,\r
+  IN  VOID                    *Context\r
+  )\r
+\r
+{\r
+  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;\r
+\r
+  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context);\r
+  VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn);\r
+\r
+}\r
+\r
+//\r
+// EFI Simple Text In Protocol Functions\r
+//\r
+/**\r
+  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE)\r
+  then do some extra keyboard validations.\r
+\r
+  @param  This                  Pointer of simple text Protocol.\r
+  @param  ExtendedVerification  Whether perform the extra validation of\r
+                                keyboard. True: perform; FALSE: skip.\r
+\r
+  @retval EFI_SUCCESS           The command byte is written successfully.\r
+  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReset (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
+  IN  BOOLEAN                         ExtendedVerification\r
+  )\r
+{\r
+  VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;\r
+  EFI_STATUS           Status;\r
+  EFI_TPL              OldTpl;\r
+\r
+  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Raise TPL to avoid mouse operation impact\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  if (VirtualKeyboardPrivate->PlatformVirtual &&\r
+      VirtualKeyboardPrivate->PlatformVirtual->Reset) {\r
+    Status = VirtualKeyboardPrivate->PlatformVirtual->Reset ();\r
+  } else {\r
+    Status = EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // resume priority of task level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reset the input device and optionaly run diagnostics\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  ExtendedVerification  Driver may perform diagnostics on reset.\r
+\r
+  @retval EFI_SUCCESS           The device was reset.\r
+  @retval EFI_DEVICE_ERROR      The device is not functioning properly and\r
+                                could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  )\r
+{\r
+  VIRTUAL_KEYBOARD_DEV                  *VirtualKeyboardPrivate;\r
+  EFI_STATUS                            Status;\r
+  EFI_TPL                               OldTpl;\r
+\r
+  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  Status = VirtualKeyboardPrivate->SimpleTextIn.Reset (\r
+                                     &VirtualKeyboardPrivate->SimpleTextIn,\r
+                                     ExtendedVerification\r
+                                     );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\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
+  @param  VirtualKeyboardPrivate   Virtualkeyboard driver private structure.\r
+  @param  KeyData                  A pointer to a buffer that is filled in\r
+                                   with the keystroke state data for the key\r
+                                   that was pressed.\r
+\r
+  @retval EFI_SUCCESS              The keystroke information was returned.\r
+  @retval EFI_NOT_READY            There was no keystroke data availiable.\r
+  @retval EFI_DEVICE_ERROR         The keystroke information was not returned\r
+                                   due to hardware errors.\r
+  @retval EFI_INVALID_PARAMETER    KeyData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+KeyboardReadKeyStrokeWorker (\r
+  IN VIRTUAL_KEYBOARD_DEV  *VirtualKeyboardPrivate,\r
+  OUT EFI_KEY_DATA      *KeyData\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_TPL                               OldTpl;\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Use TimerEvent callback function to check whether there's any key pressed\r
+  //\r
+\r
+  //\r
+  // Stall 1ms to give a chance to let other driver interrupt this routine for\r
+  // their timer event.\r
+  // e.g. OS loader, other drivers which are driven by timer event will have a\r
+  // bad performance during this period,\r
+  // e.g. usb keyboard driver.\r
+  // Add a stall period can greatly increate other driver performance during\r
+  // the WaitForKey is recursivly invoked. 1ms delay will make little impact\r
+  // to the thunk keyboard driver, and user can not feel the delay at all when\r
+  // input.\r
+  //\r
+  gBS->Stall (1000);\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate);\r
+  //\r
+  // If there's no key, just return\r
+  //\r
+  Status = CheckQueue (&VirtualKeyboardPrivate->Queue);\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->RestoreTPL (OldTpl);\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData);\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Read out the scan code of the key that has just been stroked.\r
+\r
+  @param  This        Pointer of simple text Protocol.\r
+  @param  Key         Pointer for store the key that read out.\r
+\r
+  @retval EFI_SUCCESS The key is read out successfully.\r
+  @retval other       The key reading failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReadKeyStroke (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
+  OUT EFI_INPUT_KEY                   *Key\r
+  )\r
+{\r
+  VIRTUAL_KEYBOARD_DEV     *VirtualKeyboardPrivate;\r
+  EFI_STATUS               Status;\r
+  EFI_KEY_DATA             KeyData;\r
+\r
+  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Convert the Ctrl+[a-z] to Ctrl+[1-26]\r
+  //\r
+  if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+    if (KeyData.Key.UnicodeChar >= L'a' &&\r
+        KeyData.Key.UnicodeChar <= L'z') {\r
+      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+    } else if (KeyData.Key.UnicodeChar >= L'A' &&\r
+               KeyData.Key.UnicodeChar <= L'Z') {\r
+      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+    }\r
+  }\r
+\r
+  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\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
+  @param  This         Protocol instance pointer.\r
+  @param  KeyData      A pointer to a buffer that is filled in with the\r
+                       keystroke state data for the key that was pressed.\r
+\r
+  @retval  EFI_SUCCESS           The keystroke information was returned.\r
+  @retval  EFI_NOT_READY         There was no keystroke data availiable.\r
+  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned\r
+                                 due to hardware errors.\r
+  @retval  EFI_INVALID_PARAMETER KeyData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  )\r
+{\r
+  VIRTUAL_KEYBOARD_DEV                  *VirtualKeyboardPrivate;\r
+\r
+  if (KeyData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, KeyData);\r
+\r
+}\r
+\r
+/**\r
+  Set certain state for the input device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
+                            state for the input device.\r
+\r
+  @retval EFI_SUCCESS           The device state was set successfully.\r
+  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and\r
+                                could not have the setting adjusted.\r
+  @retval EFI_UNSUPPORTED       The device does not have the ability to set\r
+                                its state.\r
+  @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  )\r
+{\r
+  if (KeyToggleState == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register a notification function for a particular keystroke for the\r
+  input device.\r
+\r
+  @param  This                    Protocol instance pointer.\r
+  @param  KeyData                 A pointer to a buffer that is filled in with\r
+                                  the keystroke information data for the key\r
+                                  that was pressed.\r
+  @param  KeyNotificationFunction Points to the function to be called when the\r
+                                  key sequence is typed specified by KeyData.\r
+  @param  NotifyHandle            Points to the unique handle assigned to the\r
+                                  registered notification.\r
+\r
+\r
+  @retval EFI_SUCCESS             The notification function was registered\r
+                                  successfully.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary\r
+                                  data structures.\r
+  @retval EFI_INVALID_PARAMETER   KeyData or NotifyHandle is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardRegisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_DATA                       *KeyData,\r
+  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
+  OUT VOID                              **NotifyHandle\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  VIRTUAL_KEYBOARD_DEV                  *VirtualKeyboardPrivate;\r
+  EFI_TPL                               OldTpl;\r
+  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+  LIST_ENTRY                            *Link;\r
+  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+  if (KeyData == NULL ||\r
+      NotifyHandle == NULL ||\r
+      KeyNotificationFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Enter critical section\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  //\r
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already\r
+  // registered.\r
+  //\r
+  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;\r
+       Link != &VirtualKeyboardPrivate->NotifyList;\r
+       Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                      NotifyEntry,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+        *NotifyHandle = CurrentNotify;\r
+        Status = EFI_SUCCESS;\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Allocate resource to save the notification function\r
+  //\r
+\r
+  NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
+  if (NewNotify == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  NewNotify->Signature         = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+  InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);\r
+\r
+  *NotifyHandle                = NewNotify;\r
+  Status                       = EFI_SUCCESS;\r
+\r
+Exit:\r
+  //\r
+  // Leave critical section and return\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Remove a registered notification function from a particular keystroke.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  NotificationHandle   The handle of the notification function\r
+                               being unregistered.\r
+\r
+  @retval EFI_SUCCESS             The notification function was unregistered\r
+                                  successfully.\r
+  @retval EFI_INVALID_PARAMETER   The NotificationHandle is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN VOID                               *NotificationHandle\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  VIRTUAL_KEYBOARD_DEV                  *VirtualKeyboardPrivate;\r
+  EFI_TPL                               OldTpl;\r
+  LIST_ENTRY                            *Link;\r
+  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+\r
+  //\r
+  // Check incoming notification handle\r
+  //\r
+  if (NotificationHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature !=\r
+      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Enter critical section\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;\r
+       Link != &VirtualKeyboardPrivate->NotifyList;\r
+       Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                      NotifyEntry,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (CurrentNotify == NotificationHandle) {\r
+      //\r
+      // Remove the notification function from NotifyList and free resources\r
+      //\r
+      RemoveEntryList (&CurrentNotify->NotifyEntry);\r
+\r
+      Status = EFI_SUCCESS;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Can not find the specified Notification Handle\r
+  //\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+Exit:\r
+  //\r
+  // Leave critical section and return\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Timer event handler: read a series of scancodes from 8042\r
+  and put them into memory scancode buffer.\r
+  it read as much scancodes to either fill\r
+  the memory buffer or empty the keyboard buffer.\r
+  It is registered as running under TPL_NOTIFY\r
+\r
+  @param Event       The timer event\r
+  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardTimerHandler (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_TPL                                OldTpl;\r
+  LIST_ENTRY                             *Link;\r
+  EFI_KEY_DATA                           KeyData;\r
+  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;\r
+  VIRTUAL_KEYBOARD_DEV                   *VirtualKeyboardPrivate;\r
+  VIRTUAL_KBD_KEY                        VirtualKey;\r
+\r
+  VirtualKeyboardPrivate = Context;\r
+\r
+  //\r
+  // Enter critical section\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  if (VirtualKeyboardPrivate->PlatformVirtual &&\r
+      VirtualKeyboardPrivate->PlatformVirtual->Query) {\r
+    if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) ==\r
+        FALSE) {\r
+      goto Exit;\r
+    }\r
+    // Found key\r
+    KeyData.Key.ScanCode = VirtualKey.Key.ScanCode;\r
+    KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar;\r
+    KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;\r
+    KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+    if (VirtualKeyboardPrivate->PlatformVirtual->Clear) {\r
+      VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey);\r
+    }\r
+  } else {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Signal KeyNotify process event if this key pressed matches any key registered.\r
+  //\r
+  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;\r
+       Link != &VirtualKeyboardPrivate->NotifyList;\r
+       Link = Link->ForwardLink) {\r
+    CurrentNotify = CR (\r
+                      Link,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                      NotifyEntry,\r
+                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                      );\r
+    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+      //\r
+      // The key notification function needs to run at TPL_CALLBACK\r
+      // while current TPL is TPL_NOTIFY. It will be invoked in\r
+      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
+      //\r
+      Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);\r
+      gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);\r
+    }\r
+  }\r
+\r
+  Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData);\r
+\r
+Exit:\r
+  //\r
+  // Leave critical section and return\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+}\r
+\r
+/**\r
+  Process key notify.\r
+\r
+  @param  Event                 Indicates the event that invoke this function.\r
+  @param  Context               Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+  IN  EFI_EVENT                 Event,\r
+  IN  VOID                      *Context\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  VIRTUAL_KEYBOARD_DEV                  *VirtualKeyboardPrivate;\r
+  EFI_KEY_DATA                          KeyData;\r
+  LIST_ENTRY                            *Link;\r
+  LIST_ENTRY                            *NotifyList;\r
+  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+  EFI_TPL                               OldTpl;\r
+\r
+  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context;\r
+\r
+  //\r
+  // Invoke notification functions.\r
+  //\r
+  NotifyList = &VirtualKeyboardPrivate->NotifyList;\r
+  while (TRUE) {\r
+    //\r
+    // Enter critical section\r
+    //\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);\r
+    //\r
+    // Leave critical section\r
+    //\r
+    gBS->RestoreTPL (OldTpl);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    for (Link = GetFirstNode (NotifyList);\r
+         !IsNull (NotifyList, Link);\r
+         Link = GetNextNode (NotifyList, Link)) {\r
+      CurrentNotify = CR (Link,\r
+                        VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                        NotifyEntry,\r
+                        VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                        );\r
+      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+        CurrentNotify->KeyNotificationFn (&KeyData);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  The user Entry Point for module VirtualKeyboard. The user code starts with\r
+  this function.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeVirtualKeyboard(\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Install driver model protocol(s).\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gVirtualKeyboardDriverBinding,\r
+             ImageHandle,\r
+             &gVirtualKeyboardComponentName,\r
+             &gVirtualKeyboardComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h
new file mode 100644 (file)
index 0000000..6dc8264
--- /dev/null
@@ -0,0 +1,544 @@
+/** @file\r
+\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions\r
+of the BSD License which accompanies this distribution.  The\r
+full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _VIRTUAL_KEYBOARD_H_\r
+#define _VIRTUAL_KEYBOARD_H_\r
+\r
+\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PlatformVirtualKeyboard.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+\r
+//\r
+// Driver Binding Externs\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL  gVirtualKeyboardDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;\r
+\r
+\r
+//\r
+// VIRTUAL Keyboard Defines\r
+//\r
+#define CHAR_SCANCODE                        0xe0\r
+#define CHAR_ESC                             0x1b\r
+\r
+#define KEYBOARD_TIMEOUT                     65536   // 0.07s\r
+#define KEYBOARD_WAITFORVALUE_TIMEOUT        1000000 // 1s\r
+#define KEYBOARD_BAT_TIMEOUT                 4000000 // 4s\r
+#define KEYBOARD_TIMER_INTERVAL              500000  // 0.5s\r
+\r
+#define QUEUE_MAX_COUNT                      32\r
+\r
+#define KEYBOARD_SCAN_CODE_MAX_COUNT         32\r
+\r
+//\r
+// VIRTUAL Keyboard Device Structure\r
+//\r
+#define VIRTUAL_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('V', 'K', 'B', 'D')\r
+#define VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('v', 'k', 'c', 'n')\r
+\r
+typedef struct _VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY {\r
+  UINTN                                      Signature;\r
+  EFI_KEY_DATA                               KeyData;\r
+  EFI_KEY_NOTIFY_FUNCTION                    KeyNotificationFn;\r
+  LIST_ENTRY                                 NotifyEntry;\r
+} VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY;\r
+\r
+typedef struct {\r
+  UINTN                                      Front;\r
+  UINTN                                      Rear;\r
+  EFI_KEY_DATA                               Buffer[QUEUE_MAX_COUNT];\r
+} SIMPLE_QUEUE;\r
+\r
+typedef struct {\r
+  UINT8                                      Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT];\r
+  UINTN                                      Head;\r
+  UINTN                                      Tail;\r
+} SCAN_CODE_QUEUE;\r
+\r
+typedef struct {\r
+  UINTN                                      Signature;\r
+  EFI_HANDLE                                 Handle;\r
+  PLATFORM_VIRTUAL_KBD_PROTOCOL              *PlatformVirtual;\r
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL             SimpleTextIn;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL          SimpleTextInputEx;\r
+\r
+  //\r
+  // Buffer storing EFI_KEY_DATA\r
+  //\r
+  SIMPLE_QUEUE                               Queue;\r
+  SIMPLE_QUEUE                               QueueForNotify;\r
+\r
+  //\r
+  // Notification Function List\r
+  //\r
+  LIST_ENTRY                                 NotifyList;\r
+  EFI_EVENT                                  KeyNotifyProcessEvent;\r
+  EFI_EVENT                                  TimerEvent;\r
+} VIRTUAL_KEYBOARD_DEV;\r
+\r
+#define VIRTUAL_KEYBOARD_DEV_FROM_THIS(a)  CR (a, VIRTUAL_KEYBOARD_DEV, SimpleTextIn, VIRTUAL_KEYBOARD_DEV_SIGNATURE)\r
+#define TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS(a) \\r
+  CR (a, \\r
+      VIRTUAL_KEYBOARD_DEV, \\r
+      SimpleTextInputEx, \\r
+      VIRTUAL_KEYBOARD_DEV_SIGNATURE \\r
+      )\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gVirtualKeyboardDriverBinding;\r
+\r
+//\r
+// Driver Binding Protocol functions\r
+//\r
+\r
+/**\r
+  Check whether the driver supports this device.\r
+\r
+  @param  This                   The Udriver binding protocol.\r
+  @param  Controller             The controller handle to check.\r
+  @param  RemainingDevicePath    The remaining device path.\r
+\r
+  @retval EFI_SUCCESS            The driver supports this controller.\r
+  @retval other                  This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starts the device with this driver.\r
+\r
+  @param  This                   The driver binding instance.\r
+  @param  Controller             Handle of device to bind driver to.\r
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
+                                 device to start.\r
+\r
+  @retval EFI_SUCCESS            The controller is controlled by the driver.\r
+  @retval Other                  This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop the device handled by this driver.\r
+\r
+  @param  This                   The driver binding protocol.\r
+  @param  Controller             The controller to release.\r
+  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.\r
+  @param  ChildHandleBuffer      The array of child handle.\r
+\r
+  @retval EFI_SUCCESS            The device was stopped.\r
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.\r
+  @retval Others                 Fail to uninstall protocols attached on the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  );\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER ControllerHandle is NULL.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PAVIRTUALETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL      *This,\r
+  IN  EFI_HANDLE                       ControllerHandle,\r
+  IN  EFI_HANDLE                       ChildHandle        OPTIONAL,\r
+  IN  CHAR8                            *Language,\r
+  OUT CHAR16                           **ControllerName\r
+  );\r
+\r
+\r
+//\r
+// Simple Text Input Protocol functions\r
+//\r
+/**\r
+  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.\r
+\r
+  @param  This                  Pointer of simple text Protocol.\r
+  @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
+\r
+  @retval EFI_SUCCESS           The command byte is written successfully.\r
+  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReset (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
+  IN  BOOLEAN                         ExtendedVerification\r
+  );\r
+\r
+/**\r
+  Reset the input device and optionaly run diagnostics\r
+\r
+  @param  This                  Protocol instance pointer.\r
+  @param  ExtendedVerification  Driver may perform diagnostics on reset.\r
+\r
+  @retval EFI_SUCCESS           The device was reset.\r
+  @retval EFI_DEVICE_ERROR      The device is not functioning properly and could\r
+                                not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardResetEx (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN BOOLEAN                            ExtendedVerification\r
+  );\r
+\r
+/**\r
+  Set certain state for the input device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
+                            state for the input device.\r
+\r
+  @retval EFI_SUCCESS           The device state was set successfully.\r
+  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could\r
+                                not have the setting adjusted.\r
+  @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.\r
+  @retval EFI_INVALID_PAVIRTUALETER KeyToggleState is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardSetState (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState\r
+  );\r
+\r
+/**\r
+  Register a notification function for a particular keystroke for the input device.\r
+\r
+  @param  This                    Protocol instance pointer.\r
+  @param  KeyData                 A pointer to a buffer that is filled in with the keystroke\r
+                                  information data for the key that was pressed.\r
+  @param  KeyNotificationFunction Points to the function to be called when the key\r
+                                  sequence is typed specified by KeyData.\r
+  @param  NotifyHandle            Points to the unique handle assigned to the registered notification.\r
+\r
+\r
+  @retval EFI_SUCCESS             The notification function was registered successfully.\r
+  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.\r
+  @retval EFI_INVALID_PAVIRTUALETER   KeyData or NotifyHandle is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardRegisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN EFI_KEY_DATA                       *KeyData,\r
+  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,\r
+  OUT VOID                              **NotifyHandle\r
+  );\r
+\r
+/**\r
+  Remove a registered notification function from a particular keystroke.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  NotificationHandle   The handle of the notification function being unregistered.\r
+\r
+  @retval EFI_SUCCESS             The notification function was unregistered successfully.\r
+  @retval EFI_INVALID_PAVIRTUALETER   The NotificationHandle is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardUnregisterKeyNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,\r
+  IN VOID                               *NotificationHandle\r
+  );\r
+\r
+//\r
+// Private worker functions\r
+//\r
+/**\r
+  Free keyboard notify list.\r
+\r
+  @param  ListHead   The list head\r
+\r
+  @retval EFI_SUCCESS           Free the notify list successfully\r
+  @retval EFI_INVALID_PAVIRTUALETER ListHead is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+VirtualKeyboardFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  );\r
+\r
+/**\r
+  Check if key is registered.\r
+\r
+  @param  RegsiteredData    A pointer to a buffer that is filled in with the keystroke\r
+                            state data for the key that was registered.\r
+  @param  InputData         A pointer to a buffer that is filled in with the keystroke\r
+                            state data for the key that was pressed.\r
+\r
+  @retval TRUE              Key be pressed matches a registered key.\r
+  @retval FLASE             Match failed.\r
+\r
+**/\r
+BOOLEAN\r
+IsKeyRegistered (\r
+  IN EFI_KEY_DATA  *RegsiteredData,\r
+  IN EFI_KEY_DATA  *InputData\r
+  );\r
+\r
+/**\r
+  Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+  @param  Event       The event that be siganlled when any key has been stroked.\r
+  @param  Context     Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardWaitForKey (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  );\r
+\r
+/**\r
+  Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
+\r
+  @param  Event    The event that be siganlled when any key has been stroked.\r
+  @param  Context  Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardWaitForKeyEx (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  );\r
+\r
+/**\r
+  Timer event handler: read a series of key stroke from 8042\r
+  and put them into memory key buffer.\r
+  It is registered as running under TPL_NOTIFY\r
+\r
+  @param  Event   The timer event\r
+  @param  Context A VIRTUAL_KEYBOARD_DEV pointer\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VirtualKeyboardTimerHandler (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  );\r
+\r
+/**\r
+  Process key notify.\r
+\r
+  @param  Event                 Indicates the event that invoke this function.\r
+  @param  Context               Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+  IN  EFI_EVENT                 Event,\r
+  IN  VOID                      *Context\r
+  );\r
+\r
+/**\r
+  Read out the scan code of the key that has just been stroked.\r
+\r
+  @param  This        Pointer of simple text Protocol.\r
+  @param  Key         Pointer for store the key that read out.\r
+\r
+  @retval EFI_SUCCESS The key is read out successfully.\r
+  @retval other       The key reading failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReadKeyStroke (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,\r
+  OUT EFI_INPUT_KEY                   *Key\r
+  );\r
+\r
+/**\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
+  @param  This         Protocol instance pointer.\r
+  @param  KeyData      A pointer to a buffer that is filled in with the keystroke\r
+                       state data for the key that was pressed.\r
+\r
+  @retval  EFI_SUCCESS           The keystroke information was returned.\r
+  @retval  EFI_NOT_READY         There was no keystroke data availiable.\r
+  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to\r
+                                 hardware errors.\r
+  @retval  EFI_INVALID_PAVIRTUALETER KeyData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtualKeyboardReadKeyStrokeEx (\r
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+  OUT EFI_KEY_DATA                      *KeyData\r
+  );\r
+\r
+#endif /* _VIRTUAL_KEYBOARD_H_ */\r
diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
new file mode 100644 (file)
index 0000000..d6bbf69
--- /dev/null
@@ -0,0 +1,60 @@
+## @file\r
+# Virtual Keyboard driver.\r
+#\r
+# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions\r
+# of the BSD License which accompanies this distribution.  The\r
+# full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010019\r
+  BASE_NAME                      = VirtualKeyboardDxe\r
+  FILE_GUID                      = 88079b18-b42b-44aa-a6f2-b83911075e89\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = InitializeVirtualKeyboard\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF ARM AARCH64\r
+#\r
+#  DRIVER_BINDING                = gVirtualKeyboardDriverBinding\r
+#  COMPONENT_NAME                = gVirtualKeyboardComponentName\r
+#\r
+\r
+[Sources.common]\r
+  ComponentName.c\r
+  VirtualKeyboard.c\r
+\r
+[Packages]\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  IoLib\r
+  ReportStatusCodeLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiLib\r
+\r
+[Protocols]\r
+  gEfiDriverBindingProtocolGuid\r
+  gEfiSimpleTextInProtocolGuid\r
+  gEfiSimpleTextInputExProtocolGuid\r
+  gPlatformVirtualKeyboardProtocolGuid\r
+\r
+[Depex]\r
+  TRUE\r
index c7b134dd34e6b02398987482a473b2e41a4c9e6f..179c1b16b28ed49dc68dda81b56f8ca5267ab187 100644 (file)
@@ -82,6 +82,7 @@
   gAndroidFastbootPlatformProtocolGuid =  { 0x524685a0, 0x89a0, 0x11e3, {0x9d, 0x4d, 0xbf, 0xa9, 0xf6, 0xa4, 0x03, 0x08}}\r
   gUsbDeviceProtocolGuid =  { 0x021bd2ca, 0x51d2, 0x11e3, {0x8e, 0x56, 0xb7, 0x54, 0x17, 0xc7,  0x0b, 0x44 }}\r
   gPlatformGpioProtocolGuid = { 0x52ce9845, 0x5af4, 0x43e2, {0xba, 0xfd, 0x23, 0x08, 0x12, 0x54, 0x7a, 0xc2 }}\r
+  gPlatformVirtualKeyboardProtocolGuid = { 0x0e3606d2, 0x1dc3, 0x4e6f, { 0xbe, 0x65, 0x39, 0x49, 0x82, 0xa2, 0x65, 0x47 }}\r
   gAndroidBootImgProtocolGuid = { 0x9859bb19, 0x407c, 0x4f8b, {0xbc, 0xe1, 0xf8, 0xda, 0x65, 0x65, 0xf4, 0xa5 }}\r
 \r
 [Ppis]\r
diff --git a/EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h b/EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h
new file mode 100644 (file)
index 0000000..c64d21e
--- /dev/null
@@ -0,0 +1,65 @@
+/** @file\r
+\r
+  Copyright (c) 2018, Linaro. All rights reserved.\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __PLATFORM_VIRTUAL_KEYBOARD_H__\r
+#define __PLATFORM_VIRTUAL_KEYBOARD_H__\r
+\r
+//\r
+// Protocol interface structure\r
+//\r
+typedef struct _PLATFORM_VIRTUAL_KBD_PROTOCOL  PLATFORM_VIRTUAL_KBD_PROTOCOL;\r
+\r
+typedef struct _VIRTUAL_KBD_KEY                VIRTUAL_KBD_KEY;\r
+\r
+#define VIRTUAL_KEYBOARD_KEY_SIGNATURE         SIGNATURE_32 ('v', 'k', 'b', 'd')\r
+\r
+struct _VIRTUAL_KBD_KEY {\r
+  UINTN                    Signature;\r
+  EFI_INPUT_KEY            Key;\r
+};\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PLATFORM_VIRTUAL_KBD_REGISTER) (\r
+  IN VOID\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PLATFORM_VIRTUAL_KBD_RESET) (\r
+  IN VOID\r
+  );\r
+\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *PLATFORM_VIRTUAL_KBD_QUERY) (\r
+  IN VIRTUAL_KBD_KEY                           *VirtualKey\r
+  );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PLATFORM_VIRTUAL_KBD_CLEAR) (\r
+  IN VIRTUAL_KBD_KEY                           *VirtualKey\r
+  );\r
+\r
+struct _PLATFORM_VIRTUAL_KBD_PROTOCOL {\r
+  PLATFORM_VIRTUAL_KBD_REGISTER                Register;\r
+  PLATFORM_VIRTUAL_KBD_RESET                   Reset;\r
+  PLATFORM_VIRTUAL_KBD_QUERY                   Query;\r
+  PLATFORM_VIRTUAL_KBD_CLEAR                   Clear;\r
+};\r
+\r
+extern EFI_GUID gPlatformVirtualKeyboardProtocolGuid;\r
+\r
+#endif /* __PLATFORM_VIRTUAL_KEYBOARD_H__ */\r