From: "Tan, Ming" <ming.tan@intel.com>
To: devel@edk2.groups.io
Subject: [PATCH v2] Features/Intel/UserInterface: Add VirtualKeyboardFeaturePkg
Date: Wed, 15 Apr 2020 09:37:41 +0800 [thread overview]
Message-ID: <20200415013742.14842-1-ming.tan@intel.com> (raw)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2603
It add a VirtualKeyboardDxe driver.
It is used with a touch panel, simulate a keyboard in the screen.
Signed-off-by: Ming Tan <ming.tan@intel.com>
---
.../Include/PostMemory.fdf | 10 +
.../Include/PreMemory.fdf | 8 +
.../Include/VirtualKeyboardFeature.dsc | 96 ++
.../VirtualKeyboardFeaturePkg/Readme.md | 97 ++
.../CapitalLetterKeyboard.bmp | Bin 0 -> 330454 bytes
.../VirtualKeyboardDxe/ComponentName.c | 159 ++
.../VirtualKeyboardDxe/ComponentName.h | 95 ++
.../VirtualKeyboardDxe/DigitKeyboard.bmp | Bin 0 -> 330454 bytes
.../VirtualKeyboardDxe/FullIcon.bmp | Bin 0 -> 5454 bytes
.../VirtualKeyboardDxe/Keyboard.c | 1409 ++++++++++++++++
.../VirtualKeyboardDxe/KeyboardLayout.c | 1438 +++++++++++++++++
.../VirtualKeyboardDxe/KeyboardLayout.idf | 12 +
.../VirtualKeyboardDxe/SimpleIcon.bmp | Bin 0 -> 2814 bytes
.../VirtualKeyboardDxe/SimpleKeyboard.bmp | Bin 0 -> 30054 bytes
.../VirtualKeyboardDxe/VirtualKeyboard.h | 829 ++++++++++
.../VirtualKeyboardDriver.c | 515 ++++++
.../VirtualKeyboardDxe/VirtualKeyboardDxe.inf | 78 +
.../VirtualKeyboardFeaturePkg.dec | 26 +
.../VirtualKeyboardFeaturePkg.dsc | 30 +
19 files changed, 4802 insertions(+)
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
new file mode 100644
index 0000000000..bf4a4d5078
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
@@ -0,0 +1,10 @@
+## @file
+# FDF file for post-memory modules that enable Virtual Keyboard.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+ INF UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
new file mode 100644
index 0000000000..c39a057f94
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
@@ -0,0 +1,8 @@
+## @file
+# FDF file for pre-memory modules that enable Virtual Keyboard.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
new file mode 100644
index 0000000000..c10fb2d567
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
@@ -0,0 +1,96 @@
+## @file
+# This is a build description file for the Virtual Keyboard feature.
+# This file should be included into another package DSC file to build this feature.
+#
+# The DEC files are used by the utilities that parse DSC and
+# INF files to generate AutoGen.c and AutoGen.h files
+# for the build infrastructure.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+!ifndef $(PEI_ARCH)
+ !error "PEI_ARCH must be specified to build this feature!"
+!endif
+!ifndef $(DXE_ARCH)
+ !error "DXE_ARCH must be specified to build this feature!"
+!endif
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this feature.
+#
+################################################################################
+[LibraryClasses]
+ #######################################
+ # Edk2 Packages
+ #######################################
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ #######################################
+ # Edk2 Packages
+ #######################################
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+#
+# Feature DXE Components
+#
+[Components.X64]
+ #####################################
+ # Virtual Keyboard Feature Package
+ #####################################
+ UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
+
+###################################################################################################
+#
+# BuildOptions Section - Define the module specific tool chain flags that should be used as
+# the default flags for a module. These flags are appended to any
+# standard flags that are defined by the build process. They can be
+# applied for any modules or only those modules with the specific
+# module style (EDK or EDKII) specified in [Components] section.
+#
+# For advanced features, it is recommended to enable [BuildOptions] in
+# the applicable INF file so it does not affect the whole board package
+# build when this DSC file is active.
+#
+###################################################################################################
+[BuildOptions]
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
new file mode 100644
index 0000000000..80b243feb8
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
@@ -0,0 +1,97 @@
+# Overview
+* **Feature Name:** Virtual Keyboard
+* **PI Phase(s) Supported:** DXE
+* **SMM Required?** No
+
+## Purpose
+This feature provides a DXE virtual keyboard driver, used with a touch panel.
+
+# High-Level Theory of Operation
+This driver will use the following protocol:
+ gEfiAbsolutePointerProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+ gEdkiiTouchPanelGuid
+
+It will show a picture like a keyboard in the graphic output, then detect
+position when user touch the touch panel, then calculate the key which the
+user want to type.
+
+## Firmware Volumes
+FvAdvancedUncompact
+FvAdvanced
+
+## Modules
+VirtualKeyboardDxe: The main driver of virtual keyboard
+
+## <Module Name>
+*_TODO_*
+Each module in the feature should have a section that describes the module in a level of detail that is useful
+to better understand the module source code.
+
+## <Library Name>
+*_TODO_*
+Each library in the feature should have a section that describes the library in a level of detail that is useful
+to better understand the library source code.
+
+## Key Functions
+*_TODO_*
+A bulleted list of key functions for interacting with the feature.
+
+Not all features need to be listed. Only functions exposed through external interfaces that are important for feature
+users to be aware of.
+
+## Configuration
+*_TODO_*
+Information that is useful for configuring the feature.
+
+Not all configuration options need to be listed. This section is used to provide more background on configuration
+options than possible elsewhere.
+
+## Data Flows
+*_TODO_*
+Architecturally defined data structures and flows for the feature.
+
+## Control Flows
+*_TODO_*
+Key control flows for the feature.
+
+## Build Flows
+*_TODO_*
+Any special build flows should be described in this section.
+
+This is particularly useful for features that use custom build tools or require non-standard tool configuration. If the
+standard flow in the feature package template is used, this section may be empty.
+
+## Test Point Results
+*_TODO_*
+The test(s) that can verify porting is complete for the feature.
+
+Each feature must describe at least one test point to verify the feature is successful. If the test point is not
+implemented, this should be stated.
+
+## Functional Exit Criteria
+*_TODO_*
+The testable functionality for the feature.
+
+This section should provide an ordered list of criteria that a board integrator can reference to ensure the feature is
+functional on their board.
+
+## Feature Enabling Checklist
+Make sure the following protocols are supported:
+ gEfiAbsolutePointerProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+ gEdkiiTouchPanelGuid
+
+## Performance Impact
+A general expectation for the impact on overall boot performance due to using this feature.
+
+This section is expected to provide guidance on:
+* How to estimate performance impact due to the feature
+* How to measure performance impact of the feature
+* How to manage performance impact of the feature
+
+## Common Optimizations
+*_TODO_*
+Common size or performance tuning options for this feature.
+
+This section is recommended but not required. If not used, the contents should be left empty.
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..759c3d46a9f0cf6a69fa98563cd04f7a082d3b4d
GIT binary patch
literal 330454
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
Ka0)zo_WuC{9xg=y
literal 0
HcmV?d00001
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
new file mode 100644
index 0000000000..6ac28ab90b
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
@@ -0,0 +1,159 @@
+/** @file
+ Virtual Keyboard driver name.
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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"
+};
+
+//
+// Table of driver names
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {
+ {
+ "eng;en",
+ L"UEFI Virtual Keyboard Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+//
+// Controller name string table
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardControllerNameStringTable[] = {
+ {
+ "eng",
+ L"UEFI Virtual Keyboard Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that 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.
+ @param[out] DriverName 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 an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle 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[in] ChildHandle 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[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller 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.
+ @param[out] ControllerName 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
+ )
+{
+ //
+ // ChildHandle must be NULL for a Device Driver
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mVirtualKeyboardControllerNameStringTable,
+ ControllerName,
+ (BOOLEAN)(This == &gVirtualKeyboardComponentName)
+ );
+}
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
new file mode 100644
index 0000000000..327ce9f9cb
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
@@ -0,0 +1,95 @@
+/** @file
+ Header file for Virtual Keyboard driver name.
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_
+#define _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_
+
+#include <Uefi.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that 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.
+ @param[out] DriverName 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 an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle 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[in] ChildHandle 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[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller 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.
+ @param[out] ControllerName 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/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b64d62034817e7407120ee2181c935e07bef5a8c
GIT binary patch
literal 330454
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
literal 0
HcmV?d00001
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b940505c8bc74ad6550bc322629d7975c1e1c1fc
GIT binary patch
literal 5454
zcmdUyTS!(}6o56!L@l#1k<1H~<*msK=EYIGfJHUFgo!=$AR-O~g3Ln$_Tv5C7@{FW
zuaziT6L~3b87f|a5!5uTbW}2D5<@ff*ZKTcvp6&*5#z(Z`TxV--&uR@b@o|%t#u-Q
zirH&rZa;AK<^LmpPyW_cZd|Rb+&<nn4?bRUiz^!H>wdS8R##V7QBl$K<d1cWYA;{D
ztZVAFD3jL*2L~Hl`%J6LZf@c|8xF%GjEsyJ{RdKAU2P;=(N9lLXQANWU{&7M)&|ib
zoyp0`=g*%vw)L&AuN^pWKyM*7F)?9hXD7tQ#s+ft?p+nwqR!Q;S6L`LJY4m6b#+0u
zZ{MzDW@ct|bX06Ubm)+BvDx0<UI<el_wL<Ofi3EY%@Gk1s$XojwY3#uZEbDoHhXz_
z>C>^R<KyGTHv*}xtyO_7>J%0hvQTJfsOs<N=zy@jN?yNyjc+ux_O7p)LPA3J?c3++
z>FMO;BsL#Bc+kVc!`<E8$Hxa!UtjO&=*XjOQDfb*vN9GrckZ04t1GKGI5_n5^gz75
zz4!0mk1<@|ym`YJtZUwgb&HFO@87>)T3UMd?j1wg!omWC#w~`ctE&(Mwy2?ed3l+I
z(9eooA!}=E5V1`y85$b0#P}@x{Fk}?ZEkdDXJ>gplgWhtz!<)L`xf%y!v{{T5P2hW
zb93B<z*kmQkfDzTuFPdf69FJ^mLXzvM9KX8JOoujm?BD8PG%vdO{TNY4Xu4^rqvTC
zPVC;jd#|}UJ39vk2J&_W1_pNR+U4Tnf+xqv$D_QmvU10c9Y_%gFI~C>NlHq>@sNRc
zcW<~^OiawqojboXH;fq@8{?$x*|P_=etv!kG&D5G6vWP+JqzLViCT`^qeqV*iHV8G
zh&^&eA4+&A%_;b~o=rNWMV^-|sqoaPQ>eOg=Z+Grg~Y|hDe3L)g%}S$PWa-*i*4Js
zi40~VK%Jvg$RLo+%uFR>vr(<yqVuKr%q>nRhmN<P@@LMRK{@-ZBsn=5a^b=SC4GIQ
z)OBN0;AK(Lu!kbUjv+t@(kW3<QIPEHY$Z)iO`oXMTbtw*WGupFBC|dY9X15tz@HUH
zM@RGcw{PE8g3Cc-V`G(wZxHI0;2Zd}4kh?Mc<?|;SXdZJGBPrhJbd^Na{l~zCB_c^
ztU2ZM>C+sL@6FBM-=9}Th`={|eSMD}J$m@?VL5SB9aK{g>XWpzG?ZVye3?E3{`Bcn
zNJ2uwkt0Vq#Wcdgt5>f$-~j;vsKsp%XlZF7Pca3tix)3K%FD}{&f+AF_V#v2YHBJn
zVvk(Wh7v*tHK#?!XA7+P>zg-nI@L&PYb!N2hngXN$Qy*v=s<WW#8m`{MMOvlbrik_
zflIXS?CeAsLNr5wCQ2ZUjg1V+&N%bq$BzjP{r&wA5{IZo6%hu)p=fSy7PXRb5XKA$
zoHY0B*)!^AlWB#7qOQ(FtkNMJh%w5gq@+M{b8}UOyAX1R5<(?JhoWR^YD&q;lP3|V
zsi{#S-zoUH5={L>3EwH-R`XxEas^eTrKPI;{{8!qpr9ZnQr?h2l^{Sy(4iz&W2}~%
zKQb~>Wu)fU@V-fWMmgVBn|!By$>w9nj_Gn@Gx=A^SK4e$N&n+_%GcZc4g36Gn?JkH
z)JPOL#tkth0ytY#RaK<|1W!moL4gwPLX1VrXZ?A4dRnJQF<|^OCWE8o`0?W^Be7bC
zbT|?CbA8K3+_-V$2JTc+Qj(LC!;lK|w}0EUYu6y0N^a55&(G)JL->fu%gckXmPC@9
zH*Xdf7emNv;v1p^wPFv|JGT&^kmF+wC2USsRu+U4EuL`e)~%wVA_yD{kzt4)l+dAo
p86F<C#GKOBxe+HVs7?Mk@$)bFIfd8L^U5+T;g?l#J@wbDe*hRVpnL!T
literal 0
HcmV?d00001
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
new file mode 100644
index 0000000000..6dac373f9e
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
@@ -0,0 +1,1409 @@
+/** @file
+ Virtural Keyboard Control Engine
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VirtualKeyboard.h"
+
+/**
+ Notify all keyboards pressed specific key need to hidden Virtual
+ Keyboard.
+
+ @param[in] KeyData Keyboard pressed specific key data
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_NOT_FOUND Not found Virtual Keyboard protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+VkNotifyKeyCallback (
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+ UINT32 HorizontalPixel;
+ UINT32 VerticalPixel;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback Start\n"));
+
+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, (VOID **) &VkContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ HorizontalPixel = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;
+ VerticalPixel = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
+
+ //
+ // CursorRow and CursorColumn are started from 0, so need to add 2 not 1.
+ //
+ if (((UINTN)(gST->ConOut->Mode->CursorColumn * EFI_GLYPH_WIDTH) < VkContext->SimIconBackWidth) &&
+ ((UINTN)((gST->ConOut->Mode->CursorRow + 2) * EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext->SimIconBackHeight))) {
+ SaveVkIconBackgroundBltBuffer (VkContext, VkDisplayAttributeSimpleBottom);
+ } else if (((UINTN)((gST->ConOut->Mode->CursorColumn + 2) * EFI_GLYPH_WIDTH) > (HorizontalPixel - VkContext->FullIconBackWidth)) &&
+ ((UINTN)((gST->ConOut->Mode->CursorRow + 2) * EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext->FullIconBackHeight))){
+ SaveVkIconBackgroundBltBuffer (VkContext, VkDisplayAttributeFullBottom);
+ }
+
+ //
+ // Hide icon/keyboard to prevent screen scroll up.
+ //
+ if ((KeyData->Key.UnicodeChar == CHAR_CARRIAGE_RETURN) ||
+ (KeyData->Key.ScanCode == SCAN_ESC) ||
+ ((gST->ConOut->Mode->CursorColumn >= (INT32) (MaxColumn - 2)) &&
+ (gST->ConOut->Mode->CursorRow == (INT32) (MaxRow - 1)))) {
+ HideVkBody (VkContext);
+ HideVkIcon (VkContext);
+ VkContext->IconReDrawCheck = 0;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback End\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Judge whether is a registed key.
+
+ @param[in] RegsiteredData A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was registered.
+ @param[in] 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;
+}
+
+/**
+ Pop the key from the keybuffer.
+
+ @param[in, out] VkContext Address of an VK_CONTEXT structure.
+ @param[out] KeyData The EFI stand key infomation when code get the key will put
+ correct mapping key.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY The keystroke data is empty.
+
+**/
+EFI_STATUS
+VkPopTheKey (
+ IN OUT VK_CONTEXT *VkContext,
+ OUT EFI_KEY_DATA *KeyData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 IndexSt;
+ UINT8 IndexEd;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Start\n"));
+ //
+ // KeyBuffer
+ // [ 0 ]
+ // [ 1 ]<-*IndexSt/IndexEd
+ // [ 2 ]
+ // [ ... ]
+ // [MAX_KEY_BUF_SIZE - 1]
+ //
+ Status = EFI_SUCCESS;
+ IndexSt = VkContext->KeyStartIndex;
+ IndexEd = VkContext->KeyEndIndex;
+
+ if (IndexEd == IndexSt) {
+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Keyboard buffer is empty.\n"));
+ Status = EFI_NOT_READY;
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey Unicode: %08x\n", VkContext->Keybuffer[IndexSt].Key.UnicodeChar));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ScanCode: %08x\n", VkContext->Keybuffer[IndexSt].Key.ScanCode));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ShiftState: %08x\n", VkContext->Keybuffer[IndexSt].KeyState.KeyShiftState));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ToggleState:%08x\n", VkContext->Keybuffer[IndexSt].KeyState.KeyToggleState));
+
+ if (KeyData != NULL) {
+ *KeyData = VkContext->Keybuffer[IndexSt];
+ }
+ VkContext->KeyStartIndex = ++IndexSt % MAX_KEY_BUF_SIZE;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey End\n"));
+ return Status;
+}
+
+/**
+ Push the event mapping key index to the input key buffer.
+
+ @param[in, out] VkContext Address of an VK_CONTEXT structure.
+ @param[in] Unicode The font's unicode number.
+
+ @retval EFI_SUCCESS The maping key index did put the key buffer.
+
+**/
+EFI_STATUS
+VkPushTheKey (
+ IN OUT VK_CONTEXT *VkContext,
+ IN UINT16 Unicode
+ )
+{
+ UINT8 IndexSt;
+ UINT8 IndexEd;
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ VK_NOTIFY *CurrentNotify;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPushTheKey Start\n"));
+ //
+ // KeyBuffer
+ // [ 0 ]
+ // [ 1 ]<-IndexSt/*IndexEd
+ // [ 2 ]
+ // [ ... ]
+ // [MAX_KEY_BUF_SIZE - 1]
+ //
+ IndexSt = VkContext->KeyStartIndex;
+ IndexEd = VkContext->KeyEndIndex;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Check Keyboard Buffer if is full that will pop the first key
+ //
+ if (VkContext->IsSupportPartialKey &&
+ ((VkContext->KeyEndIndex + 2) % MAX_KEY_BUF_SIZE) == IndexSt) {
+ VkPopTheKey (VkContext, NULL);
+ }
+
+ if (((VkContext->KeyEndIndex + 1) % MAX_KEY_BUF_SIZE) == IndexSt) {
+ VkPopTheKey (VkContext, NULL);
+ }
+
+ KeyData.Key.ScanCode = SCAN_NULL;
+ KeyData.Key.UnicodeChar = CHAR_NULL;
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ KeyData.KeyState.KeyToggleState = VkContext->KeyToggleState;
+ KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
+ KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ? EFI_CAPS_LOCK_ACTIVE : 0;
+
+ switch (Unicode) {
+ case VkKeyShift:
+ VkContext->IsShiftKeyFlag = !VkContext->IsShiftKeyFlag;
+ if (VkContext->PageNumber >= VkPage2 && VkContext->PageNumber <= VkPage3) {
+ VkContext->IsShiftKeyFlag ? VkContext->PageNumber++ : VkContext->PageNumber--;
+ }
+ VkContext->IsRedrawUpdateUI = TRUE;
+ break;
+
+ case VkKeyTwoPage:
+ switch (VkContext->PageNumber) {
+ case VkPage0:
+ case VkPage1:
+ VkContext->IsShiftKeyFlag = FALSE;
+ VkContext->PageNumber = VkContext->IsShiftKeyFlag ? VkPage3 : VkPage2;
+ break;
+
+ case VkPage2:
+ case VkPage3:
+ VkContext->IsShiftKeyFlag = FALSE;
+ VkContext->PageNumber = VkContext->IsCapsLockFlag ? VkPage1 : VkPage0;
+ break;
+
+ default:
+ break;
+ }
+ VkContext->IsRedrawUpdateUI = TRUE;
+ break;
+
+ case VkKeyCapslock:
+ VkContext->IsCapsLockFlag = !VkContext->IsCapsLockFlag;
+ if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber <= VkPage1) {
+ VkContext->IsCapsLockFlag ? VkContext->PageNumber++ : VkContext->PageNumber--;
+ }
+ KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
+ KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ? EFI_CAPS_LOCK_ACTIVE : 0;
+ VkContext->IsRedrawUpdateUI = TRUE;
+ break;
+
+ default:
+ if ((Unicode & VkKeyScanMask) != 0) {
+ KeyData.Key.ScanCode = Unicode & ~VkKeyScanMask;
+ } else {
+ KeyData.Key.UnicodeChar = Unicode;
+ }
+ break;
+ }
+
+ if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
+ if (!VkContext->IsSupportPartialKey) {
+ goto End;
+ }
+ }
+
+ for (Link = GetFirstNode (&VkContext->NotifyList); !IsNull (&VkContext->NotifyList, Link); Link = GetNextNode (&VkContext->NotifyList, Link)) {
+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);
+ //
+ // The key notification function needs to run at TPL_CALLBACK
+ // while current TPL is TPL_NOTIFY. It will be invoked in
+ // VkKeyNotifyProcessHandler() which runs at TPL_CALLBACK.
+ //
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+ VkContext->Keybuffer[IndexEd] = KeyData;
+ VkContext->KeyEndIndex = ++IndexEd % MAX_KEY_BUF_SIZE;
+ gBS->SignalEvent (VkContext->KeyNotifyProcessEvent);
+ }
+ }
+ VkContext->Keybuffer[IndexEd] = KeyData;
+ VkContext->KeyEndIndex = ++IndexEd % MAX_KEY_BUF_SIZE;
+
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey Success, Status: %r\n", Status));
+ goto End;
+
+End:
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey End\n"));
+ return Status;
+}
+
+/**
+ Process key notify.
+
+ @param[in] Event Indicates the event that invoke this function.
+ @param[in] Context Indicates the calling context.
+
+**/
+VOID
+EFIAPI
+VkKeyNotifyProcessHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+ EFI_KEY_DATA KeyData;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NotifyList;
+ VK_NOTIFY *CurrentNotify;
+ EFI_TPL OldTpl;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Start\n"));
+ VkContext = (VK_CONTEXT *) Context;
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Invoke notification functions.
+ //
+ NotifyList = &VkContext->NotifyList;
+ Status = VkPopTheKey (VkContext, &KeyData);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+ CurrentNotify->KeyNotificationFn (&KeyData);
+ }
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Failed, Status: %r\n", Status));
+
+End:
+ gBS->RestoreTPL (OldTpl);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler End\n"));
+}
+
+/**
+ Push the event mapping key index to the input key buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[out] KeyItem Key Item.
+ @param[out] Index Index of Key Item.
+ @param[in] TouchX X position of finger touch.
+ @param[in] TouchY Y position of finger touch.
+
+ @retval TRUE Touch on Virtual Keyboard.
+ @retval FALSE Not touch on Virtual Keyboard.
+
+**/
+BOOLEAN
+IsTouchVk (
+ IN VK_CONTEXT *VkContext,
+ OUT VK_STRUCT *KeyItem,
+ OUT UINT32 *Index,
+ IN UINT32 TouchX,
+ IN UINT32 TouchY
+ )
+{
+ for (*Index = 0; *Index < VkContext->NumOfKeysInfo; (*Index)++) {
+ if (VkContext->KeyboardBodyPtr[*Index].DisStartX < TouchX &&
+ VkContext->KeyboardBodyPtr[*Index].DisEndX > TouchX &&
+ VkContext->KeyboardBodyPtr[*Index].DisStartY < TouchY &&
+ VkContext->KeyboardBodyPtr[*Index].DisEndY > TouchY) {
+ break;
+ }
+ }
+ if (*Index != VkContext->NumOfKeysInfo) {
+ *KeyItem = VkContext->KeyboardBodyPtr[*Index];
+ }
+
+ return *Index != VkContext->NumOfKeysInfo;
+}
+
+/**
+ Call back function when ready to boot into OS.
+
+ It will clear the Virtual Keyboard.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the VkContext.
+
+**/
+VOID
+EFIAPI
+VkReadyToBootCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VK_CONTEXT *VkContext;
+ VkContext = (VK_CONTEXT *)Context;
+
+ HideVkBody (VkContext);
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+}
+
+/**
+ Timer event
+
+ This routine is called at TPL_VK_SYNC.
+
+ This routine polls for touch panel input.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context,
+ which is implementation-dependent. Context corresponds
+ to NotifyContext in CreateEventEx().
+
+**/
+VOID
+EFIAPI
+VkTimer (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
+ EFI_ABSOLUTE_POINTER_STATE Point;
+ EFI_STATUS Status;
+ UINT32 TouchX;
+ UINT32 TouchY;
+ VK_CONTEXT *VkContext;
+ UINT32 Index;
+ VK_STRUCT KeyItem;
+ UINT32 Font;
+
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Start\n"));
+ VkContext = (VK_CONTEXT *)Context;
+
+ //
+ // Update keyboard UI layout
+ //
+ CheckIconCleared (VkContext);
+ CheckScreenCleared (VkContext);
+ CheckBackgroundChanged (VkContext);
+ if (VkContext->IsRedrawUpdateUI) {
+ HideVkBody (VkContext);
+ DrawKeyboardLayout (VkContext);
+ VkContext->IsRedrawUpdateUI = FALSE;
+ }
+
+ //
+ // Error handle for invalid information
+ //
+ AbsolutePointer = VkContext->AbsolutePointer;
+ Status = gBS->CheckEvent (AbsolutePointer->WaitForInput);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR - VkContext->AbsolutePointer->WaitForInput->CheckEvent failed! Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = AbsolutePointer->GetState (AbsolutePointer, &Point);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR - GetState failed, Status: %r\n", Status));
+ goto Error;
+ }
+
+ if (VkContext->AbsolutePointer->Mode->AbsoluteMaxX <= Point.CurrentX) {
+ DEBUG ((
+ DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "ERROR - X value exceeds maximum: X: 0x%016Lx, MaxX: 0x%016Lx\n",
+ Point.CurrentX,
+ VkContext->AbsolutePointer->Mode->AbsoluteMaxX
+ ));
+ Status = EFI_PROTOCOL_ERROR;
+ goto Error;
+ }
+ if (VkContext->AbsolutePointer->Mode->AbsoluteMaxY <= Point.CurrentY) {
+ DEBUG ((
+ DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "ERROR - Y value exceeds maximum: Y: 0x%016Lx, MaxY: 0x%016Lx\n",
+ Point.CurrentY,
+ VkContext->AbsolutePointer->Mode->AbsoluteMaxY
+ ));
+ Status = EFI_PROTOCOL_ERROR;
+ goto Error;
+ }
+
+ //
+ // Update the touch active status
+ //
+ VkContext->TouchActive = ((Point.ActiveButtons & EFI_ABSP_TouchActive) != 0) ? TRUE : FALSE;
+ if (!VkContext->TouchActive) {
+ VkContext->KeyPressed = FALSE;
+ }
+ ConvertCoordinate (VkContext, Point, &TouchX, &TouchY);
+
+ if (!VkContext->KeyPressed &&
+ VkContext->TouchActive &&
+ IsTouchVk (VkContext, &KeyItem, &Index, TouchX, TouchY)) {
+ VkGetMappingFont (VkContext, KeyItem, &Font);
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO, "VK Touch event is trigger!\n" ));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "TouchActive: 0x%04x \n", VkContext->TouchActive));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "CurrentKeyboardDisplay: 0x%04x \n", VkContext->CurrentKeyboardDisplay));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "X: 0x%016Lx\n", Point.CurrentX));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Y: 0x%016Lx\n", Point.CurrentY));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Z: 0x%016Lx\n", Point.CurrentZ));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Buttons: 0x%08x \n", Point.ActiveButtons));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "MapKey Index: 0x%04x \n", Index));
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Key Unicode: 0x%08x \n", Font));
+
+ switch (Font) {
+ //
+ // Touch the small keyboard icon, show/hide the keyboard.
+ //
+ case VkKeyTypeMaximum:
+ KeyboardLayoutHandler (VkContext, Index);
+ break;
+
+ //
+ // Touch the key raw.
+ //
+ default:
+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) {
+ break;
+ }
+ VkPushTheKey (VkContext, (UINT16) Font);
+ }
+ VkContext->KeyPressed = TRUE;
+ }
+
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer End\n"));
+ return;
+}
+
+/**
+ VkTouchWaitForKey - SignalEvent when the keybuffer has keys.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context,
+ which is implementation-dependent. Context corresponds
+ to NotifyContext in CreateEventEx().
+
+**/
+VOID
+EFIAPI
+VkTouchWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VK_CONTEXT *VkContext;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey Start\n"));
+ VkContext = (VK_CONTEXT*) Context;
+
+ if (VkContext->KeyStartIndex != VkContext->KeyEndIndex) {
+ DEBUG ((DEBUG_VK_KEYS, "Signal VkTouchWaitForKey\n"));
+ gBS->SignalEvent (Event);
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey End\n"));
+}
+
+/**
+ Get image file data from BIOS image through specific ImageId.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] ImageId Guid to get specific image file used.
+
+ @retval EFI_IMAGE_INPUT Image data on BIOS image.
+
+**/
+EFI_IMAGE_INPUT*
+VkGetImage (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_IMAGE_ID ImageId
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_INPUT Image;
+ EFI_IMAGE_INPUT *VkImage;
+
+
+ Status = VkContext->HiiImageEx->GetImageEx (
+ VkContext->HiiImageEx,
+ VkContext->HiiHandle,
+ ImageId,
+ &Image
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ VkImage = AllocateCopyPool (sizeof (EFI_IMAGE_INPUT), &Image);
+ if (VkImage == NULL) {
+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+ return NULL;
+ }
+
+ return VkImage;
+}
+
+/**
+ Dump partial debug message on VkContext.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+
+**/
+VOID
+VkDumpContext (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT,
+ "VkContext->Signature: 0x%016x\n",
+ VkContext->Signature
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT,
+ "VkContext->Controller: 0x%016x\n",
+ VkContext->Controller
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
+ "VkContext->GraphicsOutput->Mode->MaxMode: 0x%08x\n",
+ VkContext->GraphicsOutput->Mode->MaxMode
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
+ "VkContext->GraphicsOutput->Mode->Mode: 0x%08x\n",
+ VkContext->GraphicsOutput->Mode->Mode
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
+ "VkContext->GraphicsOutput->Mode->Info->HorizontalResolution: 0x%08x\n",
+ VkContext->GraphicsOutput->Mode->Info->HorizontalResolution
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
+ "VkContext->GraphicsOutput->Mode->Info->VerticalResolution: 0x%08x\n",
+ VkContext->GraphicsOutput->Mode->Info->VerticalResolution
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "VkContext->AbsolutePointer->Mode X: 0x%016Lx - 0x%016Lx\n",
+ VkContext->AbsolutePointer->Mode->AbsoluteMinX,
+ VkContext->AbsolutePointer->Mode->AbsoluteMaxX
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "VkContext->AbsolutePointer->Mode Y: 0x%016Lx - 0x%016Lx\n",
+ VkContext->AbsolutePointer->Mode->AbsoluteMinY,
+ VkContext->AbsolutePointer->Mode->AbsoluteMaxY
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "VkContext->AbsolutePointer->Mode Z: 0x%016Lx - 0x%016Lx\n",
+ VkContext->AbsolutePointer->Mode->AbsoluteMinZ,
+ VkContext->AbsolutePointer->Mode->AbsoluteMaxZ
+ ));
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
+ "VkContext->AbsolutePointer->Mode->Attributes: 0x%08x\n",
+ VkContext->AbsolutePointer->Mode->Attributes
+ ));
+}
+
+/**
+ Start the virtual keyboard driver
+
+ This routine allocates the necessary resources for the driver.
+
+ This routine is called by VirtualKeyboardDriverStart to complete the driver
+ initialization.
+
+ @param[in, out] VkContext Address of an VK_CONTEXT structure
+ @param[in] Controller Handle of device to work with.
+
+ @retval EFI_SUCCESS Driver API properly initialized
+
+**/
+EFI_STATUS
+VkApiStart (
+ IN OUT VK_CONTEXT *VkContext,
+ IN EFI_HANDLE Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+ EFI_KEY_DATA KeyData;
+ EFI_HANDLE NotifyHandle;
+ EFI_EVENT ReadyToBootEvent;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Start\n"));
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ VkKeyNotifyProcessHandler,
+ VkContext,
+ &VkContext->KeyNotifyProcessEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext->KeyNotifyProcessEvent, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ VkTouchWaitForKey,
+ VkContext,
+ &(VkContext->SimpleTextIn.WaitForKey)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext->SimpleTextIn.WaitForKey, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ VkTouchWaitForKey,
+ VkContext,
+ &(VkContext->SimpleTextInEx.WaitForKeyEx)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext->SimpleTextInEx.WaitForKeyEx, Status %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_VK_SYNC,
+ VkTimer,
+ (VOID *)VkContext,
+ &(VkContext->TimerEvent)
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create the timer event, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->SetTimer (
+ VkContext->TimerEvent,
+ TimerPeriodic,
+ (UINT64) VK_POLL_INTERVAL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to set the timer event, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Create event to clear keyboard before boot into OS.
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ VkReadyToBootCallBack,
+ (VOID *)VkContext,
+ &ReadyToBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create ReadyToBootEvent, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiImageExProtocolGuid,
+ NULL,
+ (VOID **) &VkContext->HiiImageEx
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to open HiiImageEx protocol, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Initialize VkContext
+ //
+ VkContext->Signature = VK_SIGNATURE;
+ VkContext->Controller = Controller;
+ VkContext->SimpleTextIn.Reset = VkKeyboardReset;
+ VkContext->SimpleTextIn.ReadKeyStroke = VkKeyboardReadKeyStroke;
+ VkContext->SimpleTextInEx.Reset = VkKeyboardResetEx;
+ VkContext->SimpleTextInEx.ReadKeyStrokeEx = VkKeyboardReadKeyStrokeEx;
+ VkContext->SimpleTextInEx.SetState = VkKeyboardSetState;
+ VkContext->SimpleTextInEx.RegisterKeyNotify = VkKeyboardRegisterKeyNotify;
+ VkContext->SimpleTextInEx.UnregisterKeyNotify = VkKeyboardUnregisterKeyNotify;
+ VkContext->IsIconShowed = FALSE;
+ VkContext->IsBackgroundChanged = FALSE;
+ VkContext->PageNumber = 0;
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+ VkContext->VkBodyBackgroundBltBuffer = NULL;
+ VkContext->VkBodyCompoundBltBuffer = NULL;
+ VkContext->VkBodyBltSize = 0;
+ VkContext->VkBodyBltStartX = 0;
+ VkContext->VkBodyBltStartY = 0;
+ VkContext->VkBodyBltHeight = 0;
+ VkContext->VkBodyBltWidth = 0;
+ VkContext->IconBltBuffer = NULL;
+ VkContext->IconBltSize = 0;
+ VkContext->IconReDrawCheck = 0;
+ VkContext->FullIconUpdatedFlag = FALSE;
+ VkContext->SimIconUpdatedFlag = FALSE;
+ VkContext->KeyStartIndex = 0;
+ VkContext->KeyEndIndex = 0;
+ VkContext->KeyToggleState = EFI_TOGGLE_STATE_VALID;
+ VkContext->SmallIcon = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_SIMPLEICON));
+ VkContext->FullIcon = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_FULLICON));
+ VkContext->SimKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_SIMPLEKEYBOARD));
+ VkContext->DigKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_DIGITKEYBOARD));
+ VkContext->CapLeKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_CAPITALLETTERKEYBOARD));
+
+ InitializeListHead (&VkContext->NotifyList);
+
+ Status = SetCharacterPosition (VkContext, 800, 600);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = DrawKeyboardLayout (VkContext);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = HideVkBody (VkContext);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = HideVkIcon (VkContext);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE (
+ VkDumpContext (VkContext);
+ );
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID **)&SimpleEx
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to found ConIn Protocol, Status: %r\n", Status));
+ goto Error;
+ }
+
+ KeyData.KeyState.KeyToggleState = 0;
+ KeyData.KeyState.KeyShiftState = 0;
+ KeyData.Key.ScanCode = SCAN_ESC;
+ KeyData.Key.UnicodeChar = CHAR_NULL;
+ NotifyHandle = NULL;
+ Status = SimpleEx->RegisterKeyNotify (
+ SimpleEx,
+ &KeyData,
+ VkNotifyKeyCallback,
+ &NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to register 'Esc', Status: %r\n", Status));
+ goto Error;
+ }
+
+ KeyData.KeyState.KeyToggleState = 0;
+ KeyData.KeyState.KeyShiftState = 0;
+ KeyData.Key.ScanCode = SCAN_NULL;
+ KeyData.Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ Status = SimpleEx->RegisterKeyNotify (
+ SimpleEx,
+ &KeyData,
+ VkNotifyKeyCallback,
+ &NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to register 'Enter', Status: %r\n", Status));
+ goto Error;
+ }
+
+ for (KeyData.Key.UnicodeChar = L' '; KeyData.Key.UnicodeChar <= L'~'; KeyData.Key.UnicodeChar++) {
+ Status = SimpleEx->RegisterKeyNotify (
+ SimpleEx,
+ &KeyData,
+ VkNotifyKeyCallback,
+ &NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR,
+ "ERROR - Failed to register '%c', Status: %r\n",
+ KeyData.Key.UnicodeChar,
+ Status
+ ));
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ VkApiStop (VkContext);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart End\n"));
+ return Status;
+}
+
+/**
+ Stop the virtual keyboard driver
+
+ This routine releases the resources allocated by VKApiStart.
+
+ This routine is called by VirtualKeyboardDriverStop to initiate the driver
+ shutdown.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure
+
+**/
+VOID
+VkApiStop (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+ VK_NOTIFY *NotifyNode;
+ LIST_ENTRY *NotifyList;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop Start\n"));
+
+ Status = gBS->SetTimer (VkContext->TimerEvent, TimerCancel, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ if (VkContext->KeyNotifyProcessEvent != NULL) {
+ Status = gBS->CloseEvent (VkContext->KeyNotifyProcessEvent);
+ ASSERT_EFI_ERROR (Status);
+ VkContext->KeyNotifyProcessEvent = NULL;
+ }
+
+ if (VkContext->TimerEvent != NULL) {
+ Status = gBS->CloseEvent (VkContext->TimerEvent);
+ ASSERT_EFI_ERROR (Status);
+ VkContext->TimerEvent = NULL;
+ }
+
+ if (VkContext->SimpleTextIn.WaitForKey != NULL) {
+ Status = gBS->CloseEvent (VkContext->SimpleTextIn.WaitForKey);
+ ASSERT_EFI_ERROR (Status);
+ VkContext->SimpleTextIn.WaitForKey = NULL;
+ }
+
+ if (VkContext->SimpleTextInEx.WaitForKeyEx != NULL) {
+ Status = gBS->CloseEvent (VkContext->SimpleTextInEx.WaitForKeyEx);
+ ASSERT_EFI_ERROR (Status);
+ VkContext->SimpleTextInEx.WaitForKeyEx = NULL;
+ }
+
+ NotifyList = &VkContext->NotifyList;
+ if (NotifyList != NULL) {
+ while (!IsListEmpty (NotifyList)) {
+ NotifyNode = CR (NotifyList->ForwardLink, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);
+ RemoveEntryList (NotifyList->ForwardLink);
+ gBS->FreePool (NotifyNode);
+ }
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop End\n"));
+}
+
+/**
+ Reset the input device and optionally run diagnostics
+
+ @param[in] This Protocol instance pointer.
+ @param[in] 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
+VkKeyboardReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset Start\n"));
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset End\n"));
+ return Status;
+}
+
+/**
+ Resets the input device hardware.
+
+ The Reset() function resets the input device hardware. As part
+ of initialization process, the firmware/device will make a quick
+ but reasonable attempt to verify that the device is functioning.
+ If the ExtendedVerification flag is TRUE the firmware may take
+ an extended amount of time to verify the device is operating on
+ reset. Otherwise the reset operation is to occur as quickly as
+ possible. The hardware verification process is not defined by
+ this specification and is left up to the platform firmware or
+ driver to implement.
+
+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Start\n"));
+
+ Status = EFI_SUCCESS;
+ if (This == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
+
+ Status = VkContext->SimpleTextIn.Reset (&VkContext->SimpleTextIn, ExtendedVerification);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VK reset, Status: %r\n", Status));
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx End\n"));
+ return Status;
+}
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existence of a keystroke via WaitForEvent () call.
+
+ @param[in] This Protocol instance pointer.
+ @param[out] Key Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data available.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+ EFI_KEY_DATA TmpKeyData;
+ EFI_TPL OldTpl;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Start\n"));
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ if (This == NULL || Key == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ VkContext = VK_CONTEXT_FROM_PROTOCOL (This);
+
+ Status = VkKeyboardReadKeyStrokeEx (&VkContext->SimpleTextInEx, &TmpKeyData);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ *Key = TmpKeyData.Key;
+
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Failed, Status: %r\n", Status));
+
+End:
+ gBS->RestoreTPL (OldTpl);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke End\n"));
+ return Status;
+}
+
+/**
+ Reads the next keystroke from the input device.
+
+ @param[in] This Protocol instance pointer.
+ @param[out] 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 available.
+ @retval EFI_INVALID_PARAMETER This or KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ )
+{
+ VK_CONTEXT *VkContext;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ EFI_KEY_DATA TmpKeyData;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Start\n"));
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ if (This == NULL || KeyData == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
+
+ while (TRUE) {
+ Status = VkPopTheKey (VkContext, &TmpKeyData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VkPopTheKey check whether keybuffer is empty, Status: %r\n", Status));
+ goto Error;
+ }
+ if (TmpKeyData.Key.ScanCode != SCAN_NULL || TmpKeyData.Key.UnicodeChar != CHAR_NULL) {
+ break;
+ }
+ }
+ *KeyData = TmpKeyData;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Failed, Status: %r\n", Status));
+
+End:
+ gBS->RestoreTPL (OldTpl);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx End\n"));
+ return Status;
+}
+
+/**
+ Set certain state for the input device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] 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 appropriately.
+ @retval EFI_INVALID_PARAMETER This or KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Start\n"));
+
+ Status = EFI_SUCCESS;
+ if (This == NULL || KeyToggleState == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
+
+ VkContext->KeyToggleState = *KeyToggleState;
+ VkContext->IsCapsLockFlag = (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE;
+ VkContext->IsSupportPartialKey = (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED;
+
+ if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber <= VkPage1) {
+ VkContext->PageNumber = VkContext->IsCapsLockFlag ? VkPage1 : VkPage0;
+ }
+
+ HideVkBody (VkContext);
+ DrawKeyboardLayout (VkContext);
+
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->KeyToggleState: %02x\n", VkContext->KeyToggleState));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->IsCapsLockFlag: %02x\n", VkContext->IsCapsLockFlag));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->IsSupportPartialKey: %02x\n", VkContext->IsSupportPartialKey));
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState End\n"));
+ return Status;
+}
+
+/**
+ Register a notification function for a particular keystroke for the input device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] KeyData A pointer to a buffer that is filled in with the keystroke
+ information data for the key that was pressed.
+ @param[in] KeyNotificationFunction Points to the function to be called when the key
+ sequence is typed specified by KeyData.
+ @param[out] 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 necessary data structures.
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ VK_CONTEXT *VkContext;
+ LIST_ENTRY *Link;
+ VK_NOTIFY *CurrentNotify;
+ VK_NOTIFY *NewNotify;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Start\n"));
+
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ if (This == NULL || KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
+
+
+ //
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
+ //
+ for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
+ *NotifyHandle = CurrentNotify;
+ Status = EFI_SUCCESS;
+ goto End;
+ }
+ }
+ }
+
+ //
+ // Allocate resource to save the notification function
+ //
+ NewNotify = (VK_NOTIFY *) AllocateZeroPool (sizeof (VK_NOTIFY));
+ if (NewNotify == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ NewNotify->Signature = VK_NOTIFY_SIGNATURE;
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
+ InsertTailList (&VkContext->NotifyList, &NewNotify->NotifyEntry);
+
+ *NotifyHandle = NewNotify;
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Failed, Status: %r\n", Status));
+
+End:
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify End\n"));
+ return Status;
+}
+
+/**
+ Remove a registered notification function from a particular keystroke.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] 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
+VkKeyboardUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ )
+{
+ EFI_STATUS Status;
+ VK_CONTEXT *VkContext;
+ EFI_TPL OldTpl;
+ LIST_ENTRY *Link;
+ VK_NOTIFY *CurrentNotify;
+ BOOLEAN IsFindNotifyHandle;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Start\n"));
+
+ //
+ // Enter critical section
+ //
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ if (This == NULL || NotificationHandle == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
+
+ IsFindNotifyHandle = FALSE;
+ for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);
+ if (CurrentNotify == NotificationHandle) {
+ //
+ // Remove the notification function from NotifyList and free resources
+ //
+ RemoveEntryList (&CurrentNotify->NotifyEntry);
+
+ gBS->FreePool (CurrentNotify);
+ IsFindNotifyHandle = TRUE;
+ break;
+ }
+ }
+
+ if (!IsFindNotifyHandle) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Failed, Status: %r\n", Status));
+
+End:
+ //
+ // Leave critical section and return
+ //
+ gBS->RestoreTPL (OldTpl);
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify End\n"));
+ return Status;
+}
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
new file mode 100644
index 0000000000..744c4324d3
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
@@ -0,0 +1,1438 @@
+/** @file
+ Virtural Keyboard Layout Engine
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VirtualKeyboard.h"
+
+//
+// 1.FullKeyboardBody
+// Follow below design
+// (1).\KeyboardLayout\CapitalLetterKeyboard.bmp
+// (2).\KeyboardLayout\DigitKeyboard.bmp
+// Based on keyboard's (startX, startY)
+//
+// Page0Font
+// +---+---+---+---+---+---+---+---+---+---+---+
+// | q | w | e | r | t | y | u | i | o | p |<X|| Line 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | | a | s | d | f | g | h | j | k | l | F2| | Line 1
+// +-+---+---+---+---+---+---+---+---+---+---+-+
+// |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2
+// +-----+---+---+---+---+---+---+---+---+---+-+
+// | Esc |12#| Space |aL |aD |aR | | Line 3
+// +-----+---+-------------------+---+---+---+-+
+//
+// Page1Font
+// +---+---+---+---+---+---+---+---+---+---+---+
+// | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | | A | S | D | F | G | H | J | K | L | F2| | Line 1
+// +-+---+---+---+---+---+---+---+---+---+---+-+
+// |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2
+// +-----+---+---+---+---+---+---+---+---+---+-+
+// | Esc |12#| Space |aL |aD |aR | | Line 3
+// +-----+---+-------------------+---+---+---+-+
+//
+// Page2Font
+// +---+---+---+---+---+---+---+---+---+---+---+
+// | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
+// +-+---+---+---+---+---+---+---+---+---+---+-+
+// |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2
+// +-----+---+---+---+---+---+---+---+---+---+-+
+// | Esc |12#| Space | \ | - | = | | Line 3
+// +-----+---+-------------------+---+---+---+-+
+//
+// Page3Font
+// +---+---+---+---+---+---+---+---+---+---+---+
+// | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
+// +-+---+---+---+---+---+---+---+---+---+---+-+
+// |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2
+// +-----+---+---+---+---+---+---+---+---+---+-+
+// | Esc |12#| Space | | | _ | + | | Line 3
+// +-----+---+-------------------+---+---+---+-+
+//
+// 2.Screen Corner
+// Follow below design
+// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
+// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D
+// +-+------------------------------------+-+
+// |A| |C|
+// +-+ +-+
+// | |
+// | |
+// | |
+// | |
+// | |
+// | |
+// +-+ +-+
+// |B| |D|
+// +-+------------------------------------+-+
+//
+VK_STRUCT mFullKeyboardBody[] = {
+ // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font
+ // Line 0
+ { 0x0000, 0x0000, 0x0032, 0x0032, {L'q', L'Q', L'1', L'!' }},
+ { 0x0032, 0x0000, 0x0064, 0x0032, {L'w', L'W', L'2', L'@' }},
+ { 0x0064, 0x0000, 0x0096, 0x0032, {L'e', L'E', L'3', L'#' }},
+ { 0x0096, 0x0000, 0x00C8, 0x0032, {L'r', L'R', L'4', L'$' }},
+ { 0x00C8, 0x0000, 0x00FA, 0x0032, {L't', L'T', L'5', L'%' }},
+ { 0x00FA, 0x0000, 0x012C, 0x0032, {L'y', L'Y', L'6', L'^' }},
+ { 0x012C, 0x0000, 0x015E, 0x0032, {L'u', L'U', L'7', L'&' }},
+ { 0x015E, 0x0000, 0x0190, 0x0032, {L'i', L'I', L'8', L'*' }},
+ { 0x0190, 0x0000, 0x01C2, 0x0032, {L'o', L'O', L'9', L'(' }},
+ { 0x01C2, 0x0000, 0x01F4, 0x0032, {L'p', L'P', L'0', L')' }},
+ { 0x01F4, 0x0000, 0x0226, 0x0032, {VkKeyBackspace, VkKeyBackspace, VkKeyBackspace, VkKeyBackspace }},
+ // Line 1
+ { 0x0000, 0x0032, 0x0019, 0x0064, {VkKeyNull, VkKeyNull, VkKeyNull, VkKeyNull }},
+ { 0x0019, 0x0032, 0x004B, 0x0064, {L'a', L'A', VkKeyF1, VkKeyF1 }},
+ { 0x004B, 0x0032, 0x007D, 0x0064, {L's', L'S', VkKeyF2, VkKeyF2 }},
+ { 0x007D, 0x0032, 0x00AF, 0x0064, {L'd', L'D', VkKeyF3, VkKeyF3 }},
+ { 0x00AF, 0x0032, 0x00E1, 0x0064, {L'f', L'F', VkKeyF4, VkKeyF4 }},
+ { 0x00E1, 0x0032, 0x0113, 0x0064, {L'g', L'G', VkKeyF5, VkKeyF5 }},
+ { 0x0113, 0x0032, 0x0145, 0x0064, {L'h', L'H', VkKeyF6, VkKeyF6 }},
+ { 0x0145, 0x0032, 0x0177, 0x0064, {L'j', L'J', VkKeyF7, VkKeyF7 }},
+ { 0x0177, 0x0032, 0x01A9, 0x0064, {L'k', L'K', VkKeyF8, VkKeyF8 }},
+ { 0x01A9, 0x0032, 0x01DB, 0x0064, {L'l', L'L', VkKeyF9, VkKeyF9 }},
+ { 0x01DB, 0x0032, 0x020D, 0x0064, {VkKeyF2, VkKeyF2, VkKeyF10, VkKeyF10 }},
+ // Line 2
+ { 0x0000, 0x0064, 0x004B, 0x0096, {VkKeyCapslock, VkKeyCapslock, VkKeyShift, VkKeyShift }},
+ { 0x004B, 0x0064, 0x007D, 0x0096, {L'z', L'Z', L'`', L'~' }},
+ { 0x007D, 0x0064, 0x00AF, 0x0096, {L'x', L'X', L';', L':' }},
+ { 0x00AF, 0x0064, 0x00E1, 0x0096, {L'c', L'C', L'\'', L'"' }},
+ { 0x00E1, 0x0064, 0x0113, 0x0096, {L'v', L'V', L',', L'<' }},
+ { 0x0113, 0x0064, 0x0145, 0x0096, {L'b', L'B', L'.', L'>' }},
+ { 0x0145, 0x0064, 0x0177, 0x0096, {L'n', L'N', L'/', L'?' }},
+ { 0x0177, 0x0064, 0x01A9, 0x0096, {L'm', L'M', VkKeyF11, VkKeyF11 }},
+ { 0x01A9, 0x0064, 0x01DB, 0x0096, {VkKeyUp, VkKeyUp, VkKeyF12, VkKeyF12 }},
+ { 0x01DB, 0x0064, 0x0226, 0x0096, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},
+ // Line 3
+ { 0x0000, 0x0096, 0x004B, 0x00C8, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},
+ { 0x004B, 0x0096, 0x007D, 0x00C8, {VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage }},
+ { 0x007D, 0x0096, 0x0177, 0x00C8, {L' ', L' ', L' ', L' ' }},
+ { 0x0177, 0x0096, 0x01A9, 0x00C8, {VkKeyLeft, VkKeyLeft, L'\\', L'|' }},
+ { 0x01A9, 0x0096, 0x01DB, 0x00C8, {VkKeyDown, VkKeyDown, L'-', L'_' }},
+ { 0x01DB, 0x0096, 0x020D, 0x00C8, {VkKeyRight, VkKeyRight, L'=', L'+' }},
+ // Screen Corner A
+ { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner B
+ { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner C
+ { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner D
+ { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}
+};
+
+//
+// 1.SimpleKeyboardBody
+// Follow below design
+// (1).\KeyboardLayout\SimpleKeyboard.bmp
+// Based on keyboard's (startX, startY)
+// +-----+-----+
+// | Esc |Enter| Line 0
+// +-----+-----+
+// | Up | Down| Line 1
+// +-----+-----+
+//
+// 2.Screen Corner
+// Follow below design
+// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
+// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D
+// +-+------------------------------------+-+
+// |A| |C|
+// +-+ +-+
+// | |
+// | |
+// | |
+// | |
+// | |
+// | |
+// +-+ +-+
+// |B| |D|
+// +-+------------------------------------+-+
+//
+VK_STRUCT mSimpleKeyboardBody[] = {
+ // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font
+ // Line 0
+ { 0x0000, 0x0000, 0x0032, 0x0032, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},
+ { 0x0032, 0x0000, 0x0064, 0x0032, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},
+ // Line 1
+ { 0x0000, 0x0032, 0x0032, 0x0064, {VkKeyUp, VkKeyUp, VkKeyUp, VkKeyUp }},
+ { 0x0032, 0x0032, 0x0064, 0x0064, {VkKeyDown, VkKeyDown, VkKeyDown, VkKeyDown }},
+ // Screen Corner A
+ { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner B
+ { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner C
+ { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
+ // Screen Corner D
+ { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}
+};
+
+/**
+ Modify the color of key if Shift or CapsLock is pressed.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in, out] BltBuffer Address of a blt buffer.
+
+ @retval EFI_SUCCESS Success for the function.
+
+**/
+EFI_STATUS
+ModifyShiftKeyColor (
+ IN VK_CONTEXT *VkContext,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempBltBuffer;
+ UINTN BltSize;
+ BOOLEAN IsPressed;
+
+ TempBltBuffer = *BltBuffer;
+ BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
+ IsPressed = VkContext->PageNumber <= VkPage1 ?
+ VkContext->IsCapsLockFlag :
+ VkContext->IsShiftKeyFlag;
+
+ while (BltSize-- != 0) {
+ //
+ // Color gradient issue
+ //
+ if (((TempBltBuffer->Red - TempBltBuffer->Green) > 0x20) &&
+ ((TempBltBuffer->Red - TempBltBuffer->Blue) > 0x20)) {
+ if (IsPressed) {
+ TempBltBuffer->Red = 0;
+ TempBltBuffer->Green = 255;
+ TempBltBuffer->Blue = 255;
+ } else {
+ TempBltBuffer->Red = 255;
+ TempBltBuffer->Green = 255;
+ TempBltBuffer->Blue = 255;
+ }
+ }
+ TempBltBuffer++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Make the keyboard transparent.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] IsTransparent TRUE for set keyboard transparent.
+ @param[in] BltIn Address of keyboard blt buffer.
+ @param[in, out] BltOut Address of output blt buffer.
+ NULL will allocate it.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+
+**/
+EFI_STATUS
+MakeKeyboardTransparent (
+ IN VK_CONTEXT *VkContext,
+ IN BOOLEAN IsTransparent,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltOut
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Keyboard;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
+ UINTN BltSize;
+
+ if (*BltOut == NULL) {
+ *BltOut = AllocateZeroPool (VkContext->VkBodyBltSize);
+ if (*BltOut == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ Compound = *BltOut;
+ Keyboard = BltIn;
+ Background = VkContext->VkBodyBackgroundBltBuffer;
+ BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
+ while (BltSize-- != 0) {
+ if (IsTransparent) {
+ Compound->Red = (Keyboard->Red * TRANSPARENCY_WEIGHT) / 100 + (Background->Red * (100 - TRANSPARENCY_WEIGHT)) / 100;
+ Compound->Green = (Keyboard->Green * TRANSPARENCY_WEIGHT) / 100 + (Background->Green * (100 - TRANSPARENCY_WEIGHT)) / 100;
+ Compound->Blue = (Keyboard->Blue * TRANSPARENCY_WEIGHT) / 100 + (Background->Blue * (100 - TRANSPARENCY_WEIGHT)) / 100;
+ } else {
+ *Compound = *Keyboard;
+ }
+ Compound++;
+ Keyboard++;
+ Background++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save the background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] BltSize Size of blt.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveVkBodyBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext,
+ IN UINTN BltSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBufferSave;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBufferSave;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
+ UINTN Size;
+
+ CurrentBltBufferSave = NULL;
+ OldBltBufferSave = NULL;
+
+ //
+ // Save original blt buffer first.
+ //
+ OldBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
+ if (OldBltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
+ CopyMem (OldBltBuffer, VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);
+ }
+
+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
+ VkContext->VkBodyBltSize = BltSize;
+ VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
+ ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else if (BltSize > VkContext->VkBodyBltSize) {
+ VkContext->VkBodyBltSize = BltSize;
+ FreePool (VkContext->VkBodyBackgroundBltBuffer);
+ VkContext->VkBodyBackgroundBltBuffer = NULL;
+ VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
+ ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ ZeroMem (VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);
+ }
+
+ CurrentBltBuffer = NULL;
+ if (VkContext->IsBackgroundChanged == TRUE) {
+ //
+ // Background changed, merge current visioning blt buffer with old background blt buffer.
+ //
+ Compound = VkContext->VkBodyCompoundBltBuffer;
+ Background = VkContext->VkBodyBackgroundBltBuffer;
+ CurrentBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
+ ASSERT (CurrentBltBuffer != NULL);
+ if (CurrentBltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ CurrentBltBuffer,
+ EfiBltVideoToBltBuffer,
+ VkContext->VkBodyBltStartX,
+ VkContext->VkBodyBltStartY,
+ 0,
+ 0,
+ VkContext->VkBodyBltWidth,
+ VkContext->VkBodyBltHeight,
+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ CurrentBltBufferSave = CurrentBltBuffer;
+ OldBltBufferSave = OldBltBuffer;
+ Size = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
+ while (Size-- != 0) {
+ if ((Compound->Red != CurrentBltBuffer->Red) ||
+ (Compound->Green != CurrentBltBuffer->Green) ||
+ (Compound->Blue != CurrentBltBuffer->Blue)) {
+ *Background = *CurrentBltBuffer;
+ } else {
+ *Background = *OldBltBuffer;
+ }
+ Compound++;
+ Background++;
+ CurrentBltBuffer++;
+ OldBltBuffer++;
+ }
+ } else {
+ //
+ // Background NOT changed, save it to VkBodyBackgroundBltBuffer directly.
+ //
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ VkContext->VkBodyBackgroundBltBuffer,
+ EfiBltVideoToBltBuffer,
+ VkContext->VkBodyBltStartX,
+ VkContext->VkBodyBltStartY,
+ 0,
+ 0,
+ VkContext->VkBodyBltWidth,
+ VkContext->VkBodyBltHeight,
+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ }
+
+ if (CurrentBltBufferSave != NULL) {
+ FreePool (CurrentBltBufferSave);
+ }
+ if (OldBltBufferSave != NULL) {
+ FreePool (OldBltBufferSave);
+ }
+
+ return Status;
+}
+
+/**
+ Restore the background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_UNSUPPORTED Input blt buffer is NULL.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RestoreVkBodyBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+
+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ VkContext->VkBodyBackgroundBltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ VkContext->VkBodyBltStartX,
+ VkContext->VkBodyBltStartY,
+ VkContext->VkBodyBltWidth,
+ VkContext->VkBodyBltHeight,
+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ FreePool (VkContext->VkBodyBackgroundBltBuffer);
+ VkContext->VkBodyBackgroundBltBuffer = NULL;
+
+ return Status;
+}
+
+/**
+ Set the position of character.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] DestX X position.
+ @param[in] DestY Y position.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+SetCharacterPosition (
+ IN VK_CONTEXT *VkContext,
+ IN UINT32 DestX,
+ IN UINT32 DestY
+ )
+{
+ UINTN Index;
+ VK_STRUCT *KeyArryPtr;
+ UINT32 KeyArrySize;
+
+ switch (VkContext->TargetKeyboardDisplay) {
+ case VkDisplayAttributeSimpleTop:
+ case VkDisplayAttributeSimpleBottom:
+ KeyArryPtr = mSimpleKeyboardBody;
+ KeyArrySize = DIM (mSimpleKeyboardBody);
+ break;
+
+ case VkDisplayAttributeFullBottom:
+ case VkDisplayAttributeFullTop:
+ KeyArryPtr = mFullKeyboardBody;
+ KeyArrySize = DIM (mFullKeyboardBody);
+ break;
+
+ case VkDisplayAttributeNone:
+ KeyArryPtr = mFullKeyboardBody;
+ KeyArrySize = DIM (mFullKeyboardBody);
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ for (Index = 0; Index < KeyArrySize; Index++) {
+ VkContext->KeyboardBodyPtr[Index] = KeyArryPtr[Index];
+ }
+ VkContext->NumOfKeysInfo = KeyArrySize;
+
+ for (Index = 0; Index < (VkContext->NumOfKeysInfo - 4); Index++) {
+ VkContext->KeyboardBodyPtr[Index].DisStartX += (UINT16)DestX;
+ VkContext->KeyboardBodyPtr[Index].DisStartY += (UINT16)DestY;
+ VkContext->KeyboardBodyPtr[Index].DisEndX += (UINT16)DestX;
+ VkContext->KeyboardBodyPtr[Index].DisEndY += (UINT16)DestY;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save the icon background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] IconType The icon type.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveVkIconBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext,
+ IN VK_DISPLAY_ATTRIBUTE IconType
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicBlt;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+ INTN StartX;
+ INTN StartY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempIconBackBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBackBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
+ UINTN Size;
+ BOOLEAN SaveCursor;
+
+ Status = EFI_SUCCESS;
+ StartX = 0;
+ StartY = 0;
+ TempIconBackBuffer = NULL;
+ IconBackBuffer = NULL;
+ Compound = NULL;
+
+ if ((IconType == VkDisplayAttributeFullTop) ||
+ (IconType == VkDisplayAttributeSimpleTop)) {
+ return EFI_SUCCESS;
+ }
+
+ SaveCursor = gST->ConOut->Mode->CursorVisible;
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ if (IconType == VkDisplayAttributeFullBottom) {
+ GraphicBlt = VkContext->FullIcon->Bitmap;
+ BltSize = VkContext->FullIcon->Height * VkContext->FullIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Height = VkContext->FullIcon->Height;
+ Width = VkContext->FullIcon->Width;
+ StartX = VkContext->FullIconBackStartX;
+ StartY = VkContext->FullIconBackStartY;
+ } else if (IconType == VkDisplayAttributeSimpleBottom) {
+ GraphicBlt = VkContext->SmallIcon->Bitmap;
+ BltSize = VkContext->SmallIcon->Height * VkContext->SmallIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Height = VkContext->SmallIcon->Height;
+ Width = VkContext->SmallIcon->Width;
+ StartX = VkContext->SimIconBackStartX;
+ StartY = VkContext->SimIconBackStartY;
+ } else {
+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
+ return EFI_UNSUPPORTED;
+ }
+
+ IconBackBuffer = AllocateZeroPool (BltSize);
+ if (IconBackBuffer == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TempIconBackBuffer = IconBackBuffer;
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ IconBackBuffer,
+ EfiBltVideoToBltBuffer,
+ StartX,
+ StartY,
+ 0,
+ 0,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ if (IconType == VkDisplayAttributeFullBottom) {
+ //
+ // Store full icon background framebuffer
+ //
+ VkContext->FullIconBackHeight = Height;
+ VkContext->FullIconBackWidth = Width;
+ if (VkContext->FullIconUpdatedFlag == FALSE) {
+ //
+ // No icon draw, save the buffer directly.
+ //
+ if (VkContext->FullIconBackBuffer == NULL) {
+ VkContext->FullIconBackBuffer = AllocateZeroPool (BltSize);
+ VkContext->FullIconBackSize = BltSize;
+ }
+ CopyMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize);
+ VkContext->FullIconUpdatedFlag = TRUE;
+ } else {
+ if (CompareMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize) != 0) {
+ Compound = VkContext->FullIconBackBuffer;
+ Size = Height * Width;
+ while (Size-- != 0) {
+ if ((GraphicBlt->Red != IconBackBuffer->Red) ||
+ (GraphicBlt->Green != IconBackBuffer->Green) ||
+ (GraphicBlt->Blue != IconBackBuffer->Blue)) {
+ *Compound = *IconBackBuffer;
+ }
+ Compound++;
+ GraphicBlt++;
+ IconBackBuffer++;
+ }
+ }
+ }
+ } else if (IconType == VkDisplayAttributeSimpleBottom) {
+ //
+ // Store simple icon background framebuffer
+ //
+ VkContext->SimIconBackHeight = Height;
+ VkContext->SimIconBackWidth = Width;
+ if (VkContext->SimIconUpdatedFlag == FALSE) {
+ //
+ // No icon draw, save the buffer directly.
+ //
+ if (VkContext->SimIconBackBuffer == NULL) {
+ VkContext->SimIconBackBuffer = AllocateZeroPool (BltSize);
+ VkContext->SimIconBackSize = BltSize;
+ }
+ CopyMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize);
+ VkContext->SimIconUpdatedFlag = TRUE;
+ } else {
+ if (CompareMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize) != 0) {
+ Compound = VkContext->SimIconBackBuffer;
+ Size = Height * Width;
+ while (Size-- != 0) {
+ if ((GraphicBlt->Red != IconBackBuffer->Red) ||
+ (GraphicBlt->Green != IconBackBuffer->Green) ||
+ (GraphicBlt->Blue != IconBackBuffer->Blue)) {
+ *Compound = *IconBackBuffer;
+ }
+ Compound++;
+ GraphicBlt++;
+ IconBackBuffer++;
+ }
+ }
+ }
+ }
+
+ if (TempIconBackBuffer != NULL) FreePool (TempIconBackBuffer);
+
+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
+ return Status;
+}
+
+/**
+ Use to draw the keyboard icon.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+ @param[in] VkImage Image of keyboard to display on the screen.
+ @param[in] Attribute Attribute of keyboard to display on the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed.
+ @retval EFI_UNSUPPORTED KeyboardFile not found
+ @retval EFI_INVALID_PARAMETER Attribute is unknown.
+
+**/
+EFI_STATUS
+EFIAPI
+DrawVkIcon (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_IMAGE_INPUT *VkImage,
+ IN VK_DISPLAY_ATTRIBUTE Attribute
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ INTN DestX;
+ INTN DestY;
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+
+ Status = EFI_SUCCESS;
+ GraphicsOutput = VkContext->GraphicsOutput;
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ CoordinateX = 0;
+ CoordinateY = 0;
+ Height = VkImage->Height;
+ Width = VkImage->Width;
+ Blt = VkImage->Bitmap;
+ BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);
+
+ //
+ // Calculate the display position according to Attribute.
+ //
+ switch (Attribute) {
+ case VkDisplayAttributeSimpleTop:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+
+ case VkDisplayAttributeFullTop:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = CoordinateY;;
+ break;
+
+ case VkDisplayAttributeFullBottom:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height - CoordinateY);
+ VkContext->FullIconBackStartX = DestX;
+ VkContext->FullIconBackStartY = DestY;
+ break;
+
+ case VkDisplayAttributeSimpleBottom:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height - CoordinateY);
+
+ //
+ // Save to check icon/screen cleared
+ //
+ if (VkContext->IconBltBuffer == NULL) {
+ VkContext->IconBltSize = BltSize;
+ VkContext->IconBltWidth = Width;
+ VkContext->IconBltHeight = Height;
+ VkContext->IconBltBuffer = AllocateZeroPool (BltSize);
+ }
+ CopyMem (VkContext->IconBltBuffer, Blt, VkContext->IconBltSize);
+
+ VkContext->SimIconBackStartX = DestX;
+ VkContext->SimIconBackStartY = DestY;
+ break;
+
+ case VkDisplayAttributeNone:
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DestX >= 0) && (DestY >= 0)) {
+ //
+ // Store icon background framebuffer
+ //
+ SaveVkIconBackgroundBltBuffer (VkContext, Attribute);
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Use to draw the keyboard.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+ @param[in] VkImage Image of keyboard to display on the screen.
+ @param[in] Attribute Attribute of keyboard to display on the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed.
+ @retval EFI_UNSUPPORTED KeyboardFile not found
+ @retval EFI_INVALID_PARAMETER Attribute is unknown.
+
+**/
+EFI_STATUS
+EFIAPI
+DrawVkBody (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_IMAGE_INPUT *VkImage,
+ IN VK_DISPLAY_ATTRIBUTE Attribute
+ )
+{
+ EFI_STATUS Status;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ INTN DestX;
+ INTN DestY;
+ UINTN BltSize;
+ UINTN Height;
+ UINTN Width;
+ UINTN CoordinateY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ Status = EFI_SUCCESS;
+ GraphicsOutput = VkContext->GraphicsOutput;
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ CoordinateY = 0;
+ Height = VkImage->Height;
+ Width = VkImage->Width;
+ BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);
+ BltIn = AllocateCopyPool (BltSize, VkImage->Bitmap);
+
+ if (BltIn == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Calculate the display position according to Attribute.
+ //
+ switch (Attribute) {
+ case VkDisplayAttributeSimpleTop:
+ DestX = ((SizeOfX / 2) - Width) / 4;
+ DestY = CoordinateY;
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleTop;
+ break;
+
+ case VkDisplayAttributeSimpleBottom:
+ DestX = ((SizeOfX / 2) - Width) / 4;
+ DestY = (SizeOfY - Height - CoordinateY);
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleBottom;
+ break;
+
+ case VkDisplayAttributeFullTop:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = CoordinateY;
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullTop;
+ break;
+
+ case VkDisplayAttributeFullBottom:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height - CoordinateY);
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullBottom;
+ break;
+
+ case VkDisplayAttributeNone:
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+ goto DVKBODY_Exit;
+
+ default:
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+ Status = EFI_INVALID_PARAMETER;
+ goto DVKBODY_Exit;
+ }
+ if ((DestX >= 0) && (DestY >= 0)) {
+ SetCharacterPosition (VkContext, (UINT32)DestX, (UINT32)DestY);
+
+ //
+ // Store current framebuffer
+ //
+ VkContext->VkBodyBltStartX = DestX;
+ VkContext->VkBodyBltStartY = DestY;
+ VkContext->VkBodyBltHeight = Height;
+ VkContext->VkBodyBltWidth = Width;
+ SaveVkBodyBackgroundBltBuffer (VkContext, BltSize);
+
+ //
+ // Free compound buffer first.
+ //
+ if (VkContext->VkBodyCompoundBltBuffer != NULL) {
+ FreePool (VkContext->VkBodyCompoundBltBuffer);
+ }
+ VkContext->VkBodyCompoundBltBuffer = NULL;
+ ModifyShiftKeyColor (VkContext, &BltIn);
+ MakeKeyboardTransparent (VkContext, TRUE, BltIn, &(VkContext->VkBodyCompoundBltBuffer));
+
+ //
+ // Draw keyboard body
+ //
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ VkContext->VkBodyCompoundBltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ }
+
+
+DVKBODY_Exit:
+ if (BltIn != NULL) {
+ FreePool (BltIn);
+ }
+
+ return Status;
+}
+
+/**
+ Clear the keyboard body
+
+ @param VkContext Code context.
+
+ @retval EFI_SUCCESS Clear rectangle is done.
+
+**/
+EFI_STATUS
+HideVkBody (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ RestoreVkBodyBackgroundBltBuffer (VkContext);
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Clear the keyboard icon
+
+ @param VkContext Code context.
+
+ @retval EFI_SUCCESS Clear rectangle is done.
+
+**/
+EFI_STATUS
+HideVkIcon (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+
+ if ((VkContext->FullIconBackBuffer == NULL) || (VkContext->SimIconBackBuffer == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((VkContext->FullIconUpdatedFlag == FALSE) || (VkContext->SimIconUpdatedFlag == FALSE)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ VkContext->FullIconBackBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ VkContext->FullIconBackStartX,
+ VkContext->FullIconBackStartY,
+ VkContext->FullIconBackWidth,
+ VkContext->FullIconBackHeight,
+ VkContext->FullIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+
+ ZeroMem (VkContext->FullIconBackBuffer, VkContext->FullIconBackSize);
+ VkContext->FullIconUpdatedFlag = FALSE;
+
+
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ VkContext->SimIconBackBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ VkContext->SimIconBackStartX,
+ VkContext->SimIconBackStartY,
+ VkContext->SimIconBackWidth,
+ VkContext->SimIconBackHeight,
+ VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ if (!EFI_ERROR (Status)) {
+ if (VkContext->ScreenCheckBuffer == NULL) {
+ VkContext->ScreenCheckBufferSize = VkContext->SimIconBackHeight *
+ VkContext->SimIconBackWidth *
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ VkContext->ScreenCheckBuffer = AllocateZeroPool (VkContext->ScreenCheckBufferSize);
+ }
+
+ CopyMem (
+ VkContext->ScreenCheckBuffer,
+ VkContext->SimIconBackBuffer,
+ (VkContext->SimIconBackHeight * VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
+ );
+ }
+ ZeroMem (VkContext->SimIconBackBuffer, VkContext->SimIconBackSize);
+ VkContext->SimIconUpdatedFlag = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Draw key board on the display
+
+ @param[in] VkContext Graphic Protocol for draw the alphabet.
+
+ @retval EFI_SUCCESS Draw keyboard was done.
+ @retval EFI_UNSUPPORTED Did not get key mapping table.
+
+**/
+EFI_STATUS
+DrawKeyboardLayout (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+ if (!VkContext->IsIconShowed) {
+ Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleTop);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleBottom);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullTop);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullBottom);
+ ASSERT_EFI_ERROR (Status);
+ VkContext->IsIconShowed = TRUE;
+ }
+
+ if (VkContext->TargetKeyboardDisplay != VkContext->CurrentKeyboardDisplay) {
+ switch (VkContext->TargetKeyboardDisplay) {
+ case VkDisplayAttributeSimpleTop:
+ case VkDisplayAttributeSimpleBottom:
+ DrawVkBody (VkContext, VkContext->SimKeyBody, VkContext->TargetKeyboardDisplay);
+ break;
+
+ case VkDisplayAttributeFullTop:
+ case VkDisplayAttributeFullBottom:
+ if (VkContext->PageNumber <= VkPage1) {
+ DrawVkBody (VkContext, VkContext->CapLeKeyBody, VkContext->TargetKeyboardDisplay);
+ } else {
+ DrawVkBody (VkContext, VkContext->DigKeyBody, VkContext->TargetKeyboardDisplay);
+ }
+
+ case VkDisplayAttributeNone:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the keyboard layout.
+
+ @param[in] VkContext Graphic Protocol for draw the alphabet.
+ @param[in] Index The layout selected.
+
+ @retval EFI_SUCCESS Draw keyboard was done.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+KeyboardLayoutHandler (
+ IN VK_CONTEXT *VkContext,
+ IN UINT32 Index
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (Index == (VkContext->NumOfKeysInfo - 4)) {
+ //
+ // Touch the LeftTop icon
+ //
+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleTop) {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+ } else {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleTop;
+ }
+ } else if (Index == (VkContext->NumOfKeysInfo - 3)) {
+ //
+ // Touch the LeftBottom icon
+ //
+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleBottom) {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+ } else {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleBottom;
+ }
+ } else if (Index == (VkContext->NumOfKeysInfo - 2)) {
+ //
+ // Touch the RightTop icon
+ //
+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullTop) {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+ } else {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullTop;
+ }
+ } else {
+ //
+ // Touch the RightBottom icon
+ //
+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullBottom) {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
+ } else {
+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullBottom;
+ }
+ }
+
+ if (VkContext->TargetKeyboardDisplay == VkDisplayAttributeNone) {
+ //
+ // Just hide the current keyboard
+ //
+ HideVkBody (VkContext);
+ VkContext->KeyTouchedTimeOut = VK_REPEAT_TIMEOUT;
+
+ } else {
+ //
+ // If current keyboard status is NOT none,
+ // hide current keyboard first and then draw the target keyboard
+ //
+ if (VkContext->CurrentKeyboardDisplay != VkDisplayAttributeNone) {
+ HideVkBody (VkContext);
+ }
+ Status = DrawKeyboardLayout (VkContext);
+ }
+
+ return Status;
+}
+
+/**
+ This routine is used to check if icon has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckIconCleared (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+ UINT32 VerticalResolution;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ Status = EFI_SUCCESS;
+ BltBuffer = NULL;
+ VkContext->IconReDrawCheck++;
+ if (VkContext->IconReDrawCheck <= 10) {
+ //
+ // Check it every 10 * 100ms.
+ //
+ return Status;
+ }
+
+ //
+ // Check if right-bottomed region is black, if yes, clean screen happened, need to re-draw keyboard.
+ //
+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
+ BltBuffer = AllocateZeroPool (VkContext->IconBltSize);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ BltBuffer,
+ EfiBltVideoToBltBuffer,
+ 0,
+ (VerticalResolution - VkContext->IconBltHeight),
+ 0,
+ 0,
+ VkContext->IconBltWidth,
+ VkContext->IconBltHeight,
+ VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ return Status;
+ }
+ VkContext->IsIconShowed = TRUE;
+ if (VkContext->IconBltBuffer == NULL) {
+ //
+ // No icon has been drawn.
+ //
+ VkContext->IsIconShowed = FALSE;
+ } else {
+ if (CompareMem (BltBuffer, VkContext->IconBltBuffer, VkContext->IconBltSize) != 0) {
+ //
+ // Icon has been overridden, need to re-draw.
+ //
+ VkContext->IsIconShowed = FALSE;
+ }
+ }
+
+ if (VkContext->IsIconShowed == FALSE) {
+ if (VkContext->ScreenCheckBuffer != NULL) {
+ if (CompareMem (BltBuffer, VkContext->ScreenCheckBuffer, VkContext->IconBltSize) == 0) {
+ //
+ // Icon has been overridden, force to re-draw the keyboard.
+ //
+ Status = DrawKeyboardLayout (VkContext);
+ } else {
+ //
+ // Save blt buffer of icon position and use it to check if icon is overridden.
+ //
+ CopyMem (VkContext->ScreenCheckBuffer, BltBuffer, VkContext->IconBltSize);
+ }
+ } else {
+ //
+ // Draw the keyboard.
+ //
+ Status = DrawKeyboardLayout (VkContext);
+ }
+ }
+
+ if (BltBuffer != NULL) {
+ FreePool (BltBuffer);
+ }
+
+ VkContext->IconReDrawCheck = 0;
+
+ return Status;
+}
+
+/**
+ ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate.
+
+ @param[in] VkContext Virtual Keyboard context.
+ @param[in] Point The coordinate reported from touch panel.
+ @param[out] TouchX The coordinate X converted to display panel.
+ @param[out] TouchY The coordinate Y converted to display panel..
+
+ @retval EFI_SUCCESS Convert success.
+
+**/
+EFI_STATUS
+ConvertCoordinate (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_ABSOLUTE_POINTER_STATE Point,
+ OUT UINT32 *TouchX,
+ OUT UINT32 *TouchY
+ )
+{
+ UINT64 AbsoluteMaxX;
+ UINT64 AbsoluteMaxY;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+
+ AbsoluteMaxX = VkContext->AbsolutePointer->Mode->AbsoluteMaxX;
+ AbsoluteMaxY = VkContext->AbsolutePointer->Mode->AbsoluteMaxY;
+ HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;
+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
+ *TouchX = (UINT32) MultU64x32 (Point.CurrentX, HorizontalResolution) / (UINT32) AbsoluteMaxX;
+ *TouchY = (UINT32) MultU64x32 (Point.CurrentY, VerticalResolution) / (UINT32) AbsoluteMaxY;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine is used to check if screen has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckScreenCleared (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBufferIndex;
+ UINTN BltSize;
+ BOOLEAN IsScreenCleared;
+
+ //
+ // Check left-bottom side.
+ // If IconBltBuffer is null, checking is meaningless.
+ //
+ if (VkContext->IconBltBuffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ IsScreenCleared = FALSE;
+ Status = EFI_SUCCESS;
+ if ((gST->ConOut->Mode->CursorColumn == 0) && (gST->ConOut->Mode->CursorRow == 0)) {
+ //
+ // System may call gST->ConOut->ClearScreen
+ //
+ HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;
+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
+ BltBuffer = AllocateZeroPool (VkContext->IconBltSize);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BltBufferIndex = BltBuffer;
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ BltBuffer,
+ EfiBltVideoToBltBuffer,
+ (HorizontalResolution - VkContext->IconBltWidth),
+ (VerticalResolution - VkContext->IconBltHeight),
+ 0,
+ 0,
+ VkContext->IconBltWidth,
+ VkContext->IconBltHeight,
+ VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ return Status;
+ }
+ BltSize = VkContext->IconBltHeight * VkContext->IconBltWidth;
+ IsScreenCleared = TRUE;
+ while (BltSize-- != 0) {
+ if ((BltBufferIndex->Red != 0) || (BltBufferIndex->Green != 0) || (BltBufferIndex->Blue != 0)) {
+ IsScreenCleared = FALSE;
+ break;
+ }
+ BltBufferIndex++;
+ }
+ FreePool (BltBuffer);
+ }
+
+ if (IsScreenCleared) {
+ VkContext->IsIconShowed = FALSE;
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+
+ if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
+ FreePool (VkContext->VkBodyBackgroundBltBuffer);
+ VkContext->VkBodyBackgroundBltBuffer = NULL;
+ }
+
+ if (VkContext->VkBodyCompoundBltBuffer != NULL) {
+ FreePool (VkContext->VkBodyCompoundBltBuffer);
+ VkContext->VkBodyCompoundBltBuffer = NULL;
+ }
+
+ if (VkContext->IconBltBuffer != NULL) {
+ FreePool (VkContext->IconBltBuffer);
+ VkContext->IconBltBuffer = NULL;
+ }
+
+ }
+
+ return Status;
+}
+
+/**
+ This routine is used to check if background beneath virtual keyboard has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckBackgroundChanged (
+ IN VK_CONTEXT *VkContext
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ Status = EFI_SUCCESS;
+ VkContext->IsBackgroundChanged = FALSE;
+
+ if ((VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) || (VkContext->VkBodyCompoundBltBuffer == NULL)) {
+ return EFI_SUCCESS;
+ }
+
+ BltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = VkContext->GraphicsOutput->Blt (
+ VkContext->GraphicsOutput,
+ BltBuffer,
+ EfiBltVideoToBltBuffer,
+ VkContext->VkBodyBltStartX,
+ VkContext->VkBodyBltStartY,
+ 0,
+ 0,
+ VkContext->VkBodyBltWidth,
+ VkContext->VkBodyBltHeight,
+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ return Status;
+ }
+ if (CompareMem (BltBuffer, VkContext->VkBodyCompoundBltBuffer, VkContext->VkBodyBltSize) != 0) {
+ VkContext->IsBackgroundChanged = TRUE;
+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
+ DrawKeyboardLayout (VkContext);
+ }
+
+ if (BltBuffer != NULL) {
+ FreePool (BltBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] KeyItem Key Item.
+ @param[out] FontPtr Follow VkContext->PageNumber to translate
+ font unicode.
+
+ @retval EFI_SUCCESS Finish translating FontPtr.
+ @retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL.
+
+**/
+EFI_STATUS
+VkGetMappingFont (
+ IN VK_CONTEXT *VkContext,
+ IN VK_STRUCT KeyItem,
+ OUT UINT32 *FontPtr
+ )
+{
+ if ((VkContext == NULL) || (FontPtr == NULL) || (VkContext->PageNumber>=VkPageMaximum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *FontPtr = (UINT32) KeyItem.PageFont[VkContext->PageNumber];
+
+ return EFI_SUCCESS;
+}
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
new file mode 100644
index 0000000000..995bd0d859
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
@@ -0,0 +1,12 @@
+// /** @file
+// Virtual Keyboard Layout
+//
+// Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+#image IMG_VK_CAPITALLETTERKEYBOARD TRANSPARENT CapitalLetterKeyboard.bmp
+#image IMG_VK_DIGITKEYBOARD TRANSPARENT DigitKeyboard.bmp
+#image IMG_VK_FULLICON TRANSPARENT FullIcon.bmp
+#image IMG_VK_SIMPLEICON TRANSPARENT SimpleIcon.bmp
+#image IMG_VK_SIMPLEKEYBOARD TRANSPARENT SimpleKeyboard.bmp
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..16816f031eb98bf8169c7119b95ea3ed1371f41d
GIT binary patch
literal 2814
zcmeHDu?>JQ41<*mn3%bM1K9bStAMDgEvtknP%#v#jj<EA^|~EHm%hdJ+18X--;Igi
zvz~tHZ083bZvKJwS=AedIaS~0$e`HvNI;OvAp=5}kZlld1O%z<Y2HkwWx^;3ew~S4
zE{O5qpp83T)f<O7RWIkrpxE|EK#<BI145UOZ4hn*1gY$4-b|%s!YByBnW#Y!<5EEz
Lcf5u-&Un3EdmJn}
literal 0
HcmV?d00001
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..3004a534f026fe4906e64480f2239b7b7923640b
GIT binary patch
literal 30054
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
D{aYn_
literal 0
HcmV?d00001
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
new file mode 100644
index 0000000000..a7e7a26841
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
@@ -0,0 +1,829 @@
+/** @file
+ Header file for Virtual Keyboard driver.
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VIRTUAL_KEYBOARD_H_
+#define _VIRTUAL_KEYBOARD_H_
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HiiLib.h>
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiImageEx.h>
+#include <Protocol/HiiPackageList.h>
+#include <Guid/ConsoleInDevice.h>
+#include "ComponentName.h"
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;
+
+///
+/// Debug raw data points
+///
+#define DEBUG_VK_POINTS 0x40000000
+
+///
+/// Debug data point scaling
+///
+#define DEBUG_VK_POINT_SCALING 0x20000000
+
+///
+/// Debug key press
+///
+#define DEBUG_VK_KEYS 0x10000000
+
+///
+/// Debug routine entry and exit
+///
+#define DEBUG_VK_ROUTINE_ENTRY_EXIT 0x08000000
+
+///
+/// Display the graphics info
+///
+#define DEBUG_VK_GRAPHICS_INFO 0x04000000
+
+///
+/// Display the timer entry and exit
+///
+#define DEBUG_VK_TIMER_ENTRY_EXIT 0x00100000
+
+///
+/// Signature
+///
+#define VK_SIGNATURE SIGNATURE_32 ('V', 'K', 'e', 'y')
+#define VK_NOTIFY_SIGNATURE SIGNATURE_32 ('V', 'K', 'n', 's')
+
+///
+/// Poll interval
+///
+#define VK_POLL_INTERVAL (1000 * 1000)
+
+///
+/// Define the touch timeout in poll intervals
+///
+#define VK_REPEAT_TIMEOUT 5
+
+///
+/// TPL used to synchronize add/remove from list
+///
+#define TPL_VK_SYNC TPL_NOTIFY
+
+///
+/// Dimension of an array ( number of elements )
+///
+#define DIM(x) ( sizeof ( x ) / sizeof ( x [ 0 ]))
+
+///
+/// Define Key buffer
+///
+#define MAX_KEY_BUF_SIZE 64
+
+///
+/// Define Transparent Weight
+///
+#define TRANSPARENCY_WEIGHT 50
+
+typedef struct _VK_CONTEXT VK_CONTEXT;
+
+typedef enum _VK_KEY_TYPE {
+ VkKeyNull = 0x0000 | CHAR_NULL,
+ VkKeyBackspace = 0x0000 | CHAR_BACKSPACE,
+ VkKeyTab = 0x0000 | CHAR_TAB,
+ VkKeyEnter = 0x0000 | CHAR_CARRIAGE_RETURN,
+ VkKeyScanMask = 0x1000,
+ VkKeyEsc = 0x1000 | SCAN_ESC,
+ VkKeyLeft = 0x1000 | SCAN_LEFT,
+ VkKeyRight = 0x1000 | SCAN_RIGHT,
+ VkKeyUp = 0x1000 | SCAN_UP,
+ VkKeyDown = 0x1000 | SCAN_DOWN,
+ VkKeyF1 = 0x1000 | SCAN_F1,
+ VkKeyF2 = 0x1000 | SCAN_F2,
+ VkKeyF3 = 0x1000 | SCAN_F3,
+ VkKeyF4 = 0x1000 | SCAN_F4,
+ VkKeyF5 = 0x1000 | SCAN_F5,
+ VkKeyF6 = 0x1000 | SCAN_F6,
+ VkKeyF7 = 0x1000 | SCAN_F7,
+ VkKeyF8 = 0x1000 | SCAN_F8,
+ VkKeyF9 = 0x1000 | SCAN_F9,
+ VkKeyF10 = 0x1000 | SCAN_F10,
+ VkKeyF11 = 0x1000 | SCAN_F11,
+ VkKeyF12 = 0x1000 | SCAN_F12,
+ VkKeySpecificMask = 0x2000,
+ VkKeyShift = 0x2000 | 0x0000,
+ VkKeyCapslock = 0x2000 | 0x0001,
+ VkKeyTwoPage = 0x2000 | 0x0002,
+ VkKeyTypeMaximum = 0xFFFF
+} VK_KEY_TYPE;
+
+typedef enum _VK_PAGE_TYPE {
+ //
+ // +---+---+---+---+---+---+---+---+---+---+---+
+ // | q | w | e | r | t | y | u | i | o | p |<X|| Line 0
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | | a | s | d | f | g | h | j | k | l | F2| | Line 1
+ // +-+---+---+---+---+---+---+---+---+---+---+-+
+ // |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2
+ // +-----+---+---+---+---+---+---+---+---+---+-+
+ // | Esc |12#| Space |aL |aD |aR | | Line 3
+ // +-----+---+-------------------+---+---+---+-+
+ //
+ VkPage0,
+
+ //
+ // +---+---+---+---+---+---+---+---+---+---+---+
+ // | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | | A | S | D | F | G | H | J | K | L | F2| | Line 1
+ // +-+---+---+---+---+---+---+---+---+---+---+-+
+ // |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2
+ // +-----+---+---+---+---+---+---+---+---+---+-+
+ // | Esc |12#| Space |aL |aD |aR | | Line 3
+ // +-----+---+-------------------+---+---+---+-+
+ //
+ VkPage1,
+
+ //
+ // +---+---+---+---+---+---+---+---+---+---+---+
+ // | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
+ // +-+---+---+---+---+---+---+---+---+---+---+-+
+ // |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2
+ // +-----+---+---+---+---+---+---+---+---+---+-+
+ // | Esc |12#| Space | \ | - | = | | Line 3
+ // +-----+---+-------------------+---+---+---+-+
+ //
+ VkPage2,
+
+ //
+ // +---+---+---+---+---+---+---+---+---+---+---+
+ // | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
+ // +-+---+---+---+---+---+---+---+---+---+---+-+
+ // |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2
+ // +-----+---+---+---+---+---+---+---+---+---+-+
+ // | Esc |12#| Space | | | _ | + | | Line 3
+ // +-----+---+-------------------+---+---+---+-+
+ //
+ VkPage3,
+ VkPageMaximum
+} VK_PAGE_TYPE;
+
+typedef enum VK_DISPLAY_ATTRIBUTE {
+ VkDisplayAttributeNone, /// No keyboard displayed
+ VkDisplayAttributeFullTop, /// Full keyboard display at top
+ VkDisplayAttributeFullBottom, /// Full keyboard display at bottom
+ VkDisplayAttributeSimpleTop, /// Simple keyboard display at top
+ VkDisplayAttributeSimpleBottom, /// Simple keyboard display at bottom
+ VkDisplayAttributeMaximum
+} VK_DISPLAY_ATTRIBUTE;
+
+typedef struct _VK_STRUCT {
+ UINT16 DisStartX;
+ UINT16 DisStartY;
+ UINT16 DisEndX;
+ UINT16 DisEndY;
+ VK_KEY_TYPE PageFont[VkPageMaximum];
+} VK_STRUCT;
+
+typedef struct _VK_NOTIFY {
+ UINTN Signature;
+ EFI_KEY_DATA KeyData;
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;
+ LIST_ENTRY NotifyEntry;
+} VK_NOTIFY;
+
+///
+/// Virtual Keyboard context
+///
+struct _VK_CONTEXT {
+ ///
+ /// Structure identification
+ ///
+ UINTN Signature;
+
+ ///
+ /// Controller Handle
+ ///
+ EFI_HANDLE Controller;
+
+ ///
+ /// Upper level API
+ ///
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
+
+ ///
+ /// Simple Text In EX
+ ///
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInEx;
+
+ ///
+ /// Lower level APIs
+ ///
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ ///
+ /// Flag when the last poll indicated a touch event
+ ///
+ BOOLEAN TouchActive;
+
+ ///
+ /// Time to poll for touch input
+ ///
+ EFI_EVENT TimerEvent;
+
+ ///
+ /// HII handle to get image data used
+ ///
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_IMAGE_EX_PROTOCOL *HiiImageEx;
+
+ ///
+ /// Keyboard body background buffer information
+ ///
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VkBodyBackgroundBltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VkBodyCompoundBltBuffer;
+ UINTN VkBodyBltSize;
+ UINTN VkBodyBltStartX;
+ UINTN VkBodyBltStartY;
+ UINTN VkBodyBltHeight;
+ UINTN VkBodyBltWidth;
+ BOOLEAN IsBackgroundChanged;
+
+ ///
+ /// Icon buffer information
+ ///
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBltBuffer;
+ UINTN IconBltSize;
+ UINTN IconBltHeight;
+ UINTN IconBltWidth;
+
+ ///
+ /// Full icon background buffer information
+ ///
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FullIconBackBuffer;
+ UINTN FullIconBackStartX;
+ UINTN FullIconBackStartY;
+ UINTN FullIconBackHeight;
+ UINTN FullIconBackWidth;
+ UINTN FullIconBackSize;
+ BOOLEAN FullIconUpdatedFlag;
+
+ ///
+ /// Simple icon background buffer information
+ ///
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SimIconBackBuffer;
+ UINTN SimIconBackStartX;
+ UINTN SimIconBackStartY;
+ UINTN SimIconBackHeight;
+ UINTN SimIconBackWidth;
+ UINTN SimIconBackSize;
+ BOOLEAN SimIconUpdatedFlag;
+
+ ///
+ /// Small Icon
+ ///
+ EFI_IMAGE_INPUT *SmallIcon;
+
+ ///
+ /// Full Icon
+ ///
+ EFI_IMAGE_INPUT *FullIcon;
+
+ ///
+ /// Simple Key body
+ ///
+ EFI_IMAGE_INPUT *SimKeyBody;
+
+ ///
+ /// Digital key body
+ ///
+ EFI_IMAGE_INPUT *DigKeyBody;
+
+ ///
+ /// Capital Letter Key board
+ ///
+ EFI_IMAGE_INPUT *CapLeKeyBody;
+
+ ///
+ /// Screen check buffer.
+ /// This is used to check if screen is kept scrolling up.
+ ///
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenCheckBuffer;
+ UINTN ScreenCheckBufferSize;
+
+ ///
+ /// Key state
+ ///
+ BOOLEAN KeyPressed;
+
+ ///
+ /// Keyboard display status
+ ///
+ VK_DISPLAY_ATTRIBUTE CurrentKeyboardDisplay;
+ VK_DISPLAY_ATTRIBUTE TargetKeyboardDisplay;
+
+ ///
+ /// Keyboard icon display status
+ ///
+ BOOLEAN IsIconShowed;
+ UINT8 IconReDrawCheck;
+
+ ///
+ /// Keyboard body Image address
+ /// Size of KeyboardBodyPtr must larger than mFullKeyboardBody
+ ///
+ UINT32 NumOfKeysInfo;
+ VK_STRUCT KeyboardBodyPtr[50];
+
+ ///
+ /// KeyBuffer
+ ///
+ EFI_EVENT KeyNotifyProcessEvent;
+ EFI_KEY_TOGGLE_STATE KeyToggleState;
+ EFI_KEY_DATA Keybuffer[MAX_KEY_BUF_SIZE];
+ UINT8 KeyStartIndex;
+ UINT8 KeyEndIndex;
+ UINT16 KeyTouchedTimeOut;
+ BOOLEAN IsShiftKeyFlag;
+ BOOLEAN IsCapsLockFlag;
+ BOOLEAN IsSupportPartialKey;
+ BOOLEAN IsRedrawUpdateUI;
+ VK_PAGE_TYPE PageNumber;
+ LIST_ENTRY NotifyList;
+};
+
+///
+/// Locate VK_CONTEXT from protocol
+///
+#define VK_CONTEXT_FROM_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleTextIn, VK_SIGNATURE)
+#define VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleTextInEx, VK_SIGNATURE)
+#define VK_CONTEXT_FROM_VKBD_PROTOCOL(a) CR (a, VK_CONTEXT, VkbdProtocol, VK_SIGNATURE)
+
+/**
+ Start the virtual keyboard driver
+
+ This routine allocates the necessary resources for the driver.
+
+ This routine is called by VirtualKeyboardDriverStart to complete the driver
+ initialization.
+
+ @param[in, out] VkContext Address of an VK_CONTEXT structure
+ @param[in] Controller Handle of device to work with.
+
+ @retval EFI_SUCCESS Driver API properly initialized
+
+**/
+EFI_STATUS
+VkApiStart (
+ IN OUT VK_CONTEXT *VkContext,
+ IN EFI_HANDLE Controller
+ );
+
+/**
+ Stop the virtual keyboard driver
+
+ This routine releases the resources allocated by VKApiStart.
+
+ This routine is called by VirtualKeyboardDriverStop to initiate the driver
+ shutdown.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure
+
+**/
+VOID
+VkApiStop (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ Resets the input device hardware.
+
+ The Reset() function resets the input device hardware. As part
+ of initialization process, the firmware/device will make a quick
+ but reasonable attempt to verify that the device is functioning.
+ If the ExtendedVerification flag is TRUE the firmware may take
+ an extended amount of time to verify the device is operating on
+ reset. Otherwise the reset operation is to occur as quickly as
+ possible. The hardware verification process is not defined by
+ this specification and is left up to the platform firmware or
+ driver to implement.
+
+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the next keystroke from the input device. The WaitForKey Event can
+ be used to test for existence of a keystroke via WaitForEvent () call.
+
+ @param[in] This Protocol instance pointer.
+ @param[out] Key Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The keystroke information was returned.
+ @retval EFI_NOT_READY There was no keystroke data available.
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
+ hardware errors.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+/**
+ Resets the input device hardware.
+
+ The Reset() function resets the input device hardware. As part
+ of initialization process, the firmware/device will make a quick
+ but reasonable attempt to verify that the device is functioning.
+ If the ExtendedVerification flag is TRUE the firmware may take
+ an extended amount of time to verify the device is operating on
+ reset. Otherwise the reset operation is to occur as quickly as
+ possible. The hardware verification process is not defined by
+ this specification and is left up to the platform firmware or
+ driver to implement.
+
+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
+
+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardResetEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the next keystroke from the input device.
+
+ @param[in] This Protocol instance pointer.
+ @param[out] 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 available.
+ @retval EFI_INVALID_PARAMETER This or KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ );
+
+/**
+ Set certain state for the input device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] 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 appropriately.
+ @retval EFI_INVALID_PARAMETER This or KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardSetState (
+ 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[in] This Protocol instance pointer.
+ @param[in] KeyData A pointer to a buffer that is filled in with the keystroke
+ information data for the key that was pressed.
+ @param[in] KeyNotificationFunction Points to the function to be called when the key
+ sequence is typed specified by KeyData.
+ @param[out] 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 necessary data structures.
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+VkKeyboardRegisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+ );
+
+/**
+ Remove a registered notification function from a particular keystroke.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] 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
+VkKeyboardUnregisterKeyNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ );
+
+/**
+ Draw key board on the display
+
+ @param[in] VkContext Graphic Protocol for draw the alphabet.
+
+ @retval EFI_SUCCESS Draw keyboard was done.
+ @retval EFI_UNSUPPORTED Did not get key mapping table.
+
+**/
+EFI_STATUS
+DrawKeyboardLayout (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ Clear the keyboard body
+
+ @param[in] VkContext Code context.
+
+ @retval EFI_SUCCESS Clear rectangle is done.
+
+**/
+EFI_STATUS
+HideVkBody (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ Clear the keyboard icon
+
+ @param[in] VkContext Code context.
+
+ @retval EFI_SUCCESS Clear rectangle is done.
+
+**/
+EFI_STATUS
+HideVkIcon (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ Use to draw the keyboard icon.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+ @param[in] VkImage Image of keyboard to display on the screen.
+ @param[in] Attribute Attribute of keyboard to display on the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed.
+ @retval EFI_UNSUPPORTED KeyboardFile not found
+ @retval EFI_INVALID_PARAMETER Attribute is unknown.
+
+**/
+EFI_STATUS
+EFIAPI
+DrawVkIcon (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_IMAGE_INPUT *VkImage,
+ IN VK_DISPLAY_ATTRIBUTE Attribute
+ );
+
+/**
+ Use to draw the keyboard.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+ @param[in] VkImage Image of keyboard to display on the screen.
+ @param[in] Attribute Attribute of keyboard to display on the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed.
+ @retval EFI_UNSUPPORTED KeyboardFile not found
+ @retval EFI_INVALID_PARAMETER Attribute is unknown.
+
+**/
+EFI_STATUS
+EFIAPI
+DrawVkBody (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_IMAGE_INPUT *VkImage,
+ IN VK_DISPLAY_ATTRIBUTE Attribute
+ );
+
+/**
+ Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] KeyItem Key Item.
+ @param[out] FontPtr Follow VkContext->PageNumber to translate
+ font unicode.
+
+ @retval EFI_SUCCESS Finish translating FontPtr.
+ @retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL.
+
+**/
+EFI_STATUS
+VkGetMappingFont (
+ IN VK_CONTEXT *VkContext,
+ IN VK_STRUCT KeyItem,
+ OUT UINT32 *FontPtr
+ );
+
+/**
+ This routine is used to check if icon has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckIconCleared (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate.
+
+ @param[in] VkContext Virtual Keyboard context.
+ @param[in] Point The coordinate reported from touch panel.
+ @param[out] TouchX The coordinate X converted to display panel.
+ @param[out] TouchY The coordinate Y converted to display panel..
+
+ @retval EFI_SUCCESS Convert success.
+
+**/
+EFI_STATUS
+ConvertCoordinate (
+ IN VK_CONTEXT *VkContext,
+ IN EFI_ABSOLUTE_POINTER_STATE Point,
+ OUT UINT32 *TouchX,
+ OUT UINT32 *TouchY
+ );
+
+/**
+ This routine is used to check if screen has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckScreenCleared (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ This routine is used to check if background beneath virtual keyboard has been cleared.
+
+ @param[in] VkContext Pointer to virtual keyboard's context
+
+ @retval EFI_SUCCESS Function completed.
+
+**/
+EFI_STATUS
+CheckBackgroundChanged (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ To prevent screen keyboard layout occur scroll up
+
+ @param[in, out] VkContext Address of an VK_CONTEXT structure.
+
+**/
+VOID
+PreventScreenScrollUp (
+ IN OUT VK_CONTEXT *VkContext
+ );
+
+/**
+ Set the position of character.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] DestX X position.
+ @param[in] DestY Y position.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+SetCharacterPosition (
+ IN VK_CONTEXT *VkContext,
+ IN UINT32 DestX,
+ IN UINT32 DestY
+ );
+
+/**
+ Set the keyboard layout.
+
+ @param[in] VkContext Graphic Protocol for draw the alphabet.
+ @param[in] Index The layout selected.
+
+ @retval EFI_SUCCESS Draw keyboard was done.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+KeyboardLayoutHandler (
+ IN VK_CONTEXT *VkContext,
+ IN UINT32 Index
+ );
+
+/**
+ Save the background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] BltSize Size of blt.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveVkBodyBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext,
+ IN UINTN BltSize
+ );
+
+/**
+ Restore the background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_UNSUPPORTED Input blt buffer is NULL.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RestoreVkBodyBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext
+ );
+
+/**
+ Save the icon background blt buffer.
+
+ @param[in] VkContext Address of an VK_CONTEXT structure.
+ @param[in] IconType The icon type.
+
+ @retval EFI_SUCCESS Success for the function.
+ @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveVkIconBackgroundBltBuffer (
+ IN VK_CONTEXT *VkContext,
+ IN VK_DISPLAY_ATTRIBUTE IconType
+ );
+#endif
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
new file mode 100644
index 0000000000..523c662b29
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
@@ -0,0 +1,515 @@
+/** @file
+ Virtual Keyboard driver.
+
+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VirtualKeyboard.h"
+
+UINT32 mOrigConOutRow = 0;
+UINT32 mOrigSetupConOutRow = 0;
+EFI_HII_HANDLE mHiiHandle = NULL;
+/**
+ Verify the controller type
+
+ This routine determines if the pointer and GOP are available.
+
+ This routine is called by the UEFI driver framework during connect
+ processing.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to test.
+ @param[in] RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtualKeyboardDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported Start\n"));
+
+ //
+ // Verify that the driver is not already started
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_ALREADY_STARTED;
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK has already initialized\n"));
+ goto Error;
+ }
+
+ //
+ // Determine if the pointer protocol is available.
+ // This should be installed in touch driver.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Absolute pointer protocol not found\n"));
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEdkiiTouchPanelGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Touch Panel Guid not found\n"));
+ goto Error;
+ }
+
+ //
+ // Determine if the graphics output protocol is available
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **)&GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Graphics output protocol not found\n"));
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverSupported Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported End\n"));
+ return Status;
+}
+
+/**
+ Connect to the controller
+
+ This routine initializes an instance of the virutal keyboard driver for this
+ controller.
+
+ This routine is called by the UEFI driver framework during connect
+ processing if the controller passes the tests in I2cBusDriverSupported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to work with.
+ @param[in] RemainingDevicePath Not used, always produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtualKeyboardDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ VK_CONTEXT *VkContext;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverStart Start\n"));
+
+ VkContext = AllocateZeroPool (sizeof (VK_CONTEXT));
+ if (VkContext == NULL) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - No memory for virtual keyboard driver\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR (Status);
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ (VOID**) &VkContext->AbsolutePointer,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to open absolute pointer protocol, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEdkiiTouchPanelGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - TouchPanel GUID not found, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**) &VkContext->GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Graphics output protocol not available, Status: %r\n", Status));
+ goto Error;
+ }
+
+ VkContext->HiiHandle = mHiiHandle;
+ Status = VkApiStart (VkContext, Controller);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to VkApiStart, Status: %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ VkContext,
+ &gEfiSimpleTextInProtocolGuid,
+ &VkContext->SimpleTextIn,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &VkContext->SimpleTextInEx,
+ &gEfiConsoleInDeviceGuid,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to install VK protocols, Status: %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ goto Error;
+ }
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverStart Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ if (VkContext != NULL) {
+ FreePool (VkContext);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Restore setting if connect device fail.
+ //
+ PcdSet32S (PcdConOutRow, mOrigConOutRow);
+ PcdSet32S (PcdSetupConOutRow, mOrigSetupConOutRow);
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart End\n"));
+
+ return Status;
+}
+
+/**
+ Disconnect from the controller.
+
+ This routine disconnects from the controller.
+
+ This routine is called by DriverUnload when the I2C bus driver
+ is being unloaded.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Controller Handle of device to stop driver on.
+ @param[in] NumberOfChildren How many children need to be stopped.
+ @param[in] ChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtualKeyboardDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ VK_CONTEXT *VkContext;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Start\n"));
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID**)&VkContext,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_SUCCESS;
+ goto Success;
+ }
+
+ //
+ // Done with the driver protocol
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close the VK protocol, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Remove ConsoleIn protocols first to close the link in ConSplitter
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiConsoleInDeviceGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall the protocols, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Remove the remaining protocols
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ VkContext,
+ &gEfiSimpleTextInProtocolGuid,
+ &VkContext->SimpleTextIn,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &VkContext->SimpleTextInEx,
+ &gEfiConsoleInDeviceGuid,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall the protocols, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Stop the driver
+ //
+ VkApiStop (VkContext);
+
+ //
+ // Release the pointer protocol upon failure
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close absolute pointer protocol, Status: %r\n", Status));
+ goto Error;
+ }
+
+ //
+ // Release VkContext
+ //
+ if (VkContext != NULL) {
+ FreePool (VkContext);
+ }
+
+Success:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop End\n"));
+ return Status;
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtualKeyboardDriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Start\n"));
+
+ //
+ // Retrieve array of all handles in the handle database
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to locate handle buffer, Status: %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ goto Error;
+ }
+
+ //
+ // Disconnect the current driver from handles in the handle database
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->DisconnectController (HandleBuffer[Index], ImageHandle, NULL);
+ }
+
+ //
+ // Free the array of handles
+ //
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ //
+ // Uninstall protocols installed in the driver entry point
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gVirtualKeyboardDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gVirtualKeyboardComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gVirtualKeyboardComponentName2,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto Error;
+ }
+
+ HiiRemovePackages (mHiiHandle);
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Success, Status: %r\n", Status));
+ goto End;
+
+Error:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Failed, Status: %r\n", Status));
+
+End:
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload End\n"));
+ return Status;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {
+ VirtualKeyboardDriverSupported,
+ VirtualKeyboardDriverStart,
+ VirtualKeyboardDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtualKeyboardDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverEntryPoint Start\n"));
+ //
+ // Install UEFI Driver Model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gVirtualKeyboardDriverBinding,
+ ImageHandle,
+ &gVirtualKeyboardComponentName,
+ &gVirtualKeyboardComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mHiiHandle = HiiAddPackages (
+ &gEfiCallerIdGuid,
+ NULL,
+ VirtualKeyboardDxeImages,
+ NULL
+ );
+ ASSERT (mHiiHandle != NULL);
+
+ mOrigConOutRow = PcdGet32 (PcdConOutRow);
+ mOrigSetupConOutRow = PcdGet32 (PcdSetupConOutRow);
+
+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverEntryPoint End\n"));
+ return Status;
+}
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
new file mode 100644
index 0000000000..38843443e1
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
@@ -0,0 +1,78 @@
+## @file
+# Instance of virtual keyboard driver binding protocol.
+#
+# Compliant with efi driver model, 1. VirtualKeyboardDriverSupported
+# determines if the pointer and GOP are available. 2.
+# VirtualKeyboardDriverStart initializes an instance of the virtual
+# keyboard driver for a particular controller. 3.
+# VirtualKeyboardDriverStop is called by DriverUnload when the I2C bus
+# driver is being unload.
+#
+# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VirtualKeyboardDxe
+ FILE_GUID = E4735AAC-9C27-493f-86EA-9EFF43D7ADCD
+ VERSION_STRING = 2.0
+ MODULE_TYPE = UEFI_DRIVER
+ ENTRY_POINT = VirtualKeyboardDriverEntryPoint
+ UNLOAD_IMAGE = VirtualKeyboardDriverUnload
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+# DRIVER_BINDING = gVirtualKeyboardDriverBinding;
+# COMPONENT_NAME = gVirtualKeyboardComponentName;
+# COMPONENT_NAME2 = gVirtualKeyboardComponentName2;
+#
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ PcdLib
+ HiiLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow
+
+[Sources]
+ CapitalLetterKeyboard.bmp
+ DigitKeyboard.bmp
+ FullIcon.bmp
+ SimpleIcon.bmp
+ SimpleKeyboard.bmp
+ KeyboardLayout.idf
+ KeyboardLayout.c
+ ComponentName.c
+ ComponentName.h
+ Keyboard.c
+ VirtualKeyboard.h
+ VirtualKeyboardDriver.c
+
+[Protocols]
+ gEfiAbsolutePointerProtocolGuid ## TO_START
+ gEfiDriverBindingProtocolGuid ## PRODUCES
+ gEfiGraphicsOutputProtocolGuid ## TO_START
+ gEfiSimpleTextInProtocolGuid ## BY_START
+ gEfiSimpleTextInputExProtocolGuid ## BY_START
+ gEfiHiiImageExProtocolGuid ## TO_START
+
+[Guids]
+ gEfiConsoleInDeviceGuid ## SOMETIMES_PRODUCES
+ gEdkiiTouchPanelGuid ## TO_START
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
new file mode 100644
index 0000000000..c26db01f09
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
@@ -0,0 +1,26 @@
+## @file
+# This package provides advanced feature functionality for User Authentication support.
+# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg.
+#
+# The DEC files are used by the utilities that parse DSC and
+# INF files to generate AutoGen.c and AutoGen.h files
+# for the build infrastructure.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010017
+ PACKAGE_NAME = VirtualKeyboardFeaturePkg
+ PACKAGE_GUID = A40DFD69-3552-40E8-8D3D-89741B03B9E1
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[Guids]
+ ## GUID used for VirtualKeyboardDriver to open TouchPanel protocol.
+ gEdkiiTouchPanelGuid = { 0x91b1d27b, 0xe126, 0x48d1, { 0x82, 0x34, 0xd2, 0x8b, 0x81, 0xc8, 0x83, 0x62 }}
diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
new file mode 100644
index 0000000000..ab3605fa15
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
@@ -0,0 +1,30 @@
+## @file
+# This is a build description file for the User Authentication advanced feature.
+# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg.
+#
+# The DEC files are used by the utilities that parse DSC and
+# INF files to generate AutoGen.c and AutoGen.h files
+# for the build infrastructure.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = VirtualKeyboardFeaturePkg
+ PLATFORM_GUID = 6D396683-C82B-41D5-84E7-BB6E13B7C2BF
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME)
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+ PEI_ARCH = IA32
+ DXE_ARCH = X64
+
+#
+# This package always builds the feature.
+#
+!include Include/VirtualKeyboardFeature.dsc
--
2.24.0.windows.2
reply other threads:[~2020-04-15 1:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200415013742.14842-1-ming.tan@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox