diff mbox series

[edk2] EmbeddedPkg/Drivers: add virtual keyboard driver

Message ID 1519635156-21954-1-git-send-email-haojian.zhuang@linaro.org
State Accepted
Commit 1df5fb2d83d9eca2d3b4b87fab7a0ec9f288cb6f
Headers show
Series [edk2] EmbeddedPkg/Drivers: add virtual keyboard driver | expand

Commit Message

Haojian Zhuang Feb. 26, 2018, 8:52 a.m. UTC
The virtual keyboard could simulate a keyboard. User could simulate
a key value when pattern is matched.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

---
 .../Drivers/VirtualKeyboardDxe/ComponentName.c     |  184 ++++
 .../Drivers/VirtualKeyboardDxe/ComponentName.h     |  154 +++
 .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.c   | 1117 ++++++++++++++++++++
 .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.h   |  544 ++++++++++
 .../VirtualKeyboardDxe/VirtualKeyboardDxe.dec      |   39 +
 .../VirtualKeyboardDxe/VirtualKeyboardDxe.inf      |   61 ++
 .../Include/Protocol/PlatformVirtualKeyboard.h     |   65 ++
 7 files changed, 2164 insertions(+)
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec
 create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
 create mode 100644 EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm Feb. 27, 2018, 12:28 p.m. UTC | #1
On Mon, Feb 26, 2018 at 04:52:36PM +0800, Haojian Zhuang wrote:
> The virtual keyboard could simulate a keyboard. User could simulate

> a key value when pattern is matched.


How? This is over 2000 lines of new code, please give a little bit
more description of what it does and how it is intended to be used.

(It sounds like is could be a useful feature, but I can only find out
what it is intended to do by reading the code, which isn't what review
is supposed to be.)

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

> ---

>  .../Drivers/VirtualKeyboardDxe/ComponentName.c     |  184 ++++

>  .../Drivers/VirtualKeyboardDxe/ComponentName.h     |  154 +++

>  .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.c   | 1117 ++++++++++++++++++++

>  .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.h   |  544 ++++++++++

>  .../VirtualKeyboardDxe/VirtualKeyboardDxe.dec      |   39 +

>  .../VirtualKeyboardDxe/VirtualKeyboardDxe.inf      |   61 ++

>  .../Include/Protocol/PlatformVirtualKeyboard.h     |   65 ++


Please generate patches with
--stat=1000 --stat-graph-width=20 
and
--subject-prefix="PATCH edk2-platforms"

(In general following the guide at)
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers

>  7 files changed, 2164 insertions(+)

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

>  create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

>  create mode 100644 EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h

> 

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

> new file mode 100644

> index 0000000..2935307

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

> @@ -0,0 +1,184 @@

> +/** @file

> +

> +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

> +

> +This program and the accompanying materials

> +are licensed and made available under the terms and conditions

> +of the BSD License which accompanies this distribution.  The

> +full text of the license may be found at

> +http://opensource.org/licenses/bsd-license.php

> +

> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#include "VirtualKeyboard.h"

> +

> +//

> +// EFI Component Name Protocol

> +//

> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName = {

> +  VirtualKeyboardComponentNameGetDriverName,

> +  VirtualKeyboardComponentNameGetControllerName,

> +  "eng"

> +};

> +

> +//

> +// EFI Component Name 2 Protocol

> +//

> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = {

> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName,

> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName,

> +  "en"

> +};

> +

> +

> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {

> +  {

> +    "eng;en",

> +    L"RAM Keyboard Driver"


What is a RAM Keyboard Driver?

> +  },


Any chance of a "zh-chs" entry?

> +  {

> +    NULL,

> +    NULL

> +  }

> +};

> +

> +/**

> +  Retrieves a Unicode string that is the user readable name of the driver.

> +

> +  This function retrieves the user readable name of a driver in the form of a

> +  Unicode string. If the driver specified by This has a user readable name in

> +  the language specified by Language, then a pointer to the driver name is

> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified

> +  by This does not support the language specified by Language,

> +  then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language. This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified

> +                                in RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  DriverName[out]       A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                driver specified by This in the language

> +                                specified by Language.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by

> +                                This and the language specified by Language was

> +                                returned in DriverName.

> +

> +  @retval EFI_INVALID_PARAMETER Language is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetDriverName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

> +  IN  CHAR8                        *Language,

> +  OUT CHAR16                       **DriverName

> +  )

> +{

> +  return LookupUnicodeString2 (

> +           Language,

> +           This->SupportedLanguages,

> +           mVirtualKeyboardDriverNameTable,

> +           DriverName,

> +           (BOOLEAN)(This == &gVirtualKeyboardComponentName)

> +           );

> +}

> +

> +/**

> +  Retrieves a Unicode string that is the user readable name of the controller

> +  that is being managed by a driver.

> +

> +  This function retrieves the user readable name of the controller specified by

> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the

> +  driver specified by This has a user readable name in the language specified by

> +  Language, then a pointer to the controller name is returned in ControllerName,

> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently

> +  managing the controller specified by ControllerHandle and ChildHandle,

> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not

> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  ControllerHandle[in]  The handle of a controller that the driver

> +                                specified by This is managing.  This handle

> +                                specifies the controller whose name is to be

> +                                returned.

> +

> +  @param  ChildHandle[in]       The handle of the child controller to retrieve

> +                                the name of.  This is an optional parameter that

> +                                may be NULL.  It will be NULL for device

> +                                drivers.  It will also be NULL for a bus drivers

> +                                that wish to retrieve the name of the bus

> +                                controller.  It will not be NULL for a bus

> +                                driver that wishes to retrieve the name of a

> +                                child controller.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language.  This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified in

> +                                RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  ControllerName[out]   A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                controller specified by ControllerHandle and

> +                                ChildHandle in the language specified by

> +                                Language from the point of view of the driver

> +                                specified by This.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in

> +                                the language specified by Language for the

> +                                driver specified by This was returned in

> +                                DriverName.

> +

> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid

> +                                EFI_HANDLE.

> +

> +  @retval EFI_INVALID_PARAMETER Language is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

> +                                managing the controller specified by

> +                                ControllerHandle and ChildHandle.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetControllerName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,

> +  IN  EFI_HANDLE                                      ControllerHandle,

> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,

> +  IN  CHAR8                                           *Language,

> +  OUT CHAR16                                          **ControllerName

> +  )

> +{

> +  return EFI_UNSUPPORTED;

> +}

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h

> new file mode 100644

> index 0000000..94bef28

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h

> @@ -0,0 +1,154 @@

> +/** @file

> +

> +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

> +

> +This program and the accompanying materials

> +are licensed and made available under the terms and conditions

> +of the BSD License which accompanies this distribution.  The

> +full text of the license may be found at

> +http://opensource.org/licenses/bsd-license.php

> +

> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#ifndef _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_

> +#define _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_

> +

> +

> +extern EFI_COMPONENT_NAME_PROTOCOL   gVirtualKeyboardComponentName;

> +extern EFI_COMPONENT_NAME2_PROTOCOL  gVirtualKeyboardComponentName2;

> +

> +//

> +// EFI Component Name Functions

> +//

> +/**

> +  Retrieves a Unicode string that is the user readable name of the driver.

> +

> +  This function retrieves the user readable name of a driver in the form of a

> +  Unicode string. If the driver specified by This has a user readable name in

> +  the language specified by Language, then a pointer to the driver name is

> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified

> +  by This does not support the language specified by Language,

> +  then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language. This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified

> +                                in RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  DriverName[out]       A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                driver specified by This in the language

> +                                specified by Language.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by

> +                                This and the language specified by Language was

> +                                returned in DriverName.

> +

> +  @retval EFI_INVALID_PARAMETER Language is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetDriverName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

> +  IN  CHAR8                        *Language,

> +  OUT CHAR16                       **DriverName

> +  );

> +

> +

> +/**

> +  Retrieves a Unicode string that is the user readable name of the controller

> +  that is being managed by a driver.

> +

> +  This function retrieves the user readable name of the controller specified by

> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the

> +  driver specified by This has a user readable name in the language specified by

> +  Language, then a pointer to the controller name is returned in ControllerName,

> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently

> +  managing the controller specified by ControllerHandle and ChildHandle,

> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not

> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  ControllerHandle[in]  The handle of a controller that the driver

> +                                specified by This is managing.  This handle

> +                                specifies the controller whose name is to be

> +                                returned.

> +

> +  @param  ChildHandle[in]       The handle of the child controller to retrieve

> +                                the name of.  This is an optional parameter that

> +                                may be NULL.  It will be NULL for device

> +                                drivers.  It will also be NULL for a bus drivers

> +                                that wish to retrieve the name of the bus

> +                                controller.  It will not be NULL for a bus

> +                                driver that wishes to retrieve the name of a

> +                                child controller.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language.  This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified in

> +                                RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  ControllerName[out]   A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                controller specified by ControllerHandle and

> +                                ChildHandle in the language specified by

> +                                Language from the point of view of the driver

> +                                specified by This.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in

> +                                the language specified by Language for the

> +                                driver specified by This was returned in

> +                                DriverName.

> +

> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid

> +                                EFI_HANDLE.

> +

> +  @retval EFI_INVALID_PARAMETER Language is NULL.

> +

> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

> +                                managing the controller specified by

> +                                ControllerHandle and ChildHandle.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetControllerName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,

> +  IN  EFI_HANDLE                                      ControllerHandle,

> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,

> +  IN  CHAR8                                           *Language,

> +  OUT CHAR16                                          **ControllerName

> +  );

> +

> +

> +#endif

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c

> new file mode 100644

> index 0000000..b2c84ba

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c

> @@ -0,0 +1,1117 @@

> +/** @file

> +  VirtualKeyboard driver

> +

> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

> +

> +This program and the accompanying materials

> +are licensed and made available under the terms and conditions

> +of the BSD License which accompanies this distribution.  The

> +full text of the license may be found at

> +http://opensource.org/licenses/bsd-license.php

> +

> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#include "VirtualKeyboard.h"

> +

> +//

> +// RAM Keyboard Driver Binding Protocol Instance

> +//

> +EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {

> +  VirtualKeyboardDriverBindingSupported,

> +  VirtualKeyboardDriverBindingStart,

> +  VirtualKeyboardDriverBindingStop,

> +  0x10,

> +  NULL,

> +  NULL

> +};

> +

> +//

> +// EFI Driver Binding Protocol Functions

> +//

> +

> +/**

> +  Check whether the driver supports this device.

> +

> +  @param  This                   The Udriver binding protocol.

> +  @param  Controller             The controller handle to check.

> +  @param  RemainingDevicePath    The remaining device path.

> +

> +  @retval EFI_SUCCESS            The driver supports this controller.

> +  @retval other                  This device isn't supported.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingSupported (

> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN EFI_HANDLE                   Controller,

> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

> +  )

> +{

> +  EFI_STATUS                     Status;

> +  PLATFORM_VIRTUAL_KBD_PROTOCOL  *PlatformVirtual;

> +

> +  Status = gBS->OpenProtocol (

> +                  Controller,

> +                  &gPlatformVirtualKeyboardProtocolGuid,

> +                  (VOID **) &PlatformVirtual,

> +                  This->DriverBindingHandle,

> +                  Controller,

> +                  EFI_OPEN_PROTOCOL_BY_DRIVER

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +  gBS->CloseProtocol (

> +         Controller,

> +         &gPlatformVirtualKeyboardProtocolGuid,

> +         This->DriverBindingHandle,

> +         Controller

> +         );

> +  return Status;

> +}

> +

> +/**

> +  Starts the device with this driver.

> +

> +  @param  This                   The driver binding instance.

> +  @param  Controller             Handle of device to bind driver to.

> +  @param  RemainingDevicePath    Optional parameter use to pick a specific child

> +                                 device to start.

> +

> +  @retval EFI_SUCCESS            The controller is controlled by the driver.

> +  @retval Other                  This controller cannot be started.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingStart (

> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN EFI_HANDLE                   Controller,

> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

> +  )

> +{

> +  EFI_STATUS                                Status;

> +  VIRTUAL_KEYBOARD_DEV                      *VirtualKeyboardPrivate;

> +  PLATFORM_VIRTUAL_KBD_PROTOCOL             *PlatformVirtual;

> +

> +  Status = gBS->OpenProtocol (

> +                  Controller,

> +                  &gPlatformVirtualKeyboardProtocolGuid,

> +                  (VOID **) &PlatformVirtual,

> +                  This->DriverBindingHandle,

> +                  Controller,

> +                  EFI_OPEN_PROTOCOL_BY_DRIVER

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +

> +  //

> +  // Allocate the private device structure

> +  //

> +  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV));

> +  if (NULL == VirtualKeyboardPrivate) {


No jeopardy-comparisons please. if (VirtualKeyboardPrivate == NULL) {

> +    Status = EFI_OUT_OF_RESOURCES;

> +    goto Done;

> +  }

> +

> +  //

> +  // Initialize the private device structure

> +  //

> +  VirtualKeyboardPrivate->Signature                  = VIRTUAL_KEYBOARD_DEV_SIGNATURE;

> +  VirtualKeyboardPrivate->Handle                     = Controller;

> +  VirtualKeyboardPrivate->PlatformVirtual            = PlatformVirtual;

> +  VirtualKeyboardPrivate->Queue.Front                = 0;

> +  VirtualKeyboardPrivate->Queue.Rear                 = 0;

> +  VirtualKeyboardPrivate->QueueForNotify.Front       = 0;

> +  VirtualKeyboardPrivate->QueueForNotify.Rear        = 0;

> +

> +  VirtualKeyboardPrivate->SimpleTextIn.Reset         = VirtualKeyboardReset;

> +  VirtualKeyboardPrivate->SimpleTextIn.ReadKeyStroke = VirtualKeyboardReadKeyStroke;

> +

> +  VirtualKeyboardPrivate->SimpleTextInputEx.Reset               = VirtualKeyboardResetEx;

> +  VirtualKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx     = VirtualKeyboardReadKeyStrokeEx;

> +  VirtualKeyboardPrivate->SimpleTextInputEx.SetState            = VirtualKeyboardSetState;

> +

> +  VirtualKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify   = VirtualKeyboardRegisterKeyNotify;

> +  VirtualKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = VirtualKeyboardUnregisterKeyNotify;

> +  InitializeListHead (&VirtualKeyboardPrivate->NotifyList);

> +

> +  Status = PlatformVirtual->Register ();

> +  if (EFI_ERROR (Status)) {

> +    goto Done;

> +  }

> +

> +  //

> +  // Report that the keyboard is being enabled

> +  //

> +  REPORT_STATUS_CODE (

> +    EFI_PROGRESS_CODE,

> +    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE

> +    );

> +

> +  //

> +  // Setup the WaitForKey event

> +  //

> +  Status = gBS->CreateEvent (

> +                  EVT_NOTIFY_WAIT,

> +                  TPL_NOTIFY,

> +                  VirtualKeyboardWaitForKey,

> +                  &(VirtualKeyboardPrivate->SimpleTextIn),

> +                  &((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey)

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    (VirtualKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;

> +    goto Done;

> +  }

> +  Status = gBS->CreateEvent (

> +                  EVT_NOTIFY_WAIT,

> +                  TPL_NOTIFY,

> +                  VirtualKeyboardWaitForKeyEx,

> +                  &(VirtualKeyboardPrivate->SimpleTextInputEx),

> +                  &(VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;

> +    goto Done;

> +  }

> +

> +  //

> +  // Setup a periodic timer, used for reading keystrokes at a fixed interval

> +  //

> +  Status = gBS->CreateEvent (

> +                  EVT_TIMER | EVT_NOTIFY_SIGNAL,

> +                  TPL_NOTIFY,

> +                  VirtualKeyboardTimerHandler,

> +                  VirtualKeyboardPrivate,

> +                  &VirtualKeyboardPrivate->TimerEvent

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    Status      = EFI_OUT_OF_RESOURCES;


The whitespace before = does not look quite right.
Please address throughout.

> +    goto Done;

> +  }

> +

> +  Status = gBS->SetTimer (

> +                  VirtualKeyboardPrivate->TimerEvent,

> +                  TimerPeriodic,

> +                  KEYBOARD_TIMER_INTERVAL

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    Status      = EFI_OUT_OF_RESOURCES;

> +    goto Done;

> +  }

> +

> +  Status = gBS->CreateEvent (

> +                  EVT_NOTIFY_SIGNAL,

> +                  TPL_CALLBACK,

> +                  KeyNotifyProcessHandler,

> +                  VirtualKeyboardPrivate,

> +                  &VirtualKeyboardPrivate->KeyNotifyProcessEvent

> +                  );

> +  if (EFI_ERROR (Status)) {

> +    Status      = EFI_OUT_OF_RESOURCES;

> +    goto Done;

> +  }

> +

> +  //

> +  // Reset the keyboard device

> +  //

> +  Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset (

> +                                                    &VirtualKeyboardPrivate->SimpleTextInputEx,


Funky indentation.
According to coding style, it's missing 3 spaces.

> +                                                    FALSE

> +                                                    );

> +  if (EFI_ERROR (Status)) {

> +    DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));


Use DEBUG_ERROR (PatchCheck.py warns about this).

> +    goto Done;

> +  }

> +  //

> +  // Install protocol interfaces for the keyboard device.

> +  //

> +  Status = gBS->InstallMultipleProtocolInterfaces (

> +                  &Controller,

> +                  &gEfiSimpleTextInProtocolGuid,

> +                  &VirtualKeyboardPrivate->SimpleTextIn,

> +                  &gEfiSimpleTextInputExProtocolGuid,

> +                  &VirtualKeyboardPrivate->SimpleTextInputEx,

> +                  NULL

> +                  );

> +

> +Done:

> +  if (EFI_ERROR (Status)) {

> +    if (VirtualKeyboardPrivate != NULL) {

> +      if ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {

> +        gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey);

> +      }

> +

> +      if ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {

> +        gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx);

> +      }

> +

> +      if (VirtualKeyboardPrivate->KeyNotifyProcessEvent != NULL) {

> +        gBS->CloseEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);

> +      }

> +

> +      VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList);

> +

> +      if (VirtualKeyboardPrivate->TimerEvent != NULL) {

> +        gBS->CloseEvent (VirtualKeyboardPrivate->TimerEvent);

> +      }

> +      FreePool (VirtualKeyboardPrivate);

> +    }

> +  }

> +

> +  gBS->CloseProtocol (

> +         Controller,

> +         &gPlatformVirtualKeyboardProtocolGuid,

> +         This->DriverBindingHandle,

> +         Controller

> +         );

> +

> +  return Status;

> +}

> +

> +/**

> +  Stop the device handled by this driver.

> +

> +  @param  This                   The driver binding protocol.

> +  @param  Controller             The controller to release.

> +  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.

> +  @param  ChildHandleBuffer      The array of child handle.

> +

> +  @retval EFI_SUCCESS            The device was stopped.

> +  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.

> +  @retval Others                 Fail to uninstall protocols attached on the device.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingStop (

> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN  EFI_HANDLE                   Controller,

> +  IN  UINTN                        NumberOfChildren,

> +  IN  EFI_HANDLE                   *ChildHandleBuffer

> +  )

> +{

> +  return EFI_SUCCESS;

> +}

> +

> +

> +/**

> +  Enqueue the key.

> +

> +  @param  Queue                 The queue to be enqueued.

> +  @param  KeyData               The key data to be enqueued.

> +

> +  @retval EFI_NOT_READY         The queue is full.

> +  @retval EFI_SUCCESS           Successfully enqueued the key data.

> +

> +**/

> +EFI_STATUS

> +Enqueue (

> +  IN SIMPLE_QUEUE         *Queue,

> +  IN EFI_KEY_DATA         *KeyData

> +  )

> +{

> +  if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {

> +    return EFI_NOT_READY;

> +  }

> +

> +  CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));

> +  Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Dequeue the key.

> +

> +  @param  Queue                 The queue to be dequeued.

> +  @param  KeyData               The key data to be dequeued.

> +

> +  @retval EFI_NOT_READY         The queue is empty.

> +  @retval EFI_SUCCESS           Successfully dequeued the key data.

> +

> +**/

> +EFI_STATUS

> +Dequeue (

> +  IN SIMPLE_QUEUE         *Queue,

> +  IN EFI_KEY_DATA         *KeyData

> +  )

> +{

> +  if (Queue->Front == Queue->Rear) {

> +    return EFI_NOT_READY;

> +  }

> +

> +  CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));

> +  Queue->Front  = (Queue->Front + 1) % QUEUE_MAX_COUNT;

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Check whether the queue is empty.

> +

> +  @param  Queue                 The queue to be checked.

> +

> +  @retval EFI_NOT_READY         The queue is empty.

> +  @retval EFI_SUCCESS           The queue is not empty.

> +

> +**/

> +EFI_STATUS

> +CheckQueue (

> +  IN SIMPLE_QUEUE         *Queue

> +  )

> +{

> +  if (Queue->Front == Queue->Rear) {

> +    return EFI_NOT_READY;

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Check key buffer to get the key stroke status.

> +

> +  @param  This         Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.

> +

> +  @retval EFI_SUCCESS  A key is being pressed now.

> +  @retval Other        No key is now pressed.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardCheckForKey (

> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This

> +  )

> +{

> +  VIRTUAL_KEYBOARD_DEV     *VirtualKeyboardPrivate;

> +

> +  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  return CheckQueue (&VirtualKeyboardPrivate->Queue);

> +}

> +

> +/**

> +  Free keyboard notify list.

> +

> +  @param  ListHead   The list head

> +

> +  @retval EFI_SUCCESS           Free the notify list successfully

> +  @retval EFI_INVALID_PARAMETER ListHead is invalid.

> +

> +**/

> +EFI_STATUS

> +VirtualKeyboardFreeNotifyList (

> +  IN OUT LIST_ENTRY           *ListHead

> +  )

> +{

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;

> +

> +  if (ListHead == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +  while (!IsListEmpty (ListHead)) {

> +    NotifyNode = CR (

> +                   ListHead->ForwardLink,

> +                   VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

> +                   NotifyEntry,

> +                   VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

> +                   );

> +    RemoveEntryList (ListHead->ForwardLink);

> +    gBS->FreePool (NotifyNode);

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Judge whether is a registed key

> +

> +  @param RegsiteredData       A pointer to a buffer that is filled in with the keystroke

> +                              state data for the key that was registered.

> +  @param InputData            A pointer to a buffer that is filled in with the keystroke

> +                              state data for the key that was pressed.

> +

> +  @retval TRUE                Key be pressed matches a registered key.

> +  @retval FLASE               Match failed.

> +

> +**/

> +BOOLEAN

> +IsKeyRegistered (

> +  IN EFI_KEY_DATA  *RegsiteredData,

> +  IN EFI_KEY_DATA  *InputData

> +  )

> +

> +{

> +  ASSERT (RegsiteredData != NULL && InputData != NULL);

> +

> +  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||

> +      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {

> +    return FALSE;

> +  }

> +

> +  //

> +  // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.

> +  //

> +  if (RegsiteredData->KeyState.KeyShiftState != 0 &&

> +      RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {

> +    return FALSE;

> +  }

> +  if (RegsiteredData->KeyState.KeyToggleState != 0 &&

> +      RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {

> +    return FALSE;

> +  }

> +

> +  return TRUE;

> +

> +}

> +

> +/**

> +  Event notification function for SIMPLE_TEXT_IN.WaitForKey event

> +  Signal the event if there is key available

> +

> +  @param Event    the event object

> +  @param Context  waitting context

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardWaitForKey (

> +  IN  EFI_EVENT               Event,

> +  IN  VOID                    *Context

> +  )

> +{

> +  //

> +  // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.

> +  // Csm will be used to check whether there is a key pending, but the csm will disable all


Well, this makes it clear this driver is based on
IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/.
I cannot really comment on whether that was the best starting point,
but please delete all and any references to CSM and eficompatibility -
these are fundamentally irrelevant for any non-x86 platforms.

> +  // interrupt before switch to compatibility16, which mean all the efiCompatibility timer

> +  // event will stop work during the compatibility16. And If a caller recursivly invoke this function,

> +  // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,

> +  // e.g. usb keyboard driver.

> +  // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.

> +  // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.

> +  //

> +  gBS->Stall (1000);

> +  //

> +  // Use TimerEvent callback function to check whether there's any key pressed

> +  //

> +  VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context));

> +

> +  if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) {

> +    gBS->SignalEvent (Event);

> +  }

> +}

> +

> +/**

> +  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event

> +  Signal the event if there is key available

> +

> +  @param Event    event object

> +  @param Context  waiting context

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardWaitForKeyEx (

> +  IN  EFI_EVENT               Event,

> +  IN  VOID                    *Context

> +  )

> +

> +{

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> +

> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context);

> +  VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn);

> +

> +}

> +

> +//

> +// EFI Simple Text In Protocol Functions

> +//

> +/**

> +  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.


There are a few really long lines in this patch. Please try to keep
to no more than 80 characters were feasible. Applies throughout.

> +

> +  @param  This                  Pointer of simple text Protocol.

> +  @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.

> +

> +  @retval EFI_SUCCESS           The command byte is written successfully.

> +  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReset (

> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

> +  IN  BOOLEAN                         ExtendedVerification

> +  )

> +{

> +  VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;

> +  EFI_STATUS           Status;

> +  EFI_TPL              OldTpl;

> +

> +  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  //

> +  // Raise TPL to avoid mouse operation impact

> +  //

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  if (VirtualKeyboardPrivate->PlatformVirtual && VirtualKeyboardPrivate->PlatformVirtual->Reset) {


  if (VirtualKeyboardPrivate->PlatformVirtual &&
      VirtualKeyboardPrivate->PlatformVirtual->Reset) {

And so on.

> +    Status = VirtualKeyboardPrivate->PlatformVirtual->Reset ();

> +  } else {

> +    Status = EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // resume priority of task level

> +  //

> +  gBS->RestoreTPL (OldTpl);

> +

> +  return Status;

> +}

> +

> +/**

> +  Reset the input device and optionaly run diagnostics

> +

> +  @param  This                  Protocol instance pointer.

> +  @param  ExtendedVerification  Driver may perform diagnostics on reset.

> +

> +  @retval EFI_SUCCESS           The device was reset.

> +  @retval EFI_DEVICE_ERROR      The device is not functioning properly and could-

> +                                not be reset.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardResetEx (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN BOOLEAN                            ExtendedVerification

> +  )

> +{

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;


Spacing does not match subsequent lines.

> +  EFI_STATUS                            Status;

> +  EFI_TPL                               OldTpl;

> +

> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  Status = VirtualKeyboardPrivate->SimpleTextIn.Reset (

> +                                               &VirtualKeyboardPrivate->SimpleTextIn,


Funky indentation.

> +                                               ExtendedVerification

> +                                               );

> +  if (EFI_ERROR (Status)) {

> +    return EFI_DEVICE_ERROR;

> +  }

> +

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  gBS->RestoreTPL (OldTpl);

> +

> +  return EFI_SUCCESS;

> +

> +}

> +

> +/**

> +  Reads the next keystroke from the input device. The WaitForKey Event can

> +  be used to test for existance of a keystroke via WaitForEvent () call.

> +

> +  @param  VirtualKeyboardPrivate   Virtualkeyboard driver private structure.

> +  @param  KeyData               A pointer to a buffer that is filled in with the keystroke

> +                                state data for the key that was pressed.

> +

> +  @retval EFI_SUCCESS           The keystroke information was returned.

> +  @retval EFI_NOT_READY         There was no keystroke data availiable.

> +  @retval EFI_DEVICE_ERROR      The keystroke information was not returned due to

> +                                hardware errors.

> +  @retval EFI_INVALID_PARAMETER KeyData is NULL.

> +

> +**/

> +EFI_STATUS

> +KeyboardReadKeyStrokeWorker (

> +  IN VIRTUAL_KEYBOARD_DEV  *VirtualKeyboardPrivate,

> +  OUT EFI_KEY_DATA      *KeyData

> +  )

> +{

> +  EFI_STATUS                            Status;

> +  EFI_TPL                               OldTpl;

> +  if (KeyData == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // Use TimerEvent callback function to check whether there's any key pressed

> +  //

> +

> +  //

> +  // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.

> +  // Csm will be used to check whether there is a key pending, but the csm will disable all

> +  // interrupt before switch to compatibility16, which mean all the efiCompatibility timer

> +  // event will stop work during the compatibility16. And If a caller recursivly invoke this function,

> +  // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,

> +  // e.g. usb keyboard driver.

> +  // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.

> +  // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.

> +  //

> +  gBS->Stall (1000);

> +

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate);

> +  //

> +  // If there's no key, just return

> +  //

> +  Status = CheckQueue (&VirtualKeyboardPrivate->Queue);

> +  if (EFI_ERROR (Status)) {

> +    gBS->RestoreTPL (OldTpl);

> +    return EFI_NOT_READY;

> +  }

> +

> +  Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData);

> +

> +  gBS->RestoreTPL (OldTpl);

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Read out the scan code of the key that has just been stroked.

> +

> +  @param  This        Pointer of simple text Protocol.

> +  @param  Key         Pointer for store the key that read out.

> +

> +  @retval EFI_SUCCESS The key is read out successfully.

> +  @retval other       The key reading failed.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReadKeyStroke (

> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

> +  OUT EFI_INPUT_KEY                   *Key

> +  )

> +{

> +  VIRTUAL_KEYBOARD_DEV     *VirtualKeyboardPrivate;

> +  EFI_STATUS            Status;

> +  EFI_KEY_DATA          KeyData;

> +

> +  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData);

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +

> +  //

> +  // Convert the Ctrl+[a-z] to Ctrl+[1-26]

> +  //

> +  if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {

> +    if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {

> +      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);

> +    } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {

> +      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);

> +    }

> +  }

> +

> +  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));

> +

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Reads the next keystroke from the input device. The WaitForKey Event can

> +  be used to test for existance of a keystroke via WaitForEvent () call.

> +

> +  @param  This         Protocol instance pointer.

> +  @param  KeyData      A pointer to a buffer that is filled in with the keystroke

> +                       state data for the key that was pressed.

> +

> +  @retval  EFI_SUCCESS           The keystroke information was returned.

> +  @retval  EFI_NOT_READY         There was no keystroke data availiable.

> +  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to

> +                                 hardware errors.

> +  @retval  EFI_INVALID_PARAMETER KeyData is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReadKeyStrokeEx (

> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

> +  OUT EFI_KEY_DATA                      *KeyData

> +  )

> +{

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> +

> +  if (KeyData == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, KeyData);

> +

> +}

> +

> +/**

> +  Set certain state for the input device.

> +

> +  @param  This              Protocol instance pointer.

> +  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the-

> +                            state for the input device.

> +

> +  @retval EFI_SUCCESS           The device state was set successfully.

> +  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could-

> +                                not have the setting adjusted.

> +  @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.

> +  @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardSetState (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState

> +  )

> +{

> +  if (KeyToggleState == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // Thunk keyboard driver doesn't support partial keystroke.

> +  //

> +  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||

> +      (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED

> +      ) {

> +    return EFI_UNSUPPORTED;

> +  }

> +


This function has no side effects, and it's an emulated keyboard (how
could a partial keystroke happen?). Why does it do anything other than
return SUCCESS?

> +  return EFI_SUCCESS;

> +}

> +

> +/**

> +  Register a notification function for a particular keystroke for the input device.

> +

> +  @param  This                    Protocol instance pointer.

> +  @param  KeyData                 A pointer to a buffer that is filled in with the keystroke

> +                                  information data for the key that was pressed.

> +  @param  KeyNotificationFunction Points to the function to be called when the key

> +                                  sequence is typed specified by KeyData.

> +  @param  NotifyHandle            Points to the unique handle assigned to the registered notification.

> +

> +

> +  @retval EFI_SUCCESS             The notification function was registered successfully.

> +  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.

> +  @retval EFI_INVALID_PARAMETER   KeyData or NotifyHandle is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardRegisterKeyNotify (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN EFI_KEY_DATA                       *KeyData,

> +  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,

> +  OUT VOID                              **NotifyHandle

> +  )

> +{

> +  EFI_STATUS                            Status;

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> +  EFI_TPL                               OldTpl;

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *NewNotify;

> +  LIST_ENTRY                            *Link;

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

> +

> +  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  //

> +  // Enter critical section

> +  //

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  //

> +  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.

> +  //

> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

> +    CurrentNotify = CR (

> +                      Link,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

> +                      NotifyEntry,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

> +                      );

> +    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {

> +      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {

> +        *NotifyHandle = CurrentNotify;

> +        Status = EFI_SUCCESS;

> +        goto Exit;

> +      }

> +    }

> +  }

> +

> +  //

> +  // Allocate resource to save the notification function

> +  //

> +

> +  NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY));

> +  if (NewNotify == NULL) {

> +    Status = EFI_OUT_OF_RESOURCES;

> +    goto Exit;

> +  }

> +

> +  NewNotify->Signature         = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;

> +  NewNotify->KeyNotificationFn = KeyNotificationFunction;

> +  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));

> +  InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);

> +

> +  *NotifyHandle                = NewNotify;

> +  Status                       = EFI_SUCCESS;

> +

> +Exit:

> +  //

> +  // Leave critical section and return

> +  //

> +  gBS->RestoreTPL (OldTpl);

> +  return Status;

> +

> +}

> +

> +/**

> +  Remove a registered notification function from a particular keystroke.

> +

> +  @param  This                 Protocol instance pointer.

> +  @param  NotificationHandle   The handle of the notification function being unregistered.

> +

> +  @retval EFI_SUCCESS             The notification function was unregistered successfully.

> +  @retval EFI_INVALID_PARAMETER   The NotificationHandle is invalid.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardUnregisterKeyNotify (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN VOID                               *NotificationHandle

> +  )

> +{

> +  EFI_STATUS                            Status;

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> +  EFI_TPL                               OldTpl;

> +  LIST_ENTRY                            *Link;

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

> +

> +  //

> +  // Check incoming notification handle

> +  //

> +  if (NotificationHandle == NULL) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

> +

> +  //

> +  // Enter critical section

> +  //

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

> +    CurrentNotify = CR (

> +                      Link,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

> +                      NotifyEntry,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

> +                      );

> +    if (CurrentNotify == NotificationHandle) {

> +      //

> +      // Remove the notification function from NotifyList and free resources

> +      //

> +      RemoveEntryList (&CurrentNotify->NotifyEntry);

> +

> +      Status = EFI_SUCCESS;

> +      goto Exit;

> +    }

> +  }

> +

> +  //

> +  // Can not find the specified Notification Handle

> +  //

> +  Status = EFI_INVALID_PARAMETER;

> +

> +Exit:

> +  //

> +  // Leave critical section and return

> +  //

> +  gBS->RestoreTPL (OldTpl);

> +  return Status;

> +}

> +

> +/**

> +  Timer event handler: read a series of scancodes from 8042

> +  and put them into memory scancode buffer.

> +  it read as much scancodes to either fill

> +  the memory buffer or empty the keyboard buffer.

> +  It is registered as running under TPL_NOTIFY

> +

> +  @param Event       The timer event

> +  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardTimerHandler (

> +  IN EFI_EVENT    Event,

> +  IN VOID         *Context

> +  )

> +{

> +  EFI_TPL                            OldTpl;

> +  LIST_ENTRY                         *Link;

> +  EFI_KEY_DATA                       KeyData;


Please make these variable names line up with the ones below.

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;

> +  VIRTUAL_KEYBOARD_DEV                   *VirtualKeyboardPrivate;

> +  VIRTUAL_KBD_KEY                        VirtualKey;

> +

> +  VirtualKeyboardPrivate = Context;

> +

> +  //

> +  // Enter critical section

> +  //

> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +

> +  if (VirtualKeyboardPrivate->PlatformVirtual &&

> +      VirtualKeyboardPrivate->PlatformVirtual->Query) {

> +    if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) == FALSE) {

> +      goto Exit;

> +    }

> +    // Found key

> +    KeyData.Key.ScanCode = VirtualKey.Key.ScanCode;

> +    KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar;

> +    KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;

> +    KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;

> +    if (VirtualKeyboardPrivate->PlatformVirtual->Clear) {

> +      VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey);

> +    }

> +  } else {

> +    goto Exit;

> +  }

> +

> +  //

> +  // Signal KeyNotify process event if this key pressed matches any key registered.

> +  //

> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

> +    CurrentNotify = CR (

> +                      Link,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

> +                      NotifyEntry,

> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

> +                      );

> +    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

> +      //

> +      // The key notification function needs to run at TPL_CALLBACK

> +      // while current TPL is TPL_NOTIFY. It will be invoked in

> +      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.

> +      //

> +      Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);

> +      gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);

> +    }

> +  }

> +

> +  Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData);

> +

> +Exit:

> +  //

> +  // Leave critical section and return

> +  //

> +  gBS->RestoreTPL (OldTpl);

> +}

> +

> +/**

> +  Process key notify.

> +

> +  @param  Event                 Indicates the event that invoke this function.

> +  @param  Context               Indicates the calling context.

> +**/

> +VOID

> +EFIAPI

> +KeyNotifyProcessHandler (

> +  IN  EFI_EVENT                 Event,

> +  IN  VOID                      *Context

> +  )

> +{

> +  EFI_STATUS                            Status;

> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> +  EFI_KEY_DATA                          KeyData;

> +  LIST_ENTRY                            *Link;

> +  LIST_ENTRY                            *NotifyList;

> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

> +  EFI_TPL                               OldTpl;


Please make variable names line up.

> +

> +  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context;

> +

> +  //

> +  // Invoke notification functions.

> +  //

> +  NotifyList = &VirtualKeyboardPrivate->NotifyList;

> +  while (TRUE) {

> +    //

> +    // Enter critical section

> +    //

> +    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

> +    Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);

> +    //

> +    // Leave critical section

> +    //

> +    gBS->RestoreTPL (OldTpl);

> +    if (EFI_ERROR (Status)) {

> +      break;

> +    }

> +    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {

> +      CurrentNotify = CR (Link, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);

> +      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

> +        CurrentNotify->KeyNotificationFn (&KeyData);

> +      }

> +    }

> +  }

> +}

> +

> +/**

> +  The user Entry Point for module VirtualKeyboard. The user code starts with this function.

> +

> +  @param[in] ImageHandle    The firmware allocated handle for the EFI image.

> +  @param[in] SystemTable    A pointer to the EFI System Table.

> +

> +  @retval EFI_SUCCESS       The entry point is executed successfully.

> +  @retval other             Some error occurs when executing this entry point.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +InitializeVirtualKeyboard(

> +  IN EFI_HANDLE           ImageHandle,

> +  IN EFI_SYSTEM_TABLE     *SystemTable

> +  )

> +{

> +  EFI_STATUS              Status;

> +

> +  //

> +  // Install driver model protocol(s).

> +  //

> +  Status = EfiLibInstallDriverBindingComponentName2 (

> +             ImageHandle,

> +             SystemTable,

> +             &gVirtualKeyboardDriverBinding,

> +             ImageHandle,

> +             &gVirtualKeyboardComponentName,

> +             &gVirtualKeyboardComponentName2

> +             );

> +  ASSERT_EFI_ERROR (Status);

> +

> +  return Status;

> +}

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

> new file mode 100644

> index 0000000..c8e256d

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

> @@ -0,0 +1,544 @@

> +/** @file

> +

> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

> +

> +This program and the accompanying materials

> +are licensed and made available under the terms and conditions

> +of the BSD License which accompanies this distribution.  The

> +full text of the license may be found at

> +http://opensource.org/licenses/bsd-license.php

> +

> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#ifndef _VIRTUAL_KEYBOARD_H_

> +#define _VIRTUAL_KEYBOARD_H_

> +

> +

> +#include <Guid/StatusCodeDataTypeId.h>

> +#include <Protocol/DevicePath.h>

> +#include <Protocol/PlatformVirtualKeyboard.h>

> +#include <Protocol/SimpleTextIn.h>

> +#include <Protocol/SimpleTextInEx.h>

> +

> +#include <Library/BaseLib.h>

> +#include <Library/BaseMemoryLib.h>

> +#include <Library/DebugLib.h>

> +#include <Library/MemoryAllocationLib.h>

> +#include <Library/IoLib.h>

> +#include <Library/PcdLib.h>

> +#include <Library/ReportStatusCodeLib.h>

> +#include <Library/UefiBootServicesTableLib.h>

> +#include <Library/UefiDriverEntryPoint.h>

> +#include <Library/UefiLib.h>

> +

> +//

> +// Driver Binding Externs

> +//

> +extern EFI_DRIVER_BINDING_PROTOCOL  gVirtualKeyboardDriverBinding;

> +extern EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName;

> +extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;

> +

> +

> +//

> +// VIRTUAL Keyboard Defines

> +//

> +#define CHAR_SCANCODE                        0xe0

> +#define CHAR_ESC                             0x1b

> +

> +#define KEYBOARD_TIMEOUT                     65536   // 0.07s

> +#define KEYBOARD_WAITFORVALUE_TIMEOUT        1000000 // 1s

> +#define KEYBOARD_BAT_TIMEOUT                 4000000 // 4s

> +#define KEYBOARD_TIMER_INTERVAL              500000  // 0.5s

> +

> +#define QUEUE_MAX_COUNT                      32

> +

> +#define KEYBOARD_SCAN_CODE_MAX_COUNT         32

> +

> +//

> +// VIRTUAL Keyboard Device Structure

> +//

> +#define VIRTUAL_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('V', 'K', 'B', 'D')

> +#define VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('v', 'k', 'c', 'n')

> +

> +typedef struct _VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY {

> +  UINTN                                      Signature;

> +  EFI_KEY_DATA                               KeyData;

> +  EFI_KEY_NOTIFY_FUNCTION                    KeyNotificationFn;

> +  LIST_ENTRY                                 NotifyEntry;

> +} VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY;

> +

> +typedef struct {

> +  UINTN                                      Front;

> +  UINTN                                      Rear;

> +  EFI_KEY_DATA                               Buffer[QUEUE_MAX_COUNT];

> +} SIMPLE_QUEUE;

> +

> +typedef struct {

> +  UINT8                                      Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT];

> +  UINTN                                      Head;

> +  UINTN                                      Tail;

> +} SCAN_CODE_QUEUE;

> +

> +typedef struct {

> +  UINTN                                      Signature;

> +  EFI_HANDLE                                 Handle;

> +  PLATFORM_VIRTUAL_KBD_PROTOCOL              *PlatformVirtual;

> +  EFI_SIMPLE_TEXT_INPUT_PROTOCOL             SimpleTextIn;

> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL          SimpleTextInputEx;

> +

> +  //

> +  // Buffer storing EFI_KEY_DATA

> +  //

> +  SIMPLE_QUEUE                               Queue;

> +  SIMPLE_QUEUE                               QueueForNotify;

> +

> +  //

> +  // Notification Function List

> +  //

> +  LIST_ENTRY                                 NotifyList;

> +  EFI_EVENT                                  KeyNotifyProcessEvent;

> +  EFI_EVENT                                  TimerEvent;

> +} VIRTUAL_KEYBOARD_DEV;

> +

> +#define VIRTUAL_KEYBOARD_DEV_FROM_THIS(a)  CR (a, VIRTUAL_KEYBOARD_DEV, SimpleTextIn, VIRTUAL_KEYBOARD_DEV_SIGNATURE)

> +#define TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS(a) \

> +  CR (a, \

> +      VIRTUAL_KEYBOARD_DEV, \

> +      SimpleTextInputEx, \

> +      VIRTUAL_KEYBOARD_DEV_SIGNATURE \

> +      )

> +

> +//

> +// Global Variables

> +//

> +extern EFI_DRIVER_BINDING_PROTOCOL   gVirtualKeyboardDriverBinding;

> +

> +//

> +// Driver Binding Protocol functions

> +//

> +

> +/**

> +  Check whether the driver supports this device.

> +

> +  @param  This                   The Udriver binding protocol.

> +  @param  Controller             The controller handle to check.

> +  @param  RemainingDevicePath    The remaining device path.

> +

> +  @retval EFI_SUCCESS            The driver supports this controller.

> +  @retval other                  This device isn't supported.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingSupported (

> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN EFI_HANDLE                   Controller,

> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

> +  );

> +

> +/**

> +  Starts the device with this driver.

> +

> +  @param  This                   The driver binding instance.

> +  @param  Controller             Handle of device to bind driver to.

> +  @param  RemainingDevicePath    Optional parameter use to pick a specific child

> +                                 device to start.

> +

> +  @retval EFI_SUCCESS            The controller is controlled by the driver.

> +  @retval Other                  This controller cannot be started.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingStart (

> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN EFI_HANDLE                   Controller,

> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

> +  );

> +

> +/**

> +  Stop the device handled by this driver.

> +

> +  @param  This                   The driver binding protocol.

> +  @param  Controller             The controller to release.

> +  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.

> +  @param  ChildHandleBuffer      The array of child handle.

> +

> +  @retval EFI_SUCCESS            The device was stopped.

> +  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.

> +  @retval Others                 Fail to uninstall protocols attached on the device.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardDriverBindingStop (

> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,

> +  IN  EFI_HANDLE                   Controller,

> +  IN  UINTN                        NumberOfChildren,

> +  IN  EFI_HANDLE                   *ChildHandleBuffer

> +  );

> +

> +/**

> +  Retrieves a Unicode string that is the user readable name of the driver.

> +

> +  This function retrieves the user readable name of a driver in the form of a

> +  Unicode string. If the driver specified by This has a user readable name in

> +  the language specified by Language, then a pointer to the driver name is

> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified

> +  by This does not support the language specified by Language,

> +  then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language. This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified

> +                                in RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  DriverName[out]       A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                driver specified by This in the language

> +                                specified by Language.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by

> +                                This and the language specified by Language was

> +                                returned in DriverName.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER DriverName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetDriverName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

> +  IN  CHAR8                        *Language,

> +  OUT CHAR16                       **DriverName

> +  );

> +

> +

> +/**

> +  Retrieves a Unicode string that is the user readable name of the controller

> +  that is being managed by a driver.

> +

> +  This function retrieves the user readable name of the controller specified by

> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the

> +  driver specified by This has a user readable name in the language specified by

> +  Language, then a pointer to the controller name is returned in ControllerName,

> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently

> +  managing the controller specified by ControllerHandle and ChildHandle,

> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not

> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.

> +

> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

> +

> +  @param  ControllerHandle[in]  The handle of a controller that the driver

> +                                specified by This is managing.  This handle

> +                                specifies the controller whose name is to be

> +                                returned.

> +

> +  @param  ChildHandle[in]       The handle of the child controller to retrieve

> +                                the name of.  This is an optional parameter that

> +                                may be NULL.  It will be NULL for device

> +                                drivers.  It will also be NULL for a bus drivers

> +                                that wish to retrieve the name of the bus

> +                                controller.  It will not be NULL for a bus

> +                                driver that wishes to retrieve the name of a

> +                                child controller.

> +

> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

> +                                array indicating the language.  This is the

> +                                language of the driver name that the caller is

> +                                requesting, and it must match one of the

> +                                languages specified in SupportedLanguages. The

> +                                number of languages supported by a driver is up

> +                                to the driver writer. Language is specified in

> +                                RFC 4646 or ISO 639-2 language code format.

> +

> +  @param  ControllerName[out]   A pointer to the Unicode string to return.

> +                                This Unicode string is the name of the

> +                                controller specified by ControllerHandle and

> +                                ChildHandle in the language specified by

> +                                Language from the point of view of the driver

> +                                specified by This.

> +

> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in

> +                                the language specified by Language for the

> +                                driver specified by This was returned in

> +                                DriverName.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER ControllerHandle is NULL.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER ChildHandle is not NULL and it is not a valid

> +                                EFI_HANDLE.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.

> +

> +  @retval EFI_INVALID_PAVIRTUALETER ControllerName is NULL.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

> +                                managing the controller specified by

> +                                ControllerHandle and ChildHandle.

> +

> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

> +                                the language specified by Language.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardComponentNameGetControllerName (

> +  IN  EFI_COMPONENT_NAME_PROTOCOL      *This,

> +  IN  EFI_HANDLE                       ControllerHandle,

> +  IN  EFI_HANDLE                       ChildHandle        OPTIONAL,

> +  IN  CHAR8                            *Language,

> +  OUT CHAR16                           **ControllerName

> +  );

> +

> +

> +//

> +// Simple Text Input Protocol functions

> +//

> +/**

> +  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.

> +

> +  @param  This                  Pointer of simple text Protocol.

> +  @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.

> +

> +  @retval EFI_SUCCESS           The command byte is written successfully.

> +  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReset (

> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

> +  IN  BOOLEAN                         ExtendedVerification

> +  );

> +

> +/**

> +  Reset the input device and optionaly run diagnostics

> +

> +  @param  This                  Protocol instance pointer.

> +  @param  ExtendedVerification  Driver may perform diagnostics on reset.

> +

> +  @retval EFI_SUCCESS           The device was reset.

> +  @retval EFI_DEVICE_ERROR      The device is not functioning properly and could 


Trailing whitespace. (PatchCheck.py warns about this.)

> +                                not be reset.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardResetEx (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN BOOLEAN                            ExtendedVerification

> +  );

> +

> +/**

> +  Set certain state for the input device.

> +

> +  @param  This              Protocol instance pointer.

> +  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the

> +                            state for the input device.

> +

> +  @retval EFI_SUCCESS           The device state was set successfully.

> +  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could

> +                                not have the setting adjusted.

> +  @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.

> +  @retval EFI_INVALID_PAVIRTUALETER KeyToggleState is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardSetState (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState

> +  );

> +

> +/**

> +  Register a notification function for a particular keystroke for the input device.

> +

> +  @param  This                    Protocol instance pointer.

> +  @param  KeyData                 A pointer to a buffer that is filled in with the keystroke

> +                                  information data for the key that was pressed.

> +  @param  KeyNotificationFunction Points to the function to be called when the key

> +                                  sequence is typed specified by KeyData.

> +  @param  NotifyHandle            Points to the unique handle assigned to the registered notification.

> +

> +

> +  @retval EFI_SUCCESS             The notification function was registered successfully.

> +  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.

> +  @retval EFI_INVALID_PAVIRTUALETER   KeyData or NotifyHandle is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardRegisterKeyNotify (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN EFI_KEY_DATA                       *KeyData,

> +  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,

> +  OUT VOID                              **NotifyHandle

> +  );

> +

> +/**

> +  Remove a registered notification function from a particular keystroke.

> +

> +  @param  This                 Protocol instance pointer.

> +  @param  NotificationHandle   The handle of the notification function being unregistered.

> +

> +  @retval EFI_SUCCESS             The notification function was unregistered successfully.

> +  @retval EFI_INVALID_PAVIRTUALETER   The NotificationHandle is invalid.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardUnregisterKeyNotify (

> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

> +  IN VOID                               *NotificationHandle

> +  );

> +

> +//

> +// Private worker functions

> +//

> +/**

> +  Free keyboard notify list.

> +

> +  @param  ListHead   The list head

> +

> +  @retval EFI_SUCCESS           Free the notify list successfully

> +  @retval EFI_INVALID_PAVIRTUALETER ListHead is invalid.

> +

> +**/

> +EFI_STATUS

> +VirtualKeyboardFreeNotifyList (

> +  IN OUT LIST_ENTRY           *ListHead

> +  );

> +

> +/**

> +  Check if key is registered.

> +

> +  @param  RegsiteredData    A pointer to a buffer that is filled in with the keystroke

> +                            state data for the key that was registered.

> +  @param  InputData         A pointer to a buffer that is filled in with the keystroke

> +                            state data for the key that was pressed.

> +

> +  @retval TRUE              Key be pressed matches a registered key.

> +  @retval FLASE             Match failed.

> +

> +**/

> +BOOLEAN

> +IsKeyRegistered (

> +  IN EFI_KEY_DATA  *RegsiteredData,

> +  IN EFI_KEY_DATA  *InputData

> +  );

> +

> +/**

> +  Waiting on the keyboard event, if there's any key pressed by the user, signal the event

> +

> +  @param  Event       The event that be siganlled when any key has been stroked.

> +  @param  Context     Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardWaitForKey (

> +  IN  EFI_EVENT  Event,

> +  IN  VOID       *Context

> +  );

> +

> +/**

> +  Waiting on the keyboard event, if there's any key pressed by the user, signal the event

> +

> +  @param  Event    The event that be siganlled when any key has been stroked.

> +  @param  Context  Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardWaitForKeyEx (

> +  IN  EFI_EVENT  Event,

> +  IN  VOID       *Context

> +  );

> +

> +/**

> +  Timer event handler: read a series of key stroke from 8042

> +  and put them into memory key buffer.

> +  It is registered as running under TPL_NOTIFY

> +

> +  @param  Event   The timer event

> +  @param  Context A VIRTUAL_KEYBOARD_DEV pointer

> +

> +**/

> +VOID

> +EFIAPI

> +VirtualKeyboardTimerHandler (

> +  IN EFI_EVENT    Event,

> +  IN VOID         *Context

> +  );

> +

> +/**

> +  Process key notify.

> +

> +  @param  Event                 Indicates the event that invoke this function.

> +  @param  Context               Indicates the calling context.

> +**/

> +VOID

> +EFIAPI

> +KeyNotifyProcessHandler (

> +  IN  EFI_EVENT                 Event,

> +  IN  VOID                      *Context

> +  );

> +

> +/**

> +  Read out the scan code of the key that has just been stroked.

> +

> +  @param  This        Pointer of simple text Protocol.

> +  @param  Key         Pointer for store the key that read out.

> +

> +  @retval EFI_SUCCESS The key is read out successfully.

> +  @retval other       The key reading failed.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReadKeyStroke (

> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

> +  OUT EFI_INPUT_KEY                   *Key

> +  );

> +

> +/**

> +  Reads the next keystroke from the input device. The WaitForKey Event can

> +  be used to test for existance of a keystroke via WaitForEvent () call.

> +

> +  @param  This         Protocol instance pointer.

> +  @param  KeyData      A pointer to a buffer that is filled in with the keystroke

> +                       state data for the key that was pressed.

> +

> +  @retval  EFI_SUCCESS           The keystroke information was returned.

> +  @retval  EFI_NOT_READY         There was no keystroke data availiable.

> +  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to

> +                                 hardware errors.

> +  @retval  EFI_INVALID_PAVIRTUALETER KeyData is NULL.

> +

> +**/

> +EFI_STATUS

> +EFIAPI

> +VirtualKeyboardReadKeyStrokeEx (

> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

> +  OUT EFI_KEY_DATA                      *KeyData

> +  );

> +

> +#endif /* _VIRTUAL_KEYBOARD_H_ */

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

> new file mode 100644

> index 0000000..065f4f2

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec


Could you add the two guids to EmbeddededPkg instead?
Or just gPlatformVirtualKeyboardProtocolGuid, I don't see any use of
gVirtualKeyboardDxeTokenSpaceGuid.

> @@ -0,0 +1,39 @@

> +#/** @file

> +# Framework Module Development Environment Industry Standards

> +#

> +# This Package provides headers and libraries that conform to EFI/PI Industry standards.

> +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>

> +# Copyright (c) 2018, Linaro. All rights reserved.<BR>

> +#

> +#    This program and the accompanying materials are licensed and made available under

> +#    the terms and conditions of the BSD License which accompanies this distribution.

> +#    The full text of the license may be found at

> +#    http://opensource.org/licenses/bsd-license.php

> +#

> +#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +#

> +#**/

> +

> +[Defines]

> +  DEC_SPECIFICATION              = 0x00010019

> +  PACKAGE_NAME                   = VirtualKeyboardDxePkg

> +  PACKAGE_GUID                   = 774326bc-20d0-4203-97e4-10dc17f7dc1a

> +  PACKAGE_VERSION                = 0.1

> +

> +################################################################################

> +#

> +# Include Section - list of Include Paths that are provided by this package.

> +#                   Comments are used for Keywords and Module Types.

> +#

> +# Supported Module Types:

> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION

> +#

> +################################################################################

> +

> +[Guids.common]

> +  gVirtualKeyboardDxeTokenSpaceGuid    = { 0x80caf901, 0x0cf6, 0x4c09, { 0x89, 0x84, 0x61, 0xd1, 0xf3, 0xd2, 0x54, 0x39 }}

> +

> +[Protocols.common]

> +  gPlatformVirtualKeyboardProtocolGuid = { 0x0e3606d2, 0x1dc3, 0x4e6f, { 0xbe, 0x65, 0x39, 0x49, 0x82, 0xa2, 0x65, 0x47 }}

> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

> new file mode 100644

> index 0000000..a7e5bd0

> --- /dev/null

> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

> @@ -0,0 +1,61 @@

> +## @file

> +# Virtual Keyboard driver.

> +#

> +# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

> +#

> +# This program and the accompanying materials

> +# are licensed and made available under the terms and conditions

> +# of the BSD License which accompanies this distribution.  The

> +# full text of the license may be found at

> +# http://opensource.org/licenses/bsd-license.php

> +#

> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +#

> +##

> +

> +[Defines]

> +  INF_VERSION                    = 0x00010019

> +  BASE_NAME                      = VirtualKeyboardDxe

> +  FILE_GUID                      = 88079b18-b42b-44aa-a6f2-b83911075e89

> +  MODULE_TYPE                    = UEFI_DRIVER

> +  VERSION_STRING                 = 1.0

> +  ENTRY_POINT                    = InitializeVirtualKeyboard

> +

> +#

> +# The following information is for reference only and not required by the build tools.

> +#

> +#  VALID_ARCHITECTURES           = AARCH64


Well, it's emulated, so I would hope it's valid for all architectures?

/
    Leif

> +#

> +#  DRIVER_BINDING                = gVirtualKeyboardDriverBinding

> +#  COMPONENT_NAME                = gVirtualKeyboardComponentName

> +#

> +

> +[Sources.common]

> +  ComponentName.c

> +  VirtualKeyboard.c

> +

> +[Packages]

> +  EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

> +  EmbeddedPkg/EmbeddedPkg.dec

> +  MdePkg/MdePkg.dec

> +  MdeModulePkg/MdeModulePkg.dec

> +

> +[LibraryClasses]

> +  BaseLib

> +  BaseMemoryLib

> +  DebugLib

> +  IoLib

> +  ReportStatusCodeLib

> +  UefiDriverEntryPoint

> +  UefiBootServicesTableLib

> +  UefiLib

> +

> +[Protocols]

> +  gEfiDriverBindingProtocolGuid

> +  gEfiSimpleTextInProtocolGuid

> +  gEfiSimpleTextInputExProtocolGuid

> +  gPlatformVirtualKeyboardProtocolGuid

> +

> +[Depex]

> +  TRUE

> diff --git a/EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h b/EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h

> new file mode 100644

> index 0000000..bea3128

> --- /dev/null

> +++ b/EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h

> @@ -0,0 +1,65 @@

> +/** @file

> +

> +  Copyright (c) 2018, Linaro. All rights reserved.

> +

> +  This program and the accompanying materials

> +  are licensed and made available under the terms and conditions of the BSD License

> +  which accompanies this distribution.  The full text of the license may be found at

> +  http://opensource.org/licenses/bsd-license.php

> +

> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#ifndef __PLATFORM_VIRTUAL_KEYBOARD_H__

> +#define __PLATFORM_VIRTUAL_KEYBOARD_H__

> +

> +//

> +// Protocol interface structure

> +//

> +typedef struct _PLATFORM_VIRTUAL_KBD_PROTOCOL  PLATFORM_VIRTUAL_KBD_PROTOCOL;

> +

> +typedef struct _VIRTUAL_KBD_KEY                VIRTUAL_KBD_KEY;

> +

> +#define VIRTUAL_KEYBOARD_KEY_SIGNATURE         SIGNATURE_32 ('v', 'k', 'b', 'd')

> +

> +struct _VIRTUAL_KBD_KEY {

> +  UINTN                    Signature;

> +  EFI_INPUT_KEY            Key;

> +};

> +

> +typedef

> +EFI_STATUS

> +(EFIAPI *PLATFORM_VIRTUAL_KBD_REGISTER) (

> +  IN VOID

> +  );

> +

> +typedef

> +EFI_STATUS

> +(EFIAPI *PLATFORM_VIRTUAL_KBD_RESET) (

> +  IN VOID

> +  );

> +

> +typedef

> +BOOLEAN

> +(EFIAPI *PLATFORM_VIRTUAL_KBD_QUERY) (

> +  IN VIRTUAL_KBD_KEY                           *VirtualKey

> +  );

> +

> +typedef

> +EFI_STATUS

> +(EFIAPI *PLATFORM_VIRTUAL_KBD_CLEAR) (

> +  IN VIRTUAL_KBD_KEY                           *VirtualKey

> +  );

> +

> +struct _PLATFORM_VIRTUAL_KBD_PROTOCOL {

> +  PLATFORM_VIRTUAL_KBD_REGISTER                Register;

> +  PLATFORM_VIRTUAL_KBD_RESET                   Reset;

> +  PLATFORM_VIRTUAL_KBD_QUERY                   Query;

> +  PLATFORM_VIRTUAL_KBD_CLEAR                   Clear;

> +};

> +

> +extern EFI_GUID gPlatformVirtualKeyboardProtocolGuid;

> +

> +#endif /* __PLATFORM_VIRTUAL_KEYBOARD_H__ */

> -- 

> 2.7.4

> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Haojian Zhuang Feb. 28, 2018, 1:03 a.m. UTC | #2
On 02/27/2018 08:28 PM, Leif Lindholm wrote:
> On Mon, Feb 26, 2018 at 04:52:36PM +0800, Haojian Zhuang wrote:

>> The virtual keyboard could simulate a keyboard. User could simulate

>> a key value when pattern is matched.

> 

> How? This is over 2000 lines of new code, please give a little bit

> more description of what it does and how it is intended to be used.

> 

> (It sounds like is could be a useful feature, but I can only find out

> what it is intended to do by reading the code, which isn't what review

> is supposed to be.)


OK. I'll append more comments in it.

> 

>> Contributed-under: TianoCore Contribution Agreement 1.1

>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

>> ---

>>   .../Drivers/VirtualKeyboardDxe/ComponentName.c     |  184 ++++

>>   .../Drivers/VirtualKeyboardDxe/ComponentName.h     |  154 +++

>>   .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.c   | 1117 ++++++++++++++++++++

>>   .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.h   |  544 ++++++++++

>>   .../VirtualKeyboardDxe/VirtualKeyboardDxe.dec      |   39 +

>>   .../VirtualKeyboardDxe/VirtualKeyboardDxe.inf      |   61 ++

>>   .../Include/Protocol/PlatformVirtualKeyboard.h     |   65 ++

> 

> Please generate patches with

> --stat=1000 --stat-graph-width=20

> and

> --subject-prefix="PATCH edk2-platforms"

> 

> (In general following the guide at)

> https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers


OK. I'll follow it.

> 

>>   7 files changed, 2164 insertions(+)

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

>>   create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

>>   create mode 100644 EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h

>>

>> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

>> new file mode 100644

>> index 0000000..2935307

>> --- /dev/null

>> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c

>> @@ -0,0 +1,184 @@

>> +/** @file

>> +

>> +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

>> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

>> +

>> +This program and the accompanying materials

>> +are licensed and made available under the terms and conditions

>> +of the BSD License which accompanies this distribution.  The

>> +full text of the license may be found at

>> +http://opensource.org/licenses/bsd-license.php

>> +

>> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

>> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

>> +

>> +**/

>> +

>> +#include "VirtualKeyboard.h"

>> +

>> +//

>> +// EFI Component Name Protocol

>> +//

>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName = {

>> +  VirtualKeyboardComponentNameGetDriverName,

>> +  VirtualKeyboardComponentNameGetControllerName,

>> +  "eng"

>> +};

>> +

>> +//

>> +// EFI Component Name 2 Protocol

>> +//

>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = {

>> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName,

>> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName,

>> +  "en"

>> +};

>> +

>> +

>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {

>> +  {

>> +    "eng;en",

>> +    L"RAM Keyboard Driver"

> 

> What is a RAM Keyboard Driver?

> 


Oh, I'll rename it to Virtual Keyboard Driver for consistent.

>> +  },

> 

> Any chance of a "zh-chs" entry?

> 


Thanks. "zh-chs" may be inconvenient for others. "eng;en" is good for 
everyone.


>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardDriverBindingStart (

>> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

>> +  IN EFI_HANDLE                   Controller,

>> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

>> +  )

>> +{

>> +  EFI_STATUS                                Status;

>> +  VIRTUAL_KEYBOARD_DEV                      *VirtualKeyboardPrivate;

>> +  PLATFORM_VIRTUAL_KBD_PROTOCOL             *PlatformVirtual;

>> +

>> +  Status = gBS->OpenProtocol (

>> +                  Controller,

>> +                  &gPlatformVirtualKeyboardProtocolGuid,

>> +                  (VOID **) &PlatformVirtual,

>> +                  This->DriverBindingHandle,

>> +                  Controller,

>> +                  EFI_OPEN_PROTOCOL_BY_DRIVER

>> +                  );

>> +  if (EFI_ERROR (Status)) {

>> +    return Status;

>> +  }

>> +

>> +  //

>> +  // Allocate the private device structure

>> +  //

>> +  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV));

>> +  if (NULL == VirtualKeyboardPrivate) {

> 

> No jeopardy-comparisons please. if (VirtualKeyboardPrivate == NULL) {

> 


OK

>> +  //

>> +  // Setup a periodic timer, used for reading keystrokes at a fixed interval

>> +  //

>> +  Status = gBS->CreateEvent (

>> +                  EVT_TIMER | EVT_NOTIFY_SIGNAL,

>> +                  TPL_NOTIFY,

>> +                  VirtualKeyboardTimerHandler,

>> +                  VirtualKeyboardPrivate,

>> +                  &VirtualKeyboardPrivate->TimerEvent

>> +                  );

>> +  if (EFI_ERROR (Status)) {

>> +    Status      = EFI_OUT_OF_RESOURCES;

> 

> The whitespace before = does not look quite right.

> Please address throughout.


OK

> 

>> +    goto Done;

>> +  }

>> +

>> +  Status = gBS->SetTimer (

>> +                  VirtualKeyboardPrivate->TimerEvent,

>> +                  TimerPeriodic,

>> +                  KEYBOARD_TIMER_INTERVAL

>> +                  );

>> +  if (EFI_ERROR (Status)) {

>> +    Status      = EFI_OUT_OF_RESOURCES;

>> +    goto Done;

>> +  }

>> +

>> +  Status = gBS->CreateEvent (

>> +                  EVT_NOTIFY_SIGNAL,

>> +                  TPL_CALLBACK,

>> +                  KeyNotifyProcessHandler,

>> +                  VirtualKeyboardPrivate,

>> +                  &VirtualKeyboardPrivate->KeyNotifyProcessEvent

>> +                  );

>> +  if (EFI_ERROR (Status)) {

>> +    Status      = EFI_OUT_OF_RESOURCES;

>> +    goto Done;

>> +  }

>> +

>> +  //

>> +  // Reset the keyboard device

>> +  //

>> +  Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset (

>> +                                                    &VirtualKeyboardPrivate->SimpleTextInputEx,

> 

> Funky indentation.

> According to coding style, it's missing 3 spaces.

> 


OK

>> +                                                    FALSE

>> +                                                    );

>> +  if (EFI_ERROR (Status)) {

>> +    DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));

> 

> Use DEBUG_ERROR (PatchCheck.py warns about this).

> 


OK

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardWaitForKey (

>> +  IN  EFI_EVENT               Event,

>> +  IN  VOID                    *Context

>> +  )

>> +{

>> +  //

>> +  // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.

>> +  // Csm will be used to check whether there is a key pending, but the csm will disable all

> 

> Well, this makes it clear this driver is based on

> IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/.

> I cannot really comment on whether that was the best starting point,

> but please delete all and any references to CSM and eficompatibility -

> these are fundamentally irrelevant for any non-x86 platforms.

> 


OK

>> +  // interrupt before switch to compatibility16, which mean all the efiCompatibility timer

>> +  // event will stop work during the compatibility16. And If a caller recursivly invoke this function,

>> +  // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,

>> +  // e.g. usb keyboard driver.

>> +  // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.

>> +  // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.

>> +  //

>> +  gBS->Stall (1000);

>> +  //

>> +  // Use TimerEvent callback function to check whether there's any key pressed

>> +  //

>> +  VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context));

>> +

>> +  if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) {

>> +    gBS->SignalEvent (Event);

>> +  }

>> +}

>> +

>> +/**

>> +  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event

>> +  Signal the event if there is key available

>> +

>> +  @param Event    event object

>> +  @param Context  waiting context

>> +

>> +**/

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardWaitForKeyEx (

>> +  IN  EFI_EVENT               Event,

>> +  IN  VOID                    *Context

>> +  )

>> +

>> +{

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

>> +

>> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context);

>> +  VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn);

>> +

>> +}

>> +

>> +//

>> +// EFI Simple Text In Protocol Functions

>> +//

>> +/**

>> +  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.

> 

> There are a few really long lines in this patch. Please try to keep

> to no more than 80 characters were feasible. Applies throughout.

> 


OK

>> +

>> +  @param  This                  Pointer of simple text Protocol.

>> +  @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.

>> +

>> +  @retval EFI_SUCCESS           The command byte is written successfully.

>> +  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReset (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

>> +  IN  BOOLEAN                         ExtendedVerification

>> +  )

>> +{

>> +  VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;

>> +  EFI_STATUS           Status;

>> +  EFI_TPL              OldTpl;

>> +

>> +  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  //

>> +  // Raise TPL to avoid mouse operation impact

>> +  //

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  if (VirtualKeyboardPrivate->PlatformVirtual && VirtualKeyboardPrivate->PlatformVirtual->Reset) {

> 

>    if (VirtualKeyboardPrivate->PlatformVirtual &&

>        VirtualKeyboardPrivate->PlatformVirtual->Reset) {

> 

> And so on.

> 


OK

>> +    Status = VirtualKeyboardPrivate->PlatformVirtual->Reset ();

>> +  } else {

>> +    Status = EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  //

>> +  // resume priority of task level

>> +  //

>> +  gBS->RestoreTPL (OldTpl);

>> +

>> +  return Status;

>> +}

>> +

>> +/**

>> +  Reset the input device and optionaly run diagnostics

>> +

>> +  @param  This                  Protocol instance pointer.

>> +  @param  ExtendedVerification  Driver may perform diagnostics on reset.

>> +

>> +  @retval EFI_SUCCESS           The device was reset.

>> +  @retval EFI_DEVICE_ERROR      The device is not functioning properly and could-

>> +                                not be reset.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardResetEx (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN BOOLEAN                            ExtendedVerification

>> +  )

>> +{

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

> 

> Spacing does not match subsequent lines.

> 

>> +  EFI_STATUS                            Status;

>> +  EFI_TPL                               OldTpl;

>> +

>> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  Status = VirtualKeyboardPrivate->SimpleTextIn.Reset (

>> +                                               &VirtualKeyboardPrivate->SimpleTextIn,

> 

> Funky indentation.

> 

>> +                                               ExtendedVerification

>> +                                               );

>> +  if (EFI_ERROR (Status)) {

>> +    return EFI_DEVICE_ERROR;

>> +  }

>> +

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  gBS->RestoreTPL (OldTpl);

>> +

>> +  return EFI_SUCCESS;

>> +

>> +}

>> +

>> +/**

>> +  Reads the next keystroke from the input device. The WaitForKey Event can

>> +  be used to test for existance of a keystroke via WaitForEvent () call.

>> +

>> +  @param  VirtualKeyboardPrivate   Virtualkeyboard driver private structure.

>> +  @param  KeyData               A pointer to a buffer that is filled in with the keystroke

>> +                                state data for the key that was pressed.

>> +

>> +  @retval EFI_SUCCESS           The keystroke information was returned.

>> +  @retval EFI_NOT_READY         There was no keystroke data availiable.

>> +  @retval EFI_DEVICE_ERROR      The keystroke information was not returned due to

>> +                                hardware errors.

>> +  @retval EFI_INVALID_PARAMETER KeyData is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +KeyboardReadKeyStrokeWorker (

>> +  IN VIRTUAL_KEYBOARD_DEV  *VirtualKeyboardPrivate,

>> +  OUT EFI_KEY_DATA      *KeyData

>> +  )

>> +{

>> +  EFI_STATUS                            Status;

>> +  EFI_TPL                               OldTpl;

>> +  if (KeyData == NULL) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  //

>> +  // Use TimerEvent callback function to check whether there's any key pressed

>> +  //

>> +

>> +  //

>> +  // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.

>> +  // Csm will be used to check whether there is a key pending, but the csm will disable all

>> +  // interrupt before switch to compatibility16, which mean all the efiCompatibility timer

>> +  // event will stop work during the compatibility16. And If a caller recursivly invoke this function,

>> +  // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,

>> +  // e.g. usb keyboard driver.

>> +  // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.

>> +  // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.

>> +  //

>> +  gBS->Stall (1000);

>> +

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate);

>> +  //

>> +  // If there's no key, just return

>> +  //

>> +  Status = CheckQueue (&VirtualKeyboardPrivate->Queue);

>> +  if (EFI_ERROR (Status)) {

>> +    gBS->RestoreTPL (OldTpl);

>> +    return EFI_NOT_READY;

>> +  }

>> +

>> +  Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData);

>> +

>> +  gBS->RestoreTPL (OldTpl);

>> +

>> +  return EFI_SUCCESS;

>> +}

>> +

>> +/**

>> +  Read out the scan code of the key that has just been stroked.

>> +

>> +  @param  This        Pointer of simple text Protocol.

>> +  @param  Key         Pointer for store the key that read out.

>> +

>> +  @retval EFI_SUCCESS The key is read out successfully.

>> +  @retval other       The key reading failed.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReadKeyStroke (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

>> +  OUT EFI_INPUT_KEY                   *Key

>> +  )

>> +{

>> +  VIRTUAL_KEYBOARD_DEV     *VirtualKeyboardPrivate;

>> +  EFI_STATUS            Status;

>> +  EFI_KEY_DATA          KeyData;

>> +

>> +  VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData);

>> +  if (EFI_ERROR (Status)) {

>> +    return Status;

>> +  }

>> +

>> +  //

>> +  // Convert the Ctrl+[a-z] to Ctrl+[1-26]

>> +  //

>> +  if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {

>> +    if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {

>> +      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);

>> +    } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {

>> +      KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);

>> +    }

>> +  }

>> +

>> +  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));

>> +

>> +  return EFI_SUCCESS;

>> +}

>> +

>> +/**

>> +  Reads the next keystroke from the input device. The WaitForKey Event can

>> +  be used to test for existance of a keystroke via WaitForEvent () call.

>> +

>> +  @param  This         Protocol instance pointer.

>> +  @param  KeyData      A pointer to a buffer that is filled in with the keystroke

>> +                       state data for the key that was pressed.

>> +

>> +  @retval  EFI_SUCCESS           The keystroke information was returned.

>> +  @retval  EFI_NOT_READY         There was no keystroke data availiable.

>> +  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to

>> +                                 hardware errors.

>> +  @retval  EFI_INVALID_PARAMETER KeyData is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReadKeyStrokeEx (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

>> +  OUT EFI_KEY_DATA                      *KeyData

>> +  )

>> +{

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

>> +

>> +  if (KeyData == NULL) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, KeyData);

>> +

>> +}

>> +

>> +/**

>> +  Set certain state for the input device.

>> +

>> +  @param  This              Protocol instance pointer.

>> +  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the-

>> +                            state for the input device.

>> +

>> +  @retval EFI_SUCCESS           The device state was set successfully.

>> +  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could-

>> +                                not have the setting adjusted.

>> +  @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.

>> +  @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardSetState (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState

>> +  )

>> +{

>> +  if (KeyToggleState == NULL) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  //

>> +  // Thunk keyboard driver doesn't support partial keystroke.

>> +  //

>> +  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||

>> +      (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED

>> +      ) {

>> +    return EFI_UNSUPPORTED;

>> +  }

>> +

> 

> This function has no side effects, and it's an emulated keyboard (how

> could a partial keystroke happen?). Why does it do anything other than

> return SUCCESS?

> 


OK. I'll change it.

>> +  return EFI_SUCCESS;

>> +}

>> +

>> +/**

>> +  Register a notification function for a particular keystroke for the input device.

>> +

>> +  @param  This                    Protocol instance pointer.

>> +  @param  KeyData                 A pointer to a buffer that is filled in with the keystroke

>> +                                  information data for the key that was pressed.

>> +  @param  KeyNotificationFunction Points to the function to be called when the key

>> +                                  sequence is typed specified by KeyData.

>> +  @param  NotifyHandle            Points to the unique handle assigned to the registered notification.

>> +

>> +

>> +  @retval EFI_SUCCESS             The notification function was registered successfully.

>> +  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.

>> +  @retval EFI_INVALID_PARAMETER   KeyData or NotifyHandle is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardRegisterKeyNotify (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN EFI_KEY_DATA                       *KeyData,

>> +  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,

>> +  OUT VOID                              **NotifyHandle

>> +  )

>> +{

>> +  EFI_STATUS                            Status;

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

>> +  EFI_TPL                               OldTpl;

>> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *NewNotify;

>> +  LIST_ENTRY                            *Link;

>> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

>> +

>> +  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  //

>> +  // Enter critical section

>> +  //

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  //

>> +  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.

>> +  //

>> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

>> +    CurrentNotify = CR (

>> +                      Link,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

>> +                      NotifyEntry,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

>> +                      );

>> +    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {

>> +      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {

>> +        *NotifyHandle = CurrentNotify;

>> +        Status = EFI_SUCCESS;

>> +        goto Exit;

>> +      }

>> +    }

>> +  }

>> +

>> +  //

>> +  // Allocate resource to save the notification function

>> +  //

>> +

>> +  NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY));

>> +  if (NewNotify == NULL) {

>> +    Status = EFI_OUT_OF_RESOURCES;

>> +    goto Exit;

>> +  }

>> +

>> +  NewNotify->Signature         = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;

>> +  NewNotify->KeyNotificationFn = KeyNotificationFunction;

>> +  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));

>> +  InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);

>> +

>> +  *NotifyHandle                = NewNotify;

>> +  Status                       = EFI_SUCCESS;

>> +

>> +Exit:

>> +  //

>> +  // Leave critical section and return

>> +  //

>> +  gBS->RestoreTPL (OldTpl);

>> +  return Status;

>> +

>> +}

>> +

>> +/**

>> +  Remove a registered notification function from a particular keystroke.

>> +

>> +  @param  This                 Protocol instance pointer.

>> +  @param  NotificationHandle   The handle of the notification function being unregistered.

>> +

>> +  @retval EFI_SUCCESS             The notification function was unregistered successfully.

>> +  @retval EFI_INVALID_PARAMETER   The NotificationHandle is invalid.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardUnregisterKeyNotify (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN VOID                               *NotificationHandle

>> +  )

>> +{

>> +  EFI_STATUS                            Status;

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

>> +  EFI_TPL                               OldTpl;

>> +  LIST_ENTRY                            *Link;

>> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

>> +

>> +  //

>> +  // Check incoming notification handle

>> +  //

>> +  if (NotificationHandle == NULL) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {

>> +    return EFI_INVALID_PARAMETER;

>> +  }

>> +

>> +  VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);

>> +

>> +  //

>> +  // Enter critical section

>> +  //

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

>> +    CurrentNotify = CR (

>> +                      Link,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

>> +                      NotifyEntry,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

>> +                      );

>> +    if (CurrentNotify == NotificationHandle) {

>> +      //

>> +      // Remove the notification function from NotifyList and free resources

>> +      //

>> +      RemoveEntryList (&CurrentNotify->NotifyEntry);

>> +

>> +      Status = EFI_SUCCESS;

>> +      goto Exit;

>> +    }

>> +  }

>> +

>> +  //

>> +  // Can not find the specified Notification Handle

>> +  //

>> +  Status = EFI_INVALID_PARAMETER;

>> +

>> +Exit:

>> +  //

>> +  // Leave critical section and return

>> +  //

>> +  gBS->RestoreTPL (OldTpl);

>> +  return Status;

>> +}

>> +

>> +/**

>> +  Timer event handler: read a series of scancodes from 8042

>> +  and put them into memory scancode buffer.

>> +  it read as much scancodes to either fill

>> +  the memory buffer or empty the keyboard buffer.

>> +  It is registered as running under TPL_NOTIFY

>> +

>> +  @param Event       The timer event

>> +  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer

>> +

>> +**/

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardTimerHandler (

>> +  IN EFI_EVENT    Event,

>> +  IN VOID         *Context

>> +  )

>> +{

>> +  EFI_TPL                            OldTpl;

>> +  LIST_ENTRY                         *Link;

>> +  EFI_KEY_DATA                       KeyData;

> 

> Please make these variable names line up with the ones below.

> 

>> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;

>> +  VIRTUAL_KEYBOARD_DEV                   *VirtualKeyboardPrivate;

>> +  VIRTUAL_KBD_KEY                        VirtualKey;

>> +

>> +  VirtualKeyboardPrivate = Context;

>> +

>> +  //

>> +  // Enter critical section

>> +  //

>> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +

>> +  if (VirtualKeyboardPrivate->PlatformVirtual &&

>> +      VirtualKeyboardPrivate->PlatformVirtual->Query) {

>> +    if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) == FALSE) {

>> +      goto Exit;

>> +    }

>> +    // Found key

>> +    KeyData.Key.ScanCode = VirtualKey.Key.ScanCode;

>> +    KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar;

>> +    KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;

>> +    KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;

>> +    if (VirtualKeyboardPrivate->PlatformVirtual->Clear) {

>> +      VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey);

>> +    }

>> +  } else {

>> +    goto Exit;

>> +  }

>> +

>> +  //

>> +  // Signal KeyNotify process event if this key pressed matches any key registered.

>> +  //

>> +  for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {

>> +    CurrentNotify = CR (

>> +                      Link,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,

>> +                      NotifyEntry,

>> +                      VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE

>> +                      );

>> +    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

>> +      //

>> +      // The key notification function needs to run at TPL_CALLBACK

>> +      // while current TPL is TPL_NOTIFY. It will be invoked in

>> +      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.

>> +      //

>> +      Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);

>> +      gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);

>> +    }

>> +  }

>> +

>> +  Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData);

>> +

>> +Exit:

>> +  //

>> +  // Leave critical section and return

>> +  //

>> +  gBS->RestoreTPL (OldTpl);

>> +}

>> +

>> +/**

>> +  Process key notify.

>> +

>> +  @param  Event                 Indicates the event that invoke this function.

>> +  @param  Context               Indicates the calling context.

>> +**/

>> +VOID

>> +EFIAPI

>> +KeyNotifyProcessHandler (

>> +  IN  EFI_EVENT                 Event,

>> +  IN  VOID                      *Context

>> +  )

>> +{

>> +  EFI_STATUS                            Status;

>> +  VIRTUAL_KEYBOARD_DEV                     *VirtualKeyboardPrivate;

>> +  EFI_KEY_DATA                          KeyData;

>> +  LIST_ENTRY                            *Link;

>> +  LIST_ENTRY                            *NotifyList;

>> +  VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;

>> +  EFI_TPL                               OldTpl;

> 

> Please make variable names line up.

> 

>> +

>> +  VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context;

>> +

>> +  //

>> +  // Invoke notification functions.

>> +  //

>> +  NotifyList = &VirtualKeyboardPrivate->NotifyList;

>> +  while (TRUE) {

>> +    //

>> +    // Enter critical section

>> +    //

>> +    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

>> +    Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);

>> +    //

>> +    // Leave critical section

>> +    //

>> +    gBS->RestoreTPL (OldTpl);

>> +    if (EFI_ERROR (Status)) {

>> +      break;

>> +    }

>> +    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {

>> +      CurrentNotify = CR (Link, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);

>> +      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

>> +        CurrentNotify->KeyNotificationFn (&KeyData);

>> +      }

>> +    }

>> +  }

>> +}

>> +

>> +/**

>> +  The user Entry Point for module VirtualKeyboard. The user code starts with this function.

>> +

>> +  @param[in] ImageHandle    The firmware allocated handle for the EFI image.

>> +  @param[in] SystemTable    A pointer to the EFI System Table.

>> +

>> +  @retval EFI_SUCCESS       The entry point is executed successfully.

>> +  @retval other             Some error occurs when executing this entry point.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +InitializeVirtualKeyboard(

>> +  IN EFI_HANDLE           ImageHandle,

>> +  IN EFI_SYSTEM_TABLE     *SystemTable

>> +  )

>> +{

>> +  EFI_STATUS              Status;

>> +

>> +  //

>> +  // Install driver model protocol(s).

>> +  //

>> +  Status = EfiLibInstallDriverBindingComponentName2 (

>> +             ImageHandle,

>> +             SystemTable,

>> +             &gVirtualKeyboardDriverBinding,

>> +             ImageHandle,

>> +             &gVirtualKeyboardComponentName,

>> +             &gVirtualKeyboardComponentName2

>> +             );

>> +  ASSERT_EFI_ERROR (Status);

>> +

>> +  return Status;

>> +}

>> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

>> new file mode 100644

>> index 0000000..c8e256d

>> --- /dev/null

>> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h

>> @@ -0,0 +1,544 @@

>> +/** @file

>> +

>> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

>> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

>> +

>> +This program and the accompanying materials

>> +are licensed and made available under the terms and conditions

>> +of the BSD License which accompanies this distribution.  The

>> +full text of the license may be found at

>> +http://opensource.org/licenses/bsd-license.php

>> +

>> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

>> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

>> +

>> +**/

>> +

>> +#ifndef _VIRTUAL_KEYBOARD_H_

>> +#define _VIRTUAL_KEYBOARD_H_

>> +

>> +

>> +#include <Guid/StatusCodeDataTypeId.h>

>> +#include <Protocol/DevicePath.h>

>> +#include <Protocol/PlatformVirtualKeyboard.h>

>> +#include <Protocol/SimpleTextIn.h>

>> +#include <Protocol/SimpleTextInEx.h>

>> +

>> +#include <Library/BaseLib.h>

>> +#include <Library/BaseMemoryLib.h>

>> +#include <Library/DebugLib.h>

>> +#include <Library/MemoryAllocationLib.h>

>> +#include <Library/IoLib.h>

>> +#include <Library/PcdLib.h>

>> +#include <Library/ReportStatusCodeLib.h>

>> +#include <Library/UefiBootServicesTableLib.h>

>> +#include <Library/UefiDriverEntryPoint.h>

>> +#include <Library/UefiLib.h>

>> +

>> +//

>> +// Driver Binding Externs

>> +//

>> +extern EFI_DRIVER_BINDING_PROTOCOL  gVirtualKeyboardDriverBinding;

>> +extern EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName;

>> +extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;

>> +

>> +

>> +//

>> +// VIRTUAL Keyboard Defines

>> +//

>> +#define CHAR_SCANCODE                        0xe0

>> +#define CHAR_ESC                             0x1b

>> +

>> +#define KEYBOARD_TIMEOUT                     65536   // 0.07s

>> +#define KEYBOARD_WAITFORVALUE_TIMEOUT        1000000 // 1s

>> +#define KEYBOARD_BAT_TIMEOUT                 4000000 // 4s

>> +#define KEYBOARD_TIMER_INTERVAL              500000  // 0.5s

>> +

>> +#define QUEUE_MAX_COUNT                      32

>> +

>> +#define KEYBOARD_SCAN_CODE_MAX_COUNT         32

>> +

>> +//

>> +// VIRTUAL Keyboard Device Structure

>> +//

>> +#define VIRTUAL_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('V', 'K', 'B', 'D')

>> +#define VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('v', 'k', 'c', 'n')

>> +

>> +typedef struct _VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY {

>> +  UINTN                                      Signature;

>> +  EFI_KEY_DATA                               KeyData;

>> +  EFI_KEY_NOTIFY_FUNCTION                    KeyNotificationFn;

>> +  LIST_ENTRY                                 NotifyEntry;

>> +} VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY;

>> +

>> +typedef struct {

>> +  UINTN                                      Front;

>> +  UINTN                                      Rear;

>> +  EFI_KEY_DATA                               Buffer[QUEUE_MAX_COUNT];

>> +} SIMPLE_QUEUE;

>> +

>> +typedef struct {

>> +  UINT8                                      Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT];

>> +  UINTN                                      Head;

>> +  UINTN                                      Tail;

>> +} SCAN_CODE_QUEUE;

>> +

>> +typedef struct {

>> +  UINTN                                      Signature;

>> +  EFI_HANDLE                                 Handle;

>> +  PLATFORM_VIRTUAL_KBD_PROTOCOL              *PlatformVirtual;

>> +  EFI_SIMPLE_TEXT_INPUT_PROTOCOL             SimpleTextIn;

>> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL          SimpleTextInputEx;

>> +

>> +  //

>> +  // Buffer storing EFI_KEY_DATA

>> +  //

>> +  SIMPLE_QUEUE                               Queue;

>> +  SIMPLE_QUEUE                               QueueForNotify;

>> +

>> +  //

>> +  // Notification Function List

>> +  //

>> +  LIST_ENTRY                                 NotifyList;

>> +  EFI_EVENT                                  KeyNotifyProcessEvent;

>> +  EFI_EVENT                                  TimerEvent;

>> +} VIRTUAL_KEYBOARD_DEV;

>> +

>> +#define VIRTUAL_KEYBOARD_DEV_FROM_THIS(a)  CR (a, VIRTUAL_KEYBOARD_DEV, SimpleTextIn, VIRTUAL_KEYBOARD_DEV_SIGNATURE)

>> +#define TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS(a) \

>> +  CR (a, \

>> +      VIRTUAL_KEYBOARD_DEV, \

>> +      SimpleTextInputEx, \

>> +      VIRTUAL_KEYBOARD_DEV_SIGNATURE \

>> +      )

>> +

>> +//

>> +// Global Variables

>> +//

>> +extern EFI_DRIVER_BINDING_PROTOCOL   gVirtualKeyboardDriverBinding;

>> +

>> +//

>> +// Driver Binding Protocol functions

>> +//

>> +

>> +/**

>> +  Check whether the driver supports this device.

>> +

>> +  @param  This                   The Udriver binding protocol.

>> +  @param  Controller             The controller handle to check.

>> +  @param  RemainingDevicePath    The remaining device path.

>> +

>> +  @retval EFI_SUCCESS            The driver supports this controller.

>> +  @retval other                  This device isn't supported.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardDriverBindingSupported (

>> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

>> +  IN EFI_HANDLE                   Controller,

>> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

>> +  );

>> +

>> +/**

>> +  Starts the device with this driver.

>> +

>> +  @param  This                   The driver binding instance.

>> +  @param  Controller             Handle of device to bind driver to.

>> +  @param  RemainingDevicePath    Optional parameter use to pick a specific child

>> +                                 device to start.

>> +

>> +  @retval EFI_SUCCESS            The controller is controlled by the driver.

>> +  @retval Other                  This controller cannot be started.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardDriverBindingStart (

>> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

>> +  IN EFI_HANDLE                   Controller,

>> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

>> +  );

>> +

>> +/**

>> +  Stop the device handled by this driver.

>> +

>> +  @param  This                   The driver binding protocol.

>> +  @param  Controller             The controller to release.

>> +  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.

>> +  @param  ChildHandleBuffer      The array of child handle.

>> +

>> +  @retval EFI_SUCCESS            The device was stopped.

>> +  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.

>> +  @retval Others                 Fail to uninstall protocols attached on the device.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardDriverBindingStop (

>> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,

>> +  IN  EFI_HANDLE                   Controller,

>> +  IN  UINTN                        NumberOfChildren,

>> +  IN  EFI_HANDLE                   *ChildHandleBuffer

>> +  );

>> +

>> +/**

>> +  Retrieves a Unicode string that is the user readable name of the driver.

>> +

>> +  This function retrieves the user readable name of a driver in the form of a

>> +  Unicode string. If the driver specified by This has a user readable name in

>> +  the language specified by Language, then a pointer to the driver name is

>> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified

>> +  by This does not support the language specified by Language,

>> +  then EFI_UNSUPPORTED is returned.

>> +

>> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

>> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

>> +

>> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

>> +                                array indicating the language. This is the

>> +                                language of the driver name that the caller is

>> +                                requesting, and it must match one of the

>> +                                languages specified in SupportedLanguages. The

>> +                                number of languages supported by a driver is up

>> +                                to the driver writer. Language is specified

>> +                                in RFC 4646 or ISO 639-2 language code format.

>> +

>> +  @param  DriverName[out]       A pointer to the Unicode string to return.

>> +                                This Unicode string is the name of the

>> +                                driver specified by This in the language

>> +                                specified by Language.

>> +

>> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by

>> +                                This and the language specified by Language was

>> +                                returned in DriverName.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER DriverName is NULL.

>> +

>> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

>> +                                the language specified by Language.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardComponentNameGetDriverName (

>> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

>> +  IN  CHAR8                        *Language,

>> +  OUT CHAR16                       **DriverName

>> +  );

>> +

>> +

>> +/**

>> +  Retrieves a Unicode string that is the user readable name of the controller

>> +  that is being managed by a driver.

>> +

>> +  This function retrieves the user readable name of the controller specified by

>> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the

>> +  driver specified by This has a user readable name in the language specified by

>> +  Language, then a pointer to the controller name is returned in ControllerName,

>> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently

>> +  managing the controller specified by ControllerHandle and ChildHandle,

>> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not

>> +  support the language specified by Language, then EFI_UNSUPPORTED is returned.

>> +

>> +  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

>> +                                EFI_COMPONENT_NAME_PROTOCOL instance.

>> +

>> +  @param  ControllerHandle[in]  The handle of a controller that the driver

>> +                                specified by This is managing.  This handle

>> +                                specifies the controller whose name is to be

>> +                                returned.

>> +

>> +  @param  ChildHandle[in]       The handle of the child controller to retrieve

>> +                                the name of.  This is an optional parameter that

>> +                                may be NULL.  It will be NULL for device

>> +                                drivers.  It will also be NULL for a bus drivers

>> +                                that wish to retrieve the name of the bus

>> +                                controller.  It will not be NULL for a bus

>> +                                driver that wishes to retrieve the name of a

>> +                                child controller.

>> +

>> +  @param  Language[in]          A pointer to a Null-terminated ASCII string

>> +                                array indicating the language.  This is the

>> +                                language of the driver name that the caller is

>> +                                requesting, and it must match one of the

>> +                                languages specified in SupportedLanguages. The

>> +                                number of languages supported by a driver is up

>> +                                to the driver writer. Language is specified in

>> +                                RFC 4646 or ISO 639-2 language code format.

>> +

>> +  @param  ControllerName[out]   A pointer to the Unicode string to return.

>> +                                This Unicode string is the name of the

>> +                                controller specified by ControllerHandle and

>> +                                ChildHandle in the language specified by

>> +                                Language from the point of view of the driver

>> +                                specified by This.

>> +

>> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in

>> +                                the language specified by Language for the

>> +                                driver specified by This was returned in

>> +                                DriverName.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER ControllerHandle is NULL.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER ChildHandle is not NULL and it is not a valid

>> +                                EFI_HANDLE.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER Language is NULL.

>> +

>> +  @retval EFI_INVALID_PAVIRTUALETER ControllerName is NULL.

>> +

>> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

>> +                                managing the controller specified by

>> +                                ControllerHandle and ChildHandle.

>> +

>> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support

>> +                                the language specified by Language.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardComponentNameGetControllerName (

>> +  IN  EFI_COMPONENT_NAME_PROTOCOL      *This,

>> +  IN  EFI_HANDLE                       ControllerHandle,

>> +  IN  EFI_HANDLE                       ChildHandle        OPTIONAL,

>> +  IN  CHAR8                            *Language,

>> +  OUT CHAR16                           **ControllerName

>> +  );

>> +

>> +

>> +//

>> +// Simple Text Input Protocol functions

>> +//

>> +/**

>> +  Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.

>> +

>> +  @param  This                  Pointer of simple text Protocol.

>> +  @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.

>> +

>> +  @retval EFI_SUCCESS           The command byte is written successfully.

>> +  @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReset (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

>> +  IN  BOOLEAN                         ExtendedVerification

>> +  );

>> +

>> +/**

>> +  Reset the input device and optionaly run diagnostics

>> +

>> +  @param  This                  Protocol instance pointer.

>> +  @param  ExtendedVerification  Driver may perform diagnostics on reset.

>> +

>> +  @retval EFI_SUCCESS           The device was reset.

>> +  @retval EFI_DEVICE_ERROR      The device is not functioning properly and could

> 

> Trailing whitespace. (PatchCheck.py warns about this.)

> 

>> +                                not be reset.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardResetEx (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN BOOLEAN                            ExtendedVerification

>> +  );

>> +

>> +/**

>> +  Set certain state for the input device.

>> +

>> +  @param  This              Protocol instance pointer.

>> +  @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the

>> +                            state for the input device.

>> +

>> +  @retval EFI_SUCCESS           The device state was set successfully.

>> +  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could

>> +                                not have the setting adjusted.

>> +  @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.

>> +  @retval EFI_INVALID_PAVIRTUALETER KeyToggleState is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardSetState (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState

>> +  );

>> +

>> +/**

>> +  Register a notification function for a particular keystroke for the input device.

>> +

>> +  @param  This                    Protocol instance pointer.

>> +  @param  KeyData                 A pointer to a buffer that is filled in with the keystroke

>> +                                  information data for the key that was pressed.

>> +  @param  KeyNotificationFunction Points to the function to be called when the key

>> +                                  sequence is typed specified by KeyData.

>> +  @param  NotifyHandle            Points to the unique handle assigned to the registered notification.

>> +

>> +

>> +  @retval EFI_SUCCESS             The notification function was registered successfully.

>> +  @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.

>> +  @retval EFI_INVALID_PAVIRTUALETER   KeyData or NotifyHandle is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardRegisterKeyNotify (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN EFI_KEY_DATA                       *KeyData,

>> +  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,

>> +  OUT VOID                              **NotifyHandle

>> +  );

>> +

>> +/**

>> +  Remove a registered notification function from a particular keystroke.

>> +

>> +  @param  This                 Protocol instance pointer.

>> +  @param  NotificationHandle   The handle of the notification function being unregistered.

>> +

>> +  @retval EFI_SUCCESS             The notification function was unregistered successfully.

>> +  @retval EFI_INVALID_PAVIRTUALETER   The NotificationHandle is invalid.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardUnregisterKeyNotify (

>> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,

>> +  IN VOID                               *NotificationHandle

>> +  );

>> +

>> +//

>> +// Private worker functions

>> +//

>> +/**

>> +  Free keyboard notify list.

>> +

>> +  @param  ListHead   The list head

>> +

>> +  @retval EFI_SUCCESS           Free the notify list successfully

>> +  @retval EFI_INVALID_PAVIRTUALETER ListHead is invalid.

>> +

>> +**/

>> +EFI_STATUS

>> +VirtualKeyboardFreeNotifyList (

>> +  IN OUT LIST_ENTRY           *ListHead

>> +  );

>> +

>> +/**

>> +  Check if key is registered.

>> +

>> +  @param  RegsiteredData    A pointer to a buffer that is filled in with the keystroke

>> +                            state data for the key that was registered.

>> +  @param  InputData         A pointer to a buffer that is filled in with the keystroke

>> +                            state data for the key that was pressed.

>> +

>> +  @retval TRUE              Key be pressed matches a registered key.

>> +  @retval FLASE             Match failed.

>> +

>> +**/

>> +BOOLEAN

>> +IsKeyRegistered (

>> +  IN EFI_KEY_DATA  *RegsiteredData,

>> +  IN EFI_KEY_DATA  *InputData

>> +  );

>> +

>> +/**

>> +  Waiting on the keyboard event, if there's any key pressed by the user, signal the event

>> +

>> +  @param  Event       The event that be siganlled when any key has been stroked.

>> +  @param  Context     Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.

>> +

>> +**/

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardWaitForKey (

>> +  IN  EFI_EVENT  Event,

>> +  IN  VOID       *Context

>> +  );

>> +

>> +/**

>> +  Waiting on the keyboard event, if there's any key pressed by the user, signal the event

>> +

>> +  @param  Event    The event that be siganlled when any key has been stroked.

>> +  @param  Context  Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.

>> +

>> +**/

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardWaitForKeyEx (

>> +  IN  EFI_EVENT  Event,

>> +  IN  VOID       *Context

>> +  );

>> +

>> +/**

>> +  Timer event handler: read a series of key stroke from 8042

>> +  and put them into memory key buffer.

>> +  It is registered as running under TPL_NOTIFY

>> +

>> +  @param  Event   The timer event

>> +  @param  Context A VIRTUAL_KEYBOARD_DEV pointer

>> +

>> +**/

>> +VOID

>> +EFIAPI

>> +VirtualKeyboardTimerHandler (

>> +  IN EFI_EVENT    Event,

>> +  IN VOID         *Context

>> +  );

>> +

>> +/**

>> +  Process key notify.

>> +

>> +  @param  Event                 Indicates the event that invoke this function.

>> +  @param  Context               Indicates the calling context.

>> +**/

>> +VOID

>> +EFIAPI

>> +KeyNotifyProcessHandler (

>> +  IN  EFI_EVENT                 Event,

>> +  IN  VOID                      *Context

>> +  );

>> +

>> +/**

>> +  Read out the scan code of the key that has just been stroked.

>> +

>> +  @param  This        Pointer of simple text Protocol.

>> +  @param  Key         Pointer for store the key that read out.

>> +

>> +  @retval EFI_SUCCESS The key is read out successfully.

>> +  @retval other       The key reading failed.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReadKeyStroke (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,

>> +  OUT EFI_INPUT_KEY                   *Key

>> +  );

>> +

>> +/**

>> +  Reads the next keystroke from the input device. The WaitForKey Event can

>> +  be used to test for existance of a keystroke via WaitForEvent () call.

>> +

>> +  @param  This         Protocol instance pointer.

>> +  @param  KeyData      A pointer to a buffer that is filled in with the keystroke

>> +                       state data for the key that was pressed.

>> +

>> +  @retval  EFI_SUCCESS           The keystroke information was returned.

>> +  @retval  EFI_NOT_READY         There was no keystroke data availiable.

>> +  @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to

>> +                                 hardware errors.

>> +  @retval  EFI_INVALID_PAVIRTUALETER KeyData is NULL.

>> +

>> +**/

>> +EFI_STATUS

>> +EFIAPI

>> +VirtualKeyboardReadKeyStrokeEx (

>> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

>> +  OUT EFI_KEY_DATA                      *KeyData

>> +  );

>> +

>> +#endif /* _VIRTUAL_KEYBOARD_H_ */

>> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

>> new file mode 100644

>> index 0000000..065f4f2

>> --- /dev/null

>> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec

> 

> Could you add the two guids to EmbeddededPkg instead?

> Or just gPlatformVirtualKeyboardProtocolGuid, I don't see any use of

> gVirtualKeyboardDxeTokenSpaceGuid.


I'll move it into EmbeddedPkg instead.

> 

>> @@ -0,0 +1,39 @@

>> +#/** @file

>> +# Framework Module Development Environment Industry Standards

>> +#

>> +# This Package provides headers and libraries that conform to EFI/PI Industry standards.

>> +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

>> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>

>> +# Copyright (c) 2018, Linaro. All rights reserved.<BR>

>> +#

>> +#    This program and the accompanying materials are licensed and made available under

>> +#    the terms and conditions of the BSD License which accompanies this distribution.

>> +#    The full text of the license may be found at

>> +#    http://opensource.org/licenses/bsd-license.php

>> +#

>> +#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

>> +#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

>> +#

>> +#**/

>> +

>> +[Defines]

>> +  DEC_SPECIFICATION              = 0x00010019

>> +  PACKAGE_NAME                   = VirtualKeyboardDxePkg

>> +  PACKAGE_GUID                   = 774326bc-20d0-4203-97e4-10dc17f7dc1a

>> +  PACKAGE_VERSION                = 0.1

>> +

>> +################################################################################

>> +#

>> +# Include Section - list of Include Paths that are provided by this package.

>> +#                   Comments are used for Keywords and Module Types.

>> +#

>> +# Supported Module Types:

>> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION

>> +#

>> +################################################################################

>> +

>> +[Guids.common]

>> +  gVirtualKeyboardDxeTokenSpaceGuid    = { 0x80caf901, 0x0cf6, 0x4c09, { 0x89, 0x84, 0x61, 0xd1, 0xf3, 0xd2, 0x54, 0x39 }}

>> +

>> +[Protocols.common]

>> +  gPlatformVirtualKeyboardProtocolGuid = { 0x0e3606d2, 0x1dc3, 0x4e6f, { 0xbe, 0x65, 0x39, 0x49, 0x82, 0xa2, 0x65, 0x47 }}

>> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

>> new file mode 100644

>> index 0000000..a7e5bd0

>> --- /dev/null

>> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

>> @@ -0,0 +1,61 @@

>> +## @file

>> +# Virtual Keyboard driver.

>> +#

>> +# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>

>> +#

>> +# This program and the accompanying materials

>> +# are licensed and made available under the terms and conditions

>> +# of the BSD License which accompanies this distribution.  The

>> +# full text of the license may be found at

>> +# http://opensource.org/licenses/bsd-license.php

>> +#

>> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

>> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

>> +#

>> +##

>> +

>> +[Defines]

>> +  INF_VERSION                    = 0x00010019

>> +  BASE_NAME                      = VirtualKeyboardDxe

>> +  FILE_GUID                      = 88079b18-b42b-44aa-a6f2-b83911075e89

>> +  MODULE_TYPE                    = UEFI_DRIVER

>> +  VERSION_STRING                 = 1.0

>> +  ENTRY_POINT                    = InitializeVirtualKeyboard

>> +

>> +#

>> +# The following information is for reference only and not required by the build tools.

>> +#

>> +#  VALID_ARCHITECTURES           = AARCH64

> 

> Well, it's emulated, so I would hope it's valid for all architectures?

> 


OK

Best Regards
Haojian
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Leif Lindholm Feb. 28, 2018, 1:36 p.m. UTC | #3
On Wed, Feb 28, 2018 at 01:03:07AM +0000, Haojian Zhuang wrote:
> >> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c
> >> new file mode 100644
> >> index 0000000..2935307
> >> --- /dev/null
> >> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c
> >> @@ -0,0 +1,184 @@
> >> +/** @file
> >> +
> >> +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
> >> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
> >> +
> >> +This program and the accompanying materials
> >> +are licensed and made available under the terms and conditions
> >> +of the BSD License which accompanies this distribution.  The
> >> +full text of the license may be found at
> >> +http://opensource.org/licenses/bsd-license.php
> >> +
> >> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> >> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> >> +
> >> +**/
> >> +
> >> +#include "VirtualKeyboard.h"
> >> +
> >> +//
> >> +// EFI Component Name Protocol
> >> +//
> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName = {
> >> +  VirtualKeyboardComponentNameGetDriverName,
> >> +  VirtualKeyboardComponentNameGetControllerName,
> >> +  "eng"
> >> +};
> >> +
> >> +//
> >> +// EFI Component Name 2 Protocol
> >> +//
> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = {
> >> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName,
> >> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName,
> >> +  "en"
> >> +};
> >> +
> >> +
> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {
> >> +  {
> >> +    "eng;en",
> >> +    L"RAM Keyboard Driver"
> > 
> > What is a RAM Keyboard Driver?
> > 
> 
> Oh, I'll rename it to Virtual Keyboard Driver for consistent.

Thanks.

> >> +  },
> > 
> > Any chance of a "zh-chs" entry?
> > 
> 
> Thanks. "zh-chs" may be inconvenient for others. "eng;en" is good for 
> everyone.

The purpose of this functionality is to provide a list with
translations of the driver name into different languages.
My request was not to use zh-chs instead of eng;en, but in addition to.

Or (according to google translate):
  {
    "eng;en",
    L"Virtual Keyboard Driver"
  },
  {
    "zh-chs".
    L"虚拟键盘驱动"
  },
  {
    NULL,
    NULL
  }
};

Best Regards,

Leif
diff mbox series

Patch

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