.../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
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
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/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 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
On 02/27/2018 08:28 PM, Leif Lindholm wrote: > On Mon, Feb 26, 2018 at 04:52:36PM +0800, Haojian Zhuang wrote: >> The virtual keyboard could simulate a keyboard. User could simulate >> a key value when pattern is matched. > > How? This is over 2000 lines of new code, please give a little bit > more description of what it does and how it is intended to be used. > > (It sounds like is could be a useful feature, but I can only find out > what it is intended to do by reading the code, which isn't what review > is supposed to be.) OK. I'll append more comments in it. > >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> >> --- >> .../Drivers/VirtualKeyboardDxe/ComponentName.c | 184 ++++ >> .../Drivers/VirtualKeyboardDxe/ComponentName.h | 154 +++ >> .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.c | 1117 ++++++++++++++++++++ >> .../Drivers/VirtualKeyboardDxe/VirtualKeyboard.h | 544 ++++++++++ >> .../VirtualKeyboardDxe/VirtualKeyboardDxe.dec | 39 + >> .../VirtualKeyboardDxe/VirtualKeyboardDxe.inf | 61 ++ >> .../Include/Protocol/PlatformVirtualKeyboard.h | 65 ++ > > Please generate patches with > --stat=1000 --stat-graph-width=20 > and > --subject-prefix="PATCH edk2-platforms" > > (In general following the guide at) > https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers OK. I'll follow it. > >> 7 files changed, 2164 insertions(+) >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.h >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.c >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec >> create mode 100644 EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf >> create mode 100644 EmbeddedPkg/Include/Protocol/PlatformVirtualKeyboard.h >> >> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c >> new file mode 100644 >> index 0000000..2935307 >> --- /dev/null >> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/ComponentName.c >> @@ -0,0 +1,184 @@ >> +/** @file >> + >> +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> >> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> >> + >> +This program and the accompanying materials >> +are licensed and made available under the terms and conditions >> +of the BSD License which accompanies this distribution. The >> +full text of the license may be found at >> +http://opensource.org/licenses/bsd-license.php >> + >> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> + >> +**/ >> + >> +#include "VirtualKeyboard.h" >> + >> +// >> +// EFI Component Name Protocol >> +// >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName = { >> + VirtualKeyboardComponentNameGetDriverName, >> + VirtualKeyboardComponentNameGetControllerName, >> + "eng" >> +}; >> + >> +// >> +// EFI Component Name 2 Protocol >> +// >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = { >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName, >> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName, >> + "en" >> +}; >> + >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = { >> + { >> + "eng;en", >> + L"RAM Keyboard Driver" > > What is a RAM Keyboard Driver? > Oh, I'll rename it to Virtual Keyboard Driver for consistent. >> + }, > > Any chance of a "zh-chs" entry? > Thanks. "zh-chs" may be inconvenient for others. "eng;en" is good for everyone. >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardDriverBindingStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ) >> +{ >> + EFI_STATUS Status; >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual; >> + >> + Status = gBS->OpenProtocol ( >> + Controller, >> + &gPlatformVirtualKeyboardProtocolGuid, >> + (VOID **) &PlatformVirtual, >> + This->DriverBindingHandle, >> + Controller, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // >> + // Allocate the private device structure >> + // >> + VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV)); >> + if (NULL == VirtualKeyboardPrivate) { > > No jeopardy-comparisons please. if (VirtualKeyboardPrivate == NULL) { > OK >> + // >> + // Setup a periodic timer, used for reading keystrokes at a fixed interval >> + // >> + Status = gBS->CreateEvent ( >> + EVT_TIMER | EVT_NOTIFY_SIGNAL, >> + TPL_NOTIFY, >> + VirtualKeyboardTimerHandler, >> + VirtualKeyboardPrivate, >> + &VirtualKeyboardPrivate->TimerEvent >> + ); >> + if (EFI_ERROR (Status)) { >> + Status = EFI_OUT_OF_RESOURCES; > > The whitespace before = does not look quite right. > Please address throughout. OK > >> + goto Done; >> + } >> + >> + Status = gBS->SetTimer ( >> + VirtualKeyboardPrivate->TimerEvent, >> + TimerPeriodic, >> + KEYBOARD_TIMER_INTERVAL >> + ); >> + if (EFI_ERROR (Status)) { >> + Status = EFI_OUT_OF_RESOURCES; >> + goto Done; >> + } >> + >> + Status = gBS->CreateEvent ( >> + EVT_NOTIFY_SIGNAL, >> + TPL_CALLBACK, >> + KeyNotifyProcessHandler, >> + VirtualKeyboardPrivate, >> + &VirtualKeyboardPrivate->KeyNotifyProcessEvent >> + ); >> + if (EFI_ERROR (Status)) { >> + Status = EFI_OUT_OF_RESOURCES; >> + goto Done; >> + } >> + >> + // >> + // Reset the keyboard device >> + // >> + Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset ( >> + &VirtualKeyboardPrivate->SimpleTextInputEx, > > Funky indentation. > According to coding style, it's missing 3 spaces. > OK >> + FALSE >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status)); > > Use DEBUG_ERROR (PatchCheck.py warns about this). > OK >> +VOID >> +EFIAPI >> +VirtualKeyboardWaitForKey ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + // >> + // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. >> + // Csm will be used to check whether there is a key pending, but the csm will disable all > > Well, this makes it clear this driver is based on > IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/. > I cannot really comment on whether that was the best starting point, > but please delete all and any references to CSM and eficompatibility - > these are fundamentally irrelevant for any non-x86 platforms. > OK >> + // interrupt before switch to compatibility16, which mean all the efiCompatibility timer >> + // event will stop work during the compatibility16. And If a caller recursivly invoke this function, >> + // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period, >> + // e.g. usb keyboard driver. >> + // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. >> + // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. >> + // >> + gBS->Stall (1000); >> + // >> + // Use TimerEvent callback function to check whether there's any key pressed >> + // >> + VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context)); >> + >> + if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) { >> + gBS->SignalEvent (Event); >> + } >> +} >> + >> +/** >> + Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event >> + Signal the event if there is key available >> + >> + @param Event event object >> + @param Context waiting context >> + >> +**/ >> +VOID >> +EFIAPI >> +VirtualKeyboardWaitForKeyEx ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> + >> +{ >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + >> + VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context); >> + VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn); >> + >> +} >> + >> +// >> +// EFI Simple Text In Protocol Functions >> +// >> +/** >> + Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. > > There are a few really long lines in this patch. Please try to keep > to no more than 80 characters were feasible. Applies throughout. > OK >> + >> + @param This Pointer of simple text Protocol. >> + @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. >> + >> + @retval EFI_SUCCESS The command byte is written successfully. >> + @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReset ( >> + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, >> + IN BOOLEAN ExtendedVerification >> + ) >> +{ >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + EFI_STATUS Status; >> + EFI_TPL OldTpl; >> + >> + VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + // >> + // Raise TPL to avoid mouse operation impact >> + // >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + if (VirtualKeyboardPrivate->PlatformVirtual && VirtualKeyboardPrivate->PlatformVirtual->Reset) { > > if (VirtualKeyboardPrivate->PlatformVirtual && > VirtualKeyboardPrivate->PlatformVirtual->Reset) { > > And so on. > OK >> + Status = VirtualKeyboardPrivate->PlatformVirtual->Reset (); >> + } else { >> + Status = EFI_INVALID_PARAMETER; >> + } >> + >> + // >> + // resume priority of task level >> + // >> + gBS->RestoreTPL (OldTpl); >> + >> + return Status; >> +} >> + >> +/** >> + Reset the input device and optionaly run diagnostics >> + >> + @param This Protocol instance pointer. >> + @param ExtendedVerification Driver may perform diagnostics on reset. >> + >> + @retval EFI_SUCCESS The device was reset. >> + @retval EFI_DEVICE_ERROR The device is not functioning properly and could- >> + not be reset. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardResetEx ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN BOOLEAN ExtendedVerification >> + ) >> +{ >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; > > Spacing does not match subsequent lines. > >> + EFI_STATUS Status; >> + EFI_TPL OldTpl; >> + >> + VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + Status = VirtualKeyboardPrivate->SimpleTextIn.Reset ( >> + &VirtualKeyboardPrivate->SimpleTextIn, > > Funky indentation. > >> + ExtendedVerification >> + ); >> + if (EFI_ERROR (Status)) { >> + return EFI_DEVICE_ERROR; >> + } >> + >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + gBS->RestoreTPL (OldTpl); >> + >> + return EFI_SUCCESS; >> + >> +} >> + >> +/** >> + Reads the next keystroke from the input device. The WaitForKey Event can >> + be used to test for existance of a keystroke via WaitForEvent () call. >> + >> + @param VirtualKeyboardPrivate Virtualkeyboard driver private structure. >> + @param KeyData A pointer to a buffer that is filled in with the keystroke >> + state data for the key that was pressed. >> + >> + @retval EFI_SUCCESS The keystroke information was returned. >> + @retval EFI_NOT_READY There was no keystroke data availiable. >> + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to >> + hardware errors. >> + @retval EFI_INVALID_PARAMETER KeyData is NULL. >> + >> +**/ >> +EFI_STATUS >> +KeyboardReadKeyStrokeWorker ( >> + IN VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate, >> + OUT EFI_KEY_DATA *KeyData >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_TPL OldTpl; >> + if (KeyData == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + // >> + // Use TimerEvent callback function to check whether there's any key pressed >> + // >> + >> + // >> + // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event. >> + // Csm will be used to check whether there is a key pending, but the csm will disable all >> + // interrupt before switch to compatibility16, which mean all the efiCompatibility timer >> + // event will stop work during the compatibility16. And If a caller recursivly invoke this function, >> + // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period, >> + // e.g. usb keyboard driver. >> + // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked. >> + // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input. >> + // >> + gBS->Stall (1000); >> + >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate); >> + // >> + // If there's no key, just return >> + // >> + Status = CheckQueue (&VirtualKeyboardPrivate->Queue); >> + if (EFI_ERROR (Status)) { >> + gBS->RestoreTPL (OldTpl); >> + return EFI_NOT_READY; >> + } >> + >> + Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData); >> + >> + gBS->RestoreTPL (OldTpl); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Read out the scan code of the key that has just been stroked. >> + >> + @param This Pointer of simple text Protocol. >> + @param Key Pointer for store the key that read out. >> + >> + @retval EFI_SUCCESS The key is read out successfully. >> + @retval other The key reading failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReadKeyStroke ( >> + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, >> + OUT EFI_INPUT_KEY *Key >> + ) >> +{ >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + EFI_STATUS Status; >> + EFI_KEY_DATA KeyData; >> + >> + VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // >> + // Convert the Ctrl+[a-z] to Ctrl+[1-26] >> + // >> + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { >> + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { >> + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); >> + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { >> + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); >> + } >> + } >> + >> + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Reads the next keystroke from the input device. The WaitForKey Event can >> + be used to test for existance of a keystroke via WaitForEvent () call. >> + >> + @param This Protocol instance pointer. >> + @param KeyData A pointer to a buffer that is filled in with the keystroke >> + state data for the key that was pressed. >> + >> + @retval EFI_SUCCESS The keystroke information was returned. >> + @retval EFI_NOT_READY There was no keystroke data availiable. >> + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to >> + hardware errors. >> + @retval EFI_INVALID_PARAMETER KeyData is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReadKeyStrokeEx ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + OUT EFI_KEY_DATA *KeyData >> + ) >> +{ >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + >> + if (KeyData == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, KeyData); >> + >> +} >> + >> +/** >> + Set certain state for the input device. >> + >> + @param This Protocol instance pointer. >> + @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the- >> + state for the input device. >> + >> + @retval EFI_SUCCESS The device state was set successfully. >> + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could- >> + not have the setting adjusted. >> + @retval EFI_UNSUPPORTED The device does not have the ability to set its state. >> + @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardSetState ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN EFI_KEY_TOGGLE_STATE *KeyToggleState >> + ) >> +{ >> + if (KeyToggleState == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + // >> + // Thunk keyboard driver doesn't support partial keystroke. >> + // >> + if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID || >> + (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED >> + ) { >> + return EFI_UNSUPPORTED; >> + } >> + > > This function has no side effects, and it's an emulated keyboard (how > could a partial keystroke happen?). Why does it do anything other than > return SUCCESS? > OK. I'll change it. >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Register a notification function for a particular keystroke for the input device. >> + >> + @param This Protocol instance pointer. >> + @param KeyData A pointer to a buffer that is filled in with the keystroke >> + information data for the key that was pressed. >> + @param KeyNotificationFunction Points to the function to be called when the key >> + sequence is typed specified by KeyData. >> + @param NotifyHandle Points to the unique handle assigned to the registered notification. >> + >> + >> + @retval EFI_SUCCESS The notification function was registered successfully. >> + @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures. >> + @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardRegisterKeyNotify ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN EFI_KEY_DATA *KeyData, >> + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, >> + OUT VOID **NotifyHandle >> + ) >> +{ >> + EFI_STATUS Status; >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + EFI_TPL OldTpl; >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; >> + LIST_ENTRY *Link; >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; >> + >> + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + // >> + // Enter critical section >> + // >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + // >> + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. >> + // >> + for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { >> + CurrentNotify = CR ( >> + Link, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, >> + NotifyEntry, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE >> + ); >> + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { >> + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { >> + *NotifyHandle = CurrentNotify; >> + Status = EFI_SUCCESS; >> + goto Exit; >> + } >> + } >> + } >> + >> + // >> + // Allocate resource to save the notification function >> + // >> + >> + NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY)); >> + if (NewNotify == NULL) { >> + Status = EFI_OUT_OF_RESOURCES; >> + goto Exit; >> + } >> + >> + NewNotify->Signature = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; >> + NewNotify->KeyNotificationFn = KeyNotificationFunction; >> + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); >> + InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry); >> + >> + *NotifyHandle = NewNotify; >> + Status = EFI_SUCCESS; >> + >> +Exit: >> + // >> + // Leave critical section and return >> + // >> + gBS->RestoreTPL (OldTpl); >> + return Status; >> + >> +} >> + >> +/** >> + Remove a registered notification function from a particular keystroke. >> + >> + @param This Protocol instance pointer. >> + @param NotificationHandle The handle of the notification function being unregistered. >> + >> + @retval EFI_SUCCESS The notification function was unregistered successfully. >> + @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardUnregisterKeyNotify ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN VOID *NotificationHandle >> + ) >> +{ >> + EFI_STATUS Status; >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + EFI_TPL OldTpl; >> + LIST_ENTRY *Link; >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; >> + >> + // >> + // Check incoming notification handle >> + // >> + if (NotificationHandle == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This); >> + >> + // >> + // Enter critical section >> + // >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { >> + CurrentNotify = CR ( >> + Link, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, >> + NotifyEntry, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE >> + ); >> + if (CurrentNotify == NotificationHandle) { >> + // >> + // Remove the notification function from NotifyList and free resources >> + // >> + RemoveEntryList (&CurrentNotify->NotifyEntry); >> + >> + Status = EFI_SUCCESS; >> + goto Exit; >> + } >> + } >> + >> + // >> + // Can not find the specified Notification Handle >> + // >> + Status = EFI_INVALID_PARAMETER; >> + >> +Exit: >> + // >> + // Leave critical section and return >> + // >> + gBS->RestoreTPL (OldTpl); >> + return Status; >> +} >> + >> +/** >> + Timer event handler: read a series of scancodes from 8042 >> + and put them into memory scancode buffer. >> + it read as much scancodes to either fill >> + the memory buffer or empty the keyboard buffer. >> + It is registered as running under TPL_NOTIFY >> + >> + @param Event The timer event >> + @param Context A KEYBOARD_CONSOLE_IN_DEV pointer >> + >> +**/ >> +VOID >> +EFIAPI >> +VirtualKeyboardTimerHandler ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + EFI_TPL OldTpl; >> + LIST_ENTRY *Link; >> + EFI_KEY_DATA KeyData; > > Please make these variable names line up with the ones below. > >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + VIRTUAL_KBD_KEY VirtualKey; >> + >> + VirtualKeyboardPrivate = Context; >> + >> + // >> + // Enter critical section >> + // >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + >> + if (VirtualKeyboardPrivate->PlatformVirtual && >> + VirtualKeyboardPrivate->PlatformVirtual->Query) { >> + if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) == FALSE) { >> + goto Exit; >> + } >> + // Found key >> + KeyData.Key.ScanCode = VirtualKey.Key.ScanCode; >> + KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar; >> + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; >> + KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; >> + if (VirtualKeyboardPrivate->PlatformVirtual->Clear) { >> + VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey); >> + } >> + } else { >> + goto Exit; >> + } >> + >> + // >> + // Signal KeyNotify process event if this key pressed matches any key registered. >> + // >> + for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink; Link != &VirtualKeyboardPrivate->NotifyList; Link = Link->ForwardLink) { >> + CurrentNotify = CR ( >> + Link, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, >> + NotifyEntry, >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE >> + ); >> + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { >> + // >> + // The key notification function needs to run at TPL_CALLBACK >> + // while current TPL is TPL_NOTIFY. It will be invoked in >> + // KeyNotifyProcessHandler() which runs at TPL_CALLBACK. >> + // >> + Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData); >> + gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent); >> + } >> + } >> + >> + Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData); >> + >> +Exit: >> + // >> + // Leave critical section and return >> + // >> + gBS->RestoreTPL (OldTpl); >> +} >> + >> +/** >> + Process key notify. >> + >> + @param Event Indicates the event that invoke this function. >> + @param Context Indicates the calling context. >> +**/ >> +VOID >> +EFIAPI >> +KeyNotifyProcessHandler ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + EFI_STATUS Status; >> + VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; >> + EFI_KEY_DATA KeyData; >> + LIST_ENTRY *Link; >> + LIST_ENTRY *NotifyList; >> + VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; >> + EFI_TPL OldTpl; > > Please make variable names line up. > >> + >> + VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context; >> + >> + // >> + // Invoke notification functions. >> + // >> + NotifyList = &VirtualKeyboardPrivate->NotifyList; >> + while (TRUE) { >> + // >> + // Enter critical section >> + // >> + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData); >> + // >> + // Leave critical section >> + // >> + gBS->RestoreTPL (OldTpl); >> + if (EFI_ERROR (Status)) { >> + break; >> + } >> + for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) { >> + CurrentNotify = CR (Link, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE); >> + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { >> + CurrentNotify->KeyNotificationFn (&KeyData); >> + } >> + } >> + } >> +} >> + >> +/** >> + The user Entry Point for module VirtualKeyboard. The user code starts with this function. >> + >> + @param[in] ImageHandle The firmware allocated handle for the EFI image. >> + @param[in] SystemTable A pointer to the EFI System Table. >> + >> + @retval EFI_SUCCESS The entry point is executed successfully. >> + @retval other Some error occurs when executing this entry point. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +InitializeVirtualKeyboard( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + // >> + // Install driver model protocol(s). >> + // >> + Status = EfiLibInstallDriverBindingComponentName2 ( >> + ImageHandle, >> + SystemTable, >> + &gVirtualKeyboardDriverBinding, >> + ImageHandle, >> + &gVirtualKeyboardComponentName, >> + &gVirtualKeyboardComponentName2 >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + return Status; >> +} >> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h >> new file mode 100644 >> index 0000000..c8e256d >> --- /dev/null >> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboard.h >> @@ -0,0 +1,544 @@ >> +/** @file >> + >> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> >> +Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> >> + >> +This program and the accompanying materials >> +are licensed and made available under the terms and conditions >> +of the BSD License which accompanies this distribution. The >> +full text of the license may be found at >> +http://opensource.org/licenses/bsd-license.php >> + >> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> + >> +**/ >> + >> +#ifndef _VIRTUAL_KEYBOARD_H_ >> +#define _VIRTUAL_KEYBOARD_H_ >> + >> + >> +#include <Guid/StatusCodeDataTypeId.h> >> +#include <Protocol/DevicePath.h> >> +#include <Protocol/PlatformVirtualKeyboard.h> >> +#include <Protocol/SimpleTextIn.h> >> +#include <Protocol/SimpleTextInEx.h> >> + >> +#include <Library/BaseLib.h> >> +#include <Library/BaseMemoryLib.h> >> +#include <Library/DebugLib.h> >> +#include <Library/MemoryAllocationLib.h> >> +#include <Library/IoLib.h> >> +#include <Library/PcdLib.h> >> +#include <Library/ReportStatusCodeLib.h> >> +#include <Library/UefiBootServicesTableLib.h> >> +#include <Library/UefiDriverEntryPoint.h> >> +#include <Library/UefiLib.h> >> + >> +// >> +// Driver Binding Externs >> +// >> +extern EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding; >> +extern EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName; >> +extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2; >> + >> + >> +// >> +// VIRTUAL Keyboard Defines >> +// >> +#define CHAR_SCANCODE 0xe0 >> +#define CHAR_ESC 0x1b >> + >> +#define KEYBOARD_TIMEOUT 65536 // 0.07s >> +#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s >> +#define KEYBOARD_BAT_TIMEOUT 4000000 // 4s >> +#define KEYBOARD_TIMER_INTERVAL 500000 // 0.5s >> + >> +#define QUEUE_MAX_COUNT 32 >> + >> +#define KEYBOARD_SCAN_CODE_MAX_COUNT 32 >> + >> +// >> +// VIRTUAL Keyboard Device Structure >> +// >> +#define VIRTUAL_KEYBOARD_DEV_SIGNATURE SIGNATURE_32 ('V', 'K', 'B', 'D') >> +#define VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('v', 'k', 'c', 'n') >> + >> +typedef struct _VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY { >> + UINTN Signature; >> + EFI_KEY_DATA KeyData; >> + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; >> + LIST_ENTRY NotifyEntry; >> +} VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY; >> + >> +typedef struct { >> + UINTN Front; >> + UINTN Rear; >> + EFI_KEY_DATA Buffer[QUEUE_MAX_COUNT]; >> +} SIMPLE_QUEUE; >> + >> +typedef struct { >> + UINT8 Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT]; >> + UINTN Head; >> + UINTN Tail; >> +} SCAN_CODE_QUEUE; >> + >> +typedef struct { >> + UINTN Signature; >> + EFI_HANDLE Handle; >> + PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual; >> + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; >> + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInputEx; >> + >> + // >> + // Buffer storing EFI_KEY_DATA >> + // >> + SIMPLE_QUEUE Queue; >> + SIMPLE_QUEUE QueueForNotify; >> + >> + // >> + // Notification Function List >> + // >> + LIST_ENTRY NotifyList; >> + EFI_EVENT KeyNotifyProcessEvent; >> + EFI_EVENT TimerEvent; >> +} VIRTUAL_KEYBOARD_DEV; >> + >> +#define VIRTUAL_KEYBOARD_DEV_FROM_THIS(a) CR (a, VIRTUAL_KEYBOARD_DEV, SimpleTextIn, VIRTUAL_KEYBOARD_DEV_SIGNATURE) >> +#define TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS(a) \ >> + CR (a, \ >> + VIRTUAL_KEYBOARD_DEV, \ >> + SimpleTextInputEx, \ >> + VIRTUAL_KEYBOARD_DEV_SIGNATURE \ >> + ) >> + >> +// >> +// Global Variables >> +// >> +extern EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding; >> + >> +// >> +// Driver Binding Protocol functions >> +// >> + >> +/** >> + Check whether the driver supports this device. >> + >> + @param This The Udriver binding protocol. >> + @param Controller The controller handle to check. >> + @param RemainingDevicePath The remaining device path. >> + >> + @retval EFI_SUCCESS The driver supports this controller. >> + @retval other This device isn't supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardDriverBindingSupported ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +/** >> + Starts the device with this driver. >> + >> + @param This The driver binding instance. >> + @param Controller Handle of device to bind driver to. >> + @param RemainingDevicePath Optional parameter use to pick a specific child >> + device to start. >> + >> + @retval EFI_SUCCESS The controller is controlled by the driver. >> + @retval Other This controller cannot be started. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardDriverBindingStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +/** >> + Stop the device handled by this driver. >> + >> + @param This The driver binding protocol. >> + @param Controller The controller to release. >> + @param NumberOfChildren The number of handles in ChildHandleBuffer. >> + @param ChildHandleBuffer The array of child handle. >> + >> + @retval EFI_SUCCESS The device was stopped. >> + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. >> + @retval Others Fail to uninstall protocols attached on the device. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardDriverBindingStop ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN UINTN NumberOfChildren, >> + IN EFI_HANDLE *ChildHandleBuffer >> + ); >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the driver. >> + >> + This function retrieves the user readable name of a driver in the form of a >> + Unicode string. If the driver specified by This has a user readable name in >> + the language specified by Language, then a pointer to the driver name is >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified >> + by This does not support the language specified by Language, >> + then EFI_UNSUPPORTED is returned. >> + >> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + >> + @param Language[in] A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified >> + in RFC 4646 or ISO 639-2 language code format. >> + >> + @param DriverName[out] A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + driver specified by This in the language >> + specified by Language. >> + >> + @retval EFI_SUCCESS The Unicode string for the Driver specified by >> + This and the language specified by Language was >> + returned in DriverName. >> + >> + @retval EFI_INVALID_PAVIRTUALETER Language is NULL. >> + >> + @retval EFI_INVALID_PAVIRTUALETER DriverName is NULL. >> + >> + @retval EFI_UNSUPPORTED The driver specified by This does not support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardComponentNameGetDriverName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN CHAR8 *Language, >> + OUT CHAR16 **DriverName >> + ); >> + >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the controller >> + that is being managed by a driver. >> + >> + This function retrieves the user readable name of the controller specified by >> + ControllerHandle and ChildHandle in the form of a Unicode string. If the >> + driver specified by This has a user readable name in the language specified by >> + Language, then a pointer to the controller name is returned in ControllerName, >> + and EFI_SUCCESS is returned. If the driver specified by This is not currently >> + managing the controller specified by ControllerHandle and ChildHandle, >> + then EFI_UNSUPPORTED is returned. If the driver specified by This does not >> + support the language specified by Language, then EFI_UNSUPPORTED is returned. >> + >> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + >> + @param ControllerHandle[in] The handle of a controller that the driver >> + specified by This is managing. This handle >> + specifies the controller whose name is to be >> + returned. >> + >> + @param ChildHandle[in] The handle of the child controller to retrieve >> + the name of. This is an optional parameter that >> + may be NULL. It will be NULL for device >> + drivers. It will also be NULL for a bus drivers >> + that wish to retrieve the name of the bus >> + controller. It will not be NULL for a bus >> + driver that wishes to retrieve the name of a >> + child controller. >> + >> + @param Language[in] A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified in >> + RFC 4646 or ISO 639-2 language code format. >> + >> + @param ControllerName[out] A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + controller specified by ControllerHandle and >> + ChildHandle in the language specified by >> + Language from the point of view of the driver >> + specified by This. >> + >> + @retval EFI_SUCCESS The Unicode string for the user readable name in >> + the language specified by Language for the >> + driver specified by This was returned in >> + DriverName. >> + >> + @retval EFI_INVALID_PAVIRTUALETER ControllerHandle is NULL. >> + >> + @retval EFI_INVALID_PAVIRTUALETER ChildHandle is not NULL and it is not a valid >> + EFI_HANDLE. >> + >> + @retval EFI_INVALID_PAVIRTUALETER Language is NULL. >> + >> + @retval EFI_INVALID_PAVIRTUALETER ControllerName is NULL. >> + >> + @retval EFI_UNSUPPORTED The driver specified by This is not currently >> + managing the controller specified by >> + ControllerHandle and ChildHandle. >> + >> + @retval EFI_UNSUPPORTED The driver specified by This does not support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardComponentNameGetControllerName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> + IN CHAR8 *Language, >> + OUT CHAR16 **ControllerName >> + ); >> + >> + >> +// >> +// Simple Text Input Protocol functions >> +// >> +/** >> + Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations. >> + >> + @param This Pointer of simple text Protocol. >> + @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip. >> + >> + @retval EFI_SUCCESS The command byte is written successfully. >> + @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReset ( >> + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, >> + IN BOOLEAN ExtendedVerification >> + ); >> + >> +/** >> + Reset the input device and optionaly run diagnostics >> + >> + @param This Protocol instance pointer. >> + @param ExtendedVerification Driver may perform diagnostics on reset. >> + >> + @retval EFI_SUCCESS The device was reset. >> + @retval EFI_DEVICE_ERROR The device is not functioning properly and could > > Trailing whitespace. (PatchCheck.py warns about this.) > >> + not be reset. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardResetEx ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN BOOLEAN ExtendedVerification >> + ); >> + >> +/** >> + Set certain state for the input device. >> + >> + @param This Protocol instance pointer. >> + @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the >> + state for the input device. >> + >> + @retval EFI_SUCCESS The device state was set successfully. >> + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could >> + not have the setting adjusted. >> + @retval EFI_UNSUPPORTED The device does not have the ability to set its state. >> + @retval EFI_INVALID_PAVIRTUALETER KeyToggleState is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardSetState ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN EFI_KEY_TOGGLE_STATE *KeyToggleState >> + ); >> + >> +/** >> + Register a notification function for a particular keystroke for the input device. >> + >> + @param This Protocol instance pointer. >> + @param KeyData A pointer to a buffer that is filled in with the keystroke >> + information data for the key that was pressed. >> + @param KeyNotificationFunction Points to the function to be called when the key >> + sequence is typed specified by KeyData. >> + @param NotifyHandle Points to the unique handle assigned to the registered notification. >> + >> + >> + @retval EFI_SUCCESS The notification function was registered successfully. >> + @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures. >> + @retval EFI_INVALID_PAVIRTUALETER KeyData or NotifyHandle is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardRegisterKeyNotify ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN EFI_KEY_DATA *KeyData, >> + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, >> + OUT VOID **NotifyHandle >> + ); >> + >> +/** >> + Remove a registered notification function from a particular keystroke. >> + >> + @param This Protocol instance pointer. >> + @param NotificationHandle The handle of the notification function being unregistered. >> + >> + @retval EFI_SUCCESS The notification function was unregistered successfully. >> + @retval EFI_INVALID_PAVIRTUALETER The NotificationHandle is invalid. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardUnregisterKeyNotify ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + IN VOID *NotificationHandle >> + ); >> + >> +// >> +// Private worker functions >> +// >> +/** >> + Free keyboard notify list. >> + >> + @param ListHead The list head >> + >> + @retval EFI_SUCCESS Free the notify list successfully >> + @retval EFI_INVALID_PAVIRTUALETER ListHead is invalid. >> + >> +**/ >> +EFI_STATUS >> +VirtualKeyboardFreeNotifyList ( >> + IN OUT LIST_ENTRY *ListHead >> + ); >> + >> +/** >> + Check if key is registered. >> + >> + @param RegsiteredData A pointer to a buffer that is filled in with the keystroke >> + state data for the key that was registered. >> + @param InputData A pointer to a buffer that is filled in with the keystroke >> + state data for the key that was pressed. >> + >> + @retval TRUE Key be pressed matches a registered key. >> + @retval FLASE Match failed. >> + >> +**/ >> +BOOLEAN >> +IsKeyRegistered ( >> + IN EFI_KEY_DATA *RegsiteredData, >> + IN EFI_KEY_DATA *InputData >> + ); >> + >> +/** >> + Waiting on the keyboard event, if there's any key pressed by the user, signal the event >> + >> + @param Event The event that be siganlled when any key has been stroked. >> + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL. >> + >> +**/ >> +VOID >> +EFIAPI >> +VirtualKeyboardWaitForKey ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ); >> + >> +/** >> + Waiting on the keyboard event, if there's any key pressed by the user, signal the event >> + >> + @param Event The event that be siganlled when any key has been stroked. >> + @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. >> + >> +**/ >> +VOID >> +EFIAPI >> +VirtualKeyboardWaitForKeyEx ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ); >> + >> +/** >> + Timer event handler: read a series of key stroke from 8042 >> + and put them into memory key buffer. >> + It is registered as running under TPL_NOTIFY >> + >> + @param Event The timer event >> + @param Context A VIRTUAL_KEYBOARD_DEV pointer >> + >> +**/ >> +VOID >> +EFIAPI >> +VirtualKeyboardTimerHandler ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ); >> + >> +/** >> + Process key notify. >> + >> + @param Event Indicates the event that invoke this function. >> + @param Context Indicates the calling context. >> +**/ >> +VOID >> +EFIAPI >> +KeyNotifyProcessHandler ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ); >> + >> +/** >> + Read out the scan code of the key that has just been stroked. >> + >> + @param This Pointer of simple text Protocol. >> + @param Key Pointer for store the key that read out. >> + >> + @retval EFI_SUCCESS The key is read out successfully. >> + @retval other The key reading failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReadKeyStroke ( >> + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, >> + OUT EFI_INPUT_KEY *Key >> + ); >> + >> +/** >> + Reads the next keystroke from the input device. The WaitForKey Event can >> + be used to test for existance of a keystroke via WaitForEvent () call. >> + >> + @param This Protocol instance pointer. >> + @param KeyData A pointer to a buffer that is filled in with the keystroke >> + state data for the key that was pressed. >> + >> + @retval EFI_SUCCESS The keystroke information was returned. >> + @retval EFI_NOT_READY There was no keystroke data availiable. >> + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to >> + hardware errors. >> + @retval EFI_INVALID_PAVIRTUALETER KeyData is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +VirtualKeyboardReadKeyStrokeEx ( >> + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, >> + OUT EFI_KEY_DATA *KeyData >> + ); >> + >> +#endif /* _VIRTUAL_KEYBOARD_H_ */ >> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec >> new file mode 100644 >> index 0000000..065f4f2 >> --- /dev/null >> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.dec > > Could you add the two guids to EmbeddededPkg instead? > Or just gPlatformVirtualKeyboardProtocolGuid, I don't see any use of > gVirtualKeyboardDxeTokenSpaceGuid. I'll move it into EmbeddedPkg instead. > >> @@ -0,0 +1,39 @@ >> +#/** @file >> +# Framework Module Development Environment Industry Standards >> +# >> +# This Package provides headers and libraries that conform to EFI/PI Industry standards. >> +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> >> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> >> +# Copyright (c) 2018, Linaro. All rights reserved.<BR> >> +# >> +# This program and the accompanying materials are licensed and made available under >> +# the terms and conditions of the BSD License which accompanies this distribution. >> +# The full text of the license may be found at >> +# http://opensource.org/licenses/bsd-license.php >> +# >> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +# >> +#**/ >> + >> +[Defines] >> + DEC_SPECIFICATION = 0x00010019 >> + PACKAGE_NAME = VirtualKeyboardDxePkg >> + PACKAGE_GUID = 774326bc-20d0-4203-97e4-10dc17f7dc1a >> + PACKAGE_VERSION = 0.1 >> + >> +################################################################################ >> +# >> +# Include Section - list of Include Paths that are provided by this package. >> +# Comments are used for Keywords and Module Types. >> +# >> +# Supported Module Types: >> +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION >> +# >> +################################################################################ >> + >> +[Guids.common] >> + gVirtualKeyboardDxeTokenSpaceGuid = { 0x80caf901, 0x0cf6, 0x4c09, { 0x89, 0x84, 0x61, 0xd1, 0xf3, 0xd2, 0x54, 0x39 }} >> + >> +[Protocols.common] >> + gPlatformVirtualKeyboardProtocolGuid = { 0x0e3606d2, 0x1dc3, 0x4e6f, { 0xbe, 0x65, 0x39, 0x49, 0x82, 0xa2, 0x65, 0x47 }} >> diff --git a/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf >> new file mode 100644 >> index 0000000..a7e5bd0 >> --- /dev/null >> +++ b/EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf >> @@ -0,0 +1,61 @@ >> +## @file >> +# Virtual Keyboard driver. >> +# >> +# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR> >> +# >> +# This program and the accompanying materials >> +# are licensed and made available under the terms and conditions >> +# of the BSD License which accompanies this distribution. The >> +# full text of the license may be found at >> +# http://opensource.org/licenses/bsd-license.php >> +# >> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010019 >> + BASE_NAME = VirtualKeyboardDxe >> + FILE_GUID = 88079b18-b42b-44aa-a6f2-b83911075e89 >> + MODULE_TYPE = UEFI_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = InitializeVirtualKeyboard >> + >> +# >> +# The following information is for reference only and not required by the build tools. >> +# >> +# VALID_ARCHITECTURES = AARCH64 > > Well, it's emulated, so I would hope it's valid for all architectures? > OK Best Regards Haojian _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
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 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.