* [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver
@ 2018-02-26 8:52 Haojian Zhuang
2018-02-27 12:28 ` Leif Lindholm
0 siblings, 1 reply; 4+ messages in thread
From: Haojian Zhuang @ 2018-02-26 8:52 UTC (permalink / raw)
To: leif.lindholm, ard.biesheuvel, linaro-uefi, edk2-devel; +Cc: Haojian Zhuang
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
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__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver
2018-02-26 8:52 [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver Haojian Zhuang
@ 2018-02-27 12:28 ` Leif Lindholm
2018-02-28 1:03 ` Haojian Zhuang
0 siblings, 1 reply; 4+ messages in thread
From: Leif Lindholm @ 2018-02-27 12:28 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ard.biesheuvel, linaro-uefi, edk2-devel
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
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver
2018-02-27 12:28 ` Leif Lindholm
@ 2018-02-28 1:03 ` Haojian Zhuang
2018-02-28 13:36 ` Leif Lindholm
0 siblings, 1 reply; 4+ messages in thread
From: Haojian Zhuang @ 2018-02-28 1:03 UTC (permalink / raw)
To: Leif Lindholm
Cc: ard.biesheuvel@linaro.org, linaro-uefi@lists.linaro.org,
edk2-devel@lists.01.org
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver
2018-02-28 1:03 ` Haojian Zhuang
@ 2018-02-28 13:36 ` Leif Lindholm
0 siblings, 0 replies; 4+ messages in thread
From: Leif Lindholm @ 2018-02-28 13:36 UTC (permalink / raw)
To: Haojian Zhuang
Cc: ard.biesheuvel@linaro.org, linaro-uefi@lists.linaro.org,
edk2-devel@lists.01.org
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
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-02-28 13:30 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-26 8:52 [PATCH] EmbeddedPkg/Drivers: add virtual keyboard driver Haojian Zhuang
2018-02-27 12:28 ` Leif Lindholm
2018-02-28 1:03 ` Haojian Zhuang
2018-02-28 13:36 ` Leif Lindholm
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox