From 233068974fe19d0b4f09c31f102784a7b2b1e167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Cort=C3=A9s?= Date: Wed, 14 Aug 2024 19:03:56 -0400 Subject: [PATCH] add buttons (not functional for now) --- MSM8909Pkg/CommonDsc.dsc.inc | 3 + .../GenericKeypadDevice.c | 56 ++ .../GenericKeypadDeviceDxe.inf | 29 + MSM8909Pkg/Drivers/KeypadDxe/ComponentName.c | 352 +++++++++ MSM8909Pkg/Drivers/KeypadDxe/Keypad.c | 583 +++++++++++++++ MSM8909Pkg/Drivers/KeypadDxe/Keypad.h | 402 ++++++++++ .../Drivers/KeypadDxe/KeypadController.c | 138 ++++ MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf | 57 ++ MSM8909Pkg/Drivers/KeypadDxe/KeypadTextIn.c | 700 ++++++++++++++++++ MSM8909Pkg/Drivers/KeypadDxe/Source.txt | 2 + .../Include/Configuration/DeviceMemoryMap.h | 9 +- MSM8909Pkg/Include/Library/AtomicLib.h | 61 ++ MSM8909Pkg/Include/Library/BitmapLib.h | 62 ++ .../Include/Library/KeypadDeviceHelperLib.h | 168 +++++ .../Include/Library/KeypadDeviceImplLib.h | 9 + MSM8909Pkg/Include/Protocol/KeypadDevice.h | 29 + .../KeypadDeviceHelperLib.c | 23 + .../KeypadDeviceHelperLib.inf | 17 + .../KeypadDeviceImplLib/KeypadDeviceImplLib.c | 101 +++ .../KeypadDeviceImplLib.inf | 20 + MSM8909Pkg/MSM8909Pkg.dsc | 3 + MSM8909Pkg/MSM8909Pkg.fdf | 3 + 22 files changed, 2824 insertions(+), 3 deletions(-) create mode 100644 MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDevice.c create mode 100644 MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/ComponentName.c create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/Keypad.c create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/Keypad.h create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/KeypadController.c create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/KeypadTextIn.c create mode 100644 MSM8909Pkg/Drivers/KeypadDxe/Source.txt create mode 100644 MSM8909Pkg/Include/Library/AtomicLib.h create mode 100644 MSM8909Pkg/Include/Library/BitmapLib.h create mode 100644 MSM8909Pkg/Include/Library/KeypadDeviceHelperLib.h create mode 100644 MSM8909Pkg/Include/Library/KeypadDeviceImplLib.h create mode 100644 MSM8909Pkg/Include/Protocol/KeypadDevice.h create mode 100644 MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.c create mode 100644 MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.inf create mode 100644 MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c create mode 100644 MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf diff --git a/MSM8909Pkg/CommonDsc.dsc.inc b/MSM8909Pkg/CommonDsc.dsc.inc index 4311579..3dc78c3 100644 --- a/MSM8909Pkg/CommonDsc.dsc.inc +++ b/MSM8909Pkg/CommonDsc.dsc.inc @@ -66,6 +66,9 @@ ResetSystemLib|ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf + # KeypadDeviceHelperLib|MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.inf + # KeypadDeviceImplLib|MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf + # ARM PL011 UART Driver PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf diff --git a/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDevice.c b/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDevice.c new file mode 100644 index 0000000..829a0a5 --- /dev/null +++ b/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDevice.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +typedef struct { + VENDOR_DEVICE_PATH Keypad; + EFI_DEVICE_PATH End; +} KEYPAD_DEVICE_PATH; + +KEYPAD_DEVICE_PATH mInternalDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8), + }, + }, + EFI_CALLER_ID_GUID, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } + } +}; + +STATIC KEYPAD_DEVICE_PROTOCOL mInternalKeypadDevice = { + KeypadDeviceImplReset, + KeypadDeviceImplGetKeys, +}; + +EFI_STATUS +EFIAPI +KeypadDeviceDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gSc8830KeypadDeviceProtocolGuid, + &mInternalKeypadDevice, + &gEfiDevicePathProtocolGuid, + &mInternalDevicePath, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf b/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf new file mode 100644 index 0000000..746a02d --- /dev/null +++ b/MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf @@ -0,0 +1,29 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GenericKeypadDeviceDxe + FILE_GUID = 39A24CF8-411E-48EB-8BEA-3ED07327F400 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = KeypadDeviceDxeInitialize + +[Sources.common] + GenericKeypadDevice.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MSM8909Pkg/MSM8909Pkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + MemoryAllocationLib + KeypadDeviceImplLib + +[Protocols] + gSc8830KeypadDeviceProtocolGuid + gEfiDevicePathProtocolGuid + +[Depex] + TRUE diff --git a/MSM8909Pkg/Drivers/KeypadDxe/ComponentName.c b/MSM8909Pkg/Drivers/KeypadDxe/ComponentName.c new file mode 100644 index 0000000..312c3f6 --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/ComponentName.c @@ -0,0 +1,352 @@ +/** @file + Routines related Component Name protocol. + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Keypad.h" + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +KeypadComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +KeypadComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gKeypadComponentName = { + KeypadComponentNameGetDriverName, + KeypadComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gKeypadComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) KeypadComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) KeypadComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mKeypadDriverNameTable[] = { + { + "eng;en", + L"Keypad Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +KeypadComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mKeypadDriverNameTable, + DriverName, + (BOOLEAN)(This == &gKeypadComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +KeypadComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check Controller's handle + // + Status = EfiTestManagedDevice (ControllerHandle, gKeypadControllerDriver.DriverBindingHandle, &gSc8830KeypadDeviceProtocolGuid); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &ConIn, + gKeypadControllerDriver.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ConsoleIn = KEYPAD_CONSOLE_IN_DEV_FROM_THIS (ConIn); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + ConsoleIn->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gKeypadComponentName) + ); +} diff --git a/MSM8909Pkg/Drivers/KeypadDxe/Keypad.c b/MSM8909Pkg/Drivers/KeypadDxe/Keypad.c new file mode 100644 index 0000000..dd0789e --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/Keypad.c @@ -0,0 +1,583 @@ +/** @file + + Keypad driver. Routines that interacts with callers, + conforming to EFI driver model + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Keypad.h" +#include + +// +// Function prototypes +// +/** + Test controller is a keypad Controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver's controller + @param RemainingDevicePath children device path + + @retval EFI_UNSUPPORTED controller is not floppy disk + @retval EFI_SUCCESS controller is floppy disk +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Create KEYPAD_CONSOLE_IN_DEV instance on controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver controller handle + @param RemainingDevicePath Children's device path + + @retval whether success to create floppy control instance. +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop this driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Free the waiting key notify list. + + @param ListHead Pointer to list head + + @retval EFI_INVALID_PARAMETER ListHead is NULL + @retval EFI_SUCCESS Sucess to free NotifyList +**/ +EFI_STATUS +KbdFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ); + +// +// DriverBinding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gKeypadControllerDriver = { + KeypadControllerDriverSupported, + KeypadControllerDriverStart, + KeypadControllerDriverStop, + 0xa, + NULL, + NULL +}; + +/** + Test controller is a keypad Controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver's controller + @param RemainingDevicePath children device path + + @retval EFI_UNSUPPORTED controller is not floppy disk + @retval EFI_SUCCESS controller is floppy disk +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + KEYPAD_DEVICE_PROTOCOL *KeypadDevice; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gSc8830KeypadDeviceProtocolGuid, + (VOID **) &KeypadDevice, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gSc8830KeypadDeviceProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +STATIC +VOID +EFIAPI +KeypadReturnApiPushEfikeyBufTail ( + KEYPAD_RETURN_API *This, + EFI_KEY_DATA *KeyData + ) +{ + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + LIST_ENTRY *Link; + KEYPAD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + ConsoleIn = KEYPAD_CONSOLE_IN_DEV_FROM_KEYPAD_RETURN_API (This); + + // + // If the key can not be converted then just return. + // + if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) { + if (!ConsoleIn->IsSupportPartialKey) { + return; + } + } + + // + // Signal KeyNotify process event if this key pressed matches any key registered. + // + for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) { + CurrentNotify = CR ( + Link, + KEYPAD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + // + // The key notification function needs to run at TPL_CALLBACK + // while current TPL is TPL_NOTIFY. It will be invoked in + // KeyNotifyProcessHandler() which runs at TPL_CALLBACK. + // + PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, KeyData); + gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent); + } + } + + PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, KeyData); +} + +/** + Create KEYPAD_CONSOLE_IN_DEV instance on controller. + + @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL + @param Controller driver controller handle + @param RemainingDevicePath Children's device path + + @retval whether success to create floppy control instance. +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + KEYPAD_DEVICE_PROTOCOL *KeypadDevice; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + + // + // Get the ISA I/O Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gSc8830KeypadDeviceProtocolGuid, + (VOID **) &KeypadDevice, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate private data + // + ConsoleIn = AllocateZeroPool (sizeof (KEYPAD_CONSOLE_IN_DEV)); + if (ConsoleIn == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup the device instance + // + ConsoleIn->Signature = KEYPAD_CONSOLE_IN_DEV_SIGNATURE; + ConsoleIn->Handle = Controller; + (ConsoleIn->ConIn).Reset = KeypadEfiReset; + (ConsoleIn->ConIn).ReadKeyStroke = KeypadReadKeyStroke; + ConsoleIn->KeypadDevice = KeypadDevice; + ConsoleIn->KeypadReturnApi.PushEfikeyBufTail = KeypadReturnApiPushEfikeyBufTail; + ConsoleIn->Last = (UINT64)-1; + + ConsoleIn->ConInEx.Reset = KeypadEfiResetEx; + ConsoleIn->ConInEx.ReadKeyStrokeEx = KeypadReadKeyStrokeEx; + ConsoleIn->ConInEx.SetState = KeypadSetState; + ConsoleIn->ConInEx.RegisterKeyNotify = KeypadRegisterKeyNotify; + ConsoleIn->ConInEx.UnregisterKeyNotify = KeypadUnregisterKeyNotify; + + InitializeListHead (&ConsoleIn->NotifyList); + + // + // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. + // When KBC decode (IO port 0x60/0x64 decode) is not enabled, + // KeypadRead will read back as 0xFF and return status is EFI_SUCCESS. + // So instead we read status register to detect after read if KBC decode is enabled. + // + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + KeypadWaitForKey, + ConsoleIn, + &((ConsoleIn->ConIn).WaitForKey) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Setup the WaitForKeyEx event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + KeypadWaitForKeyEx, + ConsoleIn, + &(ConsoleIn->ConInEx.WaitForKeyEx) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // Setup a periodic timer, used for reading keystrokes at a fixed interval + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + KeypadTimerHandler, + ConsoleIn, + &ConsoleIn->TimerEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Status = gBS->SetTimer ( + ConsoleIn->TimerEvent, + TimerPeriodic, + KEYPAD_TIMER_INTERVAL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + KeyNotifyProcessHandler, + ConsoleIn, + &ConsoleIn->KeyNotifyProcessEvent + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Reset the keypad device + // + Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FALSE); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto ErrorExit; + } + + ConsoleIn->ControllerNameTable = NULL; + AddUnicodeString2 ( + "eng", + gKeypadComponentName.SupportedLanguages, + &ConsoleIn->ControllerNameTable, + L"Keypad Device", + TRUE + ); + AddUnicodeString2 ( + "en", + gKeypadComponentName2.SupportedLanguages, + &ConsoleIn->ControllerNameTable, + L"Keypad Device", + FALSE + ); + + + // + // Install protocol interfaces for the keypad device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextInProtocolGuid, + &ConsoleIn->ConIn, + &gEfiSimpleTextInputExProtocolGuid, + &ConsoleIn->ConInEx, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + return Status; + +ErrorExit: + if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { + gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); + } + + if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { + gBS->CloseEvent (ConsoleIn->TimerEvent); + } + if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { + gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); + } + if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) { + gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent); + } + KbdFreeNotifyList (&ConsoleIn->NotifyList); + if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { + FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); + } + + if (ConsoleIn != NULL) { + gBS->FreePool (ConsoleIn); + } + + gBS->CloseProtocol ( + Controller, + &gSc8830KeypadDeviceProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Stop this driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +KeypadControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + + // + // Disable Keypad + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &ConIn, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInputExProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ConsoleIn = KEYPAD_CONSOLE_IN_DEV_FROM_THIS (ConIn); + + if (ConsoleIn->TimerEvent != NULL) { + gBS->CloseEvent (ConsoleIn->TimerEvent); + ConsoleIn->TimerEvent = NULL; + } + + // + // Uninstall the SimpleTextIn and SimpleTextInEx protocols + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &ConsoleIn->ConIn, + &gEfiSimpleTextInputExProtocolGuid, + &ConsoleIn->ConInEx, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gSc8830KeypadDeviceProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free other resources + // + if ((ConsoleIn->ConIn).WaitForKey != NULL) { + gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); + (ConsoleIn->ConIn).WaitForKey = NULL; + } + if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { + gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); + ConsoleIn->ConInEx.WaitForKeyEx = NULL; + } + if (ConsoleIn->KeyNotifyProcessEvent != NULL) { + gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent); + ConsoleIn->KeyNotifyProcessEvent = NULL; + } + KbdFreeNotifyList (&ConsoleIn->NotifyList); + FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); + gBS->FreePool (ConsoleIn); + + return EFI_SUCCESS; +} + +/** + Free the waiting key notify list. + + @param ListHead Pointer to list head + + @retval EFI_INVALID_PARAMETER ListHead is NULL + @retval EFI_SUCCESS Sucess to free NotifyList +**/ +EFI_STATUS +KbdFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ) +{ + KEYPAD_CONSOLE_IN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + KEYPAD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + +/** + The module Entry Point for module Keypad. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeKeypad( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gKeypadControllerDriver, + ImageHandle, + &gKeypadComponentName, + &gKeypadComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + diff --git a/MSM8909Pkg/Drivers/KeypadDxe/Keypad.h b/MSM8909Pkg/Drivers/KeypadDxe/Keypad.h new file mode 100644 index 0000000..b8b61a8 --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/Keypad.h @@ -0,0 +1,402 @@ +/** @file + Keypad driver header file + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _KEYPAD_H_ +#define _KEYPAD_H_ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gKeypadControllerDriver; +extern EFI_COMPONENT_NAME_PROTOCOL gKeypadComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gKeypadComponentName2; + +// +// Driver Private Data +// +#define KEYPAD_CONSOLE_IN_DEV_SIGNATURE SIGNATURE_32 ('k', 'k', 'e', 'y') +#define KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 'n') + +typedef struct _KEYPAD_CONSOLE_IN_EX_NOTIFY { + UINTN Signature; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} KEYPAD_CONSOLE_IN_EX_NOTIFY; + +#define KEYPAD_EFI_KEY_MAX_COUNT 256 +typedef struct { + EFI_KEY_DATA Buffer[KEYPAD_EFI_KEY_MAX_COUNT]; + UINTN Head; + UINTN Tail; +} EFI_KEY_QUEUE; + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ConInEx; + + EFI_EVENT TimerEvent; + + KEYPAD_DEVICE_PROTOCOL *KeypadDevice; + KEYPAD_RETURN_API KeypadReturnApi; + + // counter value of the last poll + UINT64 Last; + + BOOLEAN LeftCtrl; + BOOLEAN RightCtrl; + BOOLEAN LeftAlt; + BOOLEAN RightAlt; + BOOLEAN LeftShift; + BOOLEAN RightShift; + BOOLEAN LeftLogo; + BOOLEAN RightLogo; + BOOLEAN Menu; + BOOLEAN SysReq; + + BOOLEAN CapsLock; + BOOLEAN NumLock; + BOOLEAN ScrollLock; + + BOOLEAN IsSupportPartialKey; + // + // Queue storing key scancodes + // + EFI_KEY_QUEUE EfiKeyQueue; + EFI_KEY_QUEUE EfiKeyQueueForNotify; + + // + // Error state + // + BOOLEAN KeypadErr; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // Notification Function List + // + LIST_ENTRY NotifyList; + EFI_EVENT KeyNotifyProcessEvent; +} KEYPAD_CONSOLE_IN_DEV; + +#define KEYPAD_CONSOLE_IN_DEV_FROM_KEYPAD_RETURN_API(a) CR (a, KEYPAD_CONSOLE_IN_DEV, KeypadReturnApi, KEYPAD_CONSOLE_IN_DEV_SIGNATURE) +#define KEYPAD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYPAD_CONSOLE_IN_DEV, ConIn, KEYPAD_CONSOLE_IN_DEV_SIGNATURE) +#define TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS(a) \ + CR (a, \ + KEYPAD_CONSOLE_IN_DEV, \ + ConInEx, \ + KEYPAD_CONSOLE_IN_DEV_SIGNATURE \ + ) + +#define TABLE_END 0x0 + +#define KEYPAD_TIMER_INTERVAL 200000 // 0.02s + +// +// Driver entry point +// +/** + The user Entry Point for module KeypadDxe. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InstallKeypadDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Other functions that are used among .c files +// + +/** + Process key notify. + + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. +**/ +VOID +EFIAPI +KeyNotifyProcessHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Perform 8042 controller and keypad Initialization. + If ExtendedVerification is TRUE, do additional test for + the keypad interface + + @param ConsoleIn - KEYPAD_CONSOLE_IN_DEV instance pointer + @param ExtendedVerification - indicates a thorough initialization + + @retval EFI_DEVICE_ERROR Fail to init keypad + @retval EFI_SUCCESS Success to init keypad +**/ +EFI_STATUS +InitKeypad ( + IN OUT KEYPAD_CONSOLE_IN_DEV *ConsoleIn, + IN BOOLEAN ExtendedVerification + ); + +/** + Timer event handler: read a series of scancodes from 8042 + and put them into memory scancode buffer. + it read as much scancodes to either fill + the memory buffer or empty the keypad buffer. + It is registered as running under TPL_NOTIFY + + @param Event - The timer event + @param Context - A KEYPAD_CONSOLE_IN_DEV pointer + +**/ +VOID +EFIAPI +KeypadTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + logic reset keypad + Implement SIMPLE_TEXT_IN.Reset() + Perform 8042 controller and keypad initialization + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param ExtendedVerification Indicate that the driver may perform a more + exhaustive verification operation of the device during + reset, now this par is ignored in this driver + +**/ +EFI_STATUS +EFIAPI +KeypadEfiReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Implement SIMPLE_TEXT_IN.ReadKeyStroke(). + Retrieve key values for driver user. + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param Key The output buffer for key value + + @retval EFI_SUCCESS success to read key stroke +**/ +EFI_STATUS +EFIAPI +KeypadReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +/** + Event notification function for SIMPLE_TEXT_IN.WaitForKey event + Signal the event if there is key available + + @param Event the event object + @param Context waitting context + +**/ +VOID +EFIAPI +KeypadWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event + Signal the event if there is key available + + @param Event event object + @param Context waiting context + +**/ +VOID +EFIAPI +KeypadWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Simple Text Input Ex protocol function prototypes +// + +/** + Reset the input device and optionaly run diagnostics + + @param This - Protocol instance pointer. + @param ExtendedVerification - Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS - The device was reset. + @retval EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +KeypadEfiResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + + @param This - Protocol instance pointer. + @param KeyData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + @retval EFI_SUCCESS - The keystroke information was returned. + @retval EFI_NOT_READY - There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to + hardware errors. + @retval EFI_INVALID_PARAMETER - KeyData is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ); + +/** + Set certain state for the input device. + + @param This - Protocol instance pointer. + @param KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the + state for the input device. + + @retval EFI_SUCCESS - The device state was set successfully. + @retval EFI_DEVICE_ERROR - The device is not functioning correctly and could + not have the setting adjusted. + @retval EFI_UNSUPPORTED - The device does not have the ability to set its state. + @retval EFI_INVALID_PARAMETER - KeyToggleState is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ); + +/** + Register a notification function for a particular keystroke for the input device. + + @param This - Protocol instance pointer. + @param KeyData - A pointer to a buffer that is filled in with the keystroke + information data for the key that was pressed. + @param KeyNotificationFunction - Points to the function to be called when the key + sequence is typed specified by KeyData. + @param NotifyHandle - Points to the unique handle assigned to the registered notification. + + @retval EFI_SUCCESS - The notification function was registered successfully. + @retval EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures. + @retval EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ); + +/** + Remove a registered notification function from a particular keystroke. + + @param This - Protocol instance pointer. + @param NotificationHandle - The handle of the notification function being unregistered. + + + @retval EFI_SUCCESS - The notification function was unregistered successfully. + @retval EFI_INVALID_PARAMETER - The NotificationHandle is invalid. + @retval EFI_NOT_FOUND - Can not find the matching entry in database. + +**/ +EFI_STATUS +EFIAPI +KeypadUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ); + +/** + Push one key data to the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData The key data to push. +**/ +VOID +PushEfikeyBufTail ( + IN EFI_KEY_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ); + +/** + Judge whether is a registed key + + @param RegsiteredData A pointer to a buffer that is filled in with the keystroke + state data for the key that was registered. + @param InputData A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + @retval TRUE Key be pressed matches a registered key. + @retval FLASE Match failed. + +**/ +BOOLEAN +IsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ); + +#endif diff --git a/MSM8909Pkg/Drivers/KeypadDxe/KeypadController.c b/MSM8909Pkg/Drivers/KeypadDxe/KeypadController.c new file mode 100644 index 0000000..1d83664 --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/KeypadController.c @@ -0,0 +1,138 @@ +/** @file + Routines that talk to the KeypadDevice protocol + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Keypad.h" + +/** + Display error message. + + @param ConsoleIn Pointer to instance of KEYPAD_CONSOLE_IN_DEV + @param ErrMsg Unicode string of error message + +**/ +VOID +KeypadError ( + IN KEYPAD_CONSOLE_IN_DEV *ConsoleIn, + IN CHAR16 *ErrMsg + ) +{ + ConsoleIn->KeypadErr = TRUE; +} + +/** + Timer event handler: read a series of scancodes from 8042 + and put them into memory scancode buffer. + it read as much scancodes to either fill + the memory buffer or empty the keypad buffer. + It is registered as running under TPL_NOTIFY + + @param Event The timer event + @param Context A KEYPAD_CONSOLE_IN_DEV pointer + +**/ +VOID +EFIAPI +KeypadTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + EFI_TPL OldTpl; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + + ConsoleIn = (KEYPAD_CONSOLE_IN_DEV *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + if (((KEYPAD_CONSOLE_IN_DEV *) Context)->KeypadErr) { + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return ; + } + + UINT64 CurrentCounterValue = GetPerformanceCounter(); + UINT64 DeltaCounter = CurrentCounterValue - ConsoleIn->Last; + ConsoleIn->Last = CurrentCounterValue; + + ConsoleIn->KeypadDevice->GetKeys(ConsoleIn->KeypadDevice, &ConsoleIn->KeypadReturnApi, GetTimeInNanoSecond(DeltaCounter)); + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + +/** + Perform 8042 controller and keypad Initialization. + If ExtendedVerification is TRUE, do additional test for + the keypad interface + + @param ConsoleIn - KEYPAD_CONSOLE_IN_DEV instance pointer + @param ExtendedVerification - indicates a thorough initialization + + @retval EFI_DEVICE_ERROR Fail to init keypad + @retval EFI_SUCCESS Success to init keypad +**/ +EFI_STATUS +InitKeypad ( + IN OUT KEYPAD_CONSOLE_IN_DEV *ConsoleIn, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + ConsoleIn->KeypadDevice->Reset(ConsoleIn->KeypadDevice); + + // + // Clear Memory Scancode Buffer + // + ConsoleIn->EfiKeyQueue.Head = 0; + ConsoleIn->EfiKeyQueue.Tail = 0; + ConsoleIn->EfiKeyQueueForNotify.Head = 0; + ConsoleIn->EfiKeyQueueForNotify.Tail = 0; + + // + // Reset the status indicators + // + ConsoleIn->CapsLock = FALSE; + ConsoleIn->NumLock = FALSE; + ConsoleIn->ScrollLock = FALSE; + ConsoleIn->LeftCtrl = FALSE; + ConsoleIn->RightCtrl = FALSE; + ConsoleIn->LeftAlt = FALSE; + ConsoleIn->RightAlt = FALSE; + ConsoleIn->LeftShift = FALSE; + ConsoleIn->RightShift = FALSE; + ConsoleIn->LeftLogo = FALSE; + ConsoleIn->RightLogo = FALSE; + ConsoleIn->Menu = FALSE; + ConsoleIn->SysReq = FALSE; + + ConsoleIn->IsSupportPartialKey = FALSE; + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + +} diff --git a/MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf b/MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf new file mode 100644 index 0000000..6d26fa0 --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf @@ -0,0 +1,57 @@ +## @file +# Keypad Driver. +# +# Keypad Driver for UEFI. The keypad type implemented follows IBM +# compatible PS2 protocol using Scan Code Set 1. +# +# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = KeypadDxe + FILE_GUID = 463C9415-765B-4AE8-9B1A-AA5C6ECB2892 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeKeypad + +[Sources] + ComponentName.c + Keypad.h + KeypadController.c + KeypadTextIn.c + Keypad.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + MSM8909Pkg/MSM8909Pkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiRuntimeServicesTableLib + DebugLib + DevicePathLib + UefiBootServicesTableLib + UefiLib + UefiDriverEntryPoint + BaseLib + BaseMemoryLib + TimerLib + PcdLib + IoLib + +[Protocols] + gEfiSimpleTextInProtocolGuid ## BY_START + gEfiSimpleTextInputExProtocolGuid ## BY_START + gSc8830KeypadDeviceProtocolGuid diff --git a/MSM8909Pkg/Drivers/KeypadDxe/KeypadTextIn.c b/MSM8909Pkg/Drivers/KeypadDxe/KeypadTextIn.c new file mode 100644 index 0000000..446e35a --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/KeypadTextIn.c @@ -0,0 +1,700 @@ +/** @file + Routines implements SIMPLE_TEXT_IN protocol's interfaces based on interfaces + provided by KeypadController.c. + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "Keypad.h" + +/** + Check whether the EFI key buffer is empty. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + + @retval TRUE The EFI key buffer is empty. + @retval FALSE The EFI key buffer isn't empty. +**/ +BOOLEAN +IsEfikeyBufEmpty ( + IN EFI_KEY_QUEUE *Queue + ) +{ + return (BOOLEAN) (Queue->Head == Queue->Tail); +} + +/** + Read & remove one key data from the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData Receive the key data. + + @retval EFI_SUCCESS The key data is popped successfully. + @retval EFI_NOT_READY There is no key data available. +**/ +EFI_STATUS +PopEfikeyBufHead ( + IN EFI_KEY_QUEUE *Queue, + OUT EFI_KEY_DATA *KeyData OPTIONAL + ) +{ + if (IsEfikeyBufEmpty (Queue)) { + return EFI_NOT_READY; + } + // + // Retrieve and remove the values + // + if (KeyData != NULL) { + CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA)); + } + Queue->Head = (Queue->Head + 1) % KEYPAD_EFI_KEY_MAX_COUNT; + return EFI_SUCCESS; +} + +/** + Push one key data to the EFI key buffer. + + @param Queue Pointer to instance of EFI_KEY_QUEUE. + @param KeyData The key data to push. +**/ +VOID +PushEfikeyBufTail ( + IN EFI_KEY_QUEUE *Queue, + IN EFI_KEY_DATA *KeyData + ) +{ + if ((Queue->Tail + 1) % KEYPAD_EFI_KEY_MAX_COUNT == Queue->Head) { + // + // If Queue is full, pop the one from head. + // + PopEfikeyBufHead (Queue, NULL); + } + CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA)); + Queue->Tail = (Queue->Tail + 1) % KEYPAD_EFI_KEY_MAX_COUNT; +} + +/** + Judge whether is a registed key + + @param RegsiteredData A pointer to a buffer that is filled in with the keystroke + state data for the key that was registered. + @param InputData A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + @retval TRUE Key be pressed matches a registered key. + @retval FLASE Match failed. + +**/ +BOOLEAN +IsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ) + +{ + ASSERT (RegsiteredData != NULL && InputData != NULL); + + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || + (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { + return FALSE; + } + + // + // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. + // + if (RegsiteredData->KeyState.KeyShiftState != 0 && + RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { + return FALSE; + } + if (RegsiteredData->KeyState.KeyToggleState != 0 && + RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { + return FALSE; + } + + return TRUE; + +} + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param ConsoleInDev Keypad private structure + @param KeyData A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to + hardware errors. + @retval EFI_INVALID_PARAMETER KeyData is NULL. + +**/ +EFI_STATUS +KeypadReadKeyStrokeWorker ( + IN KEYPAD_CONSOLE_IN_DEV *ConsoleInDev, + OUT EFI_KEY_DATA *KeyData + ) + +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + KeypadTimerHandler (NULL, ConsoleInDev); + + if (ConsoleInDev->KeypadErr) { + Status = EFI_DEVICE_ERROR; + } else { + Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData); + } + + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Perform 8042 controller and keypad initialization which implement SIMPLE_TEXT_IN.Reset() + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param ExtendedVerification Indicate that the driver may perform a more + exhaustive verification operation of the device during + reset, now this par is ignored in this driver + +**/ +EFI_STATUS +EFIAPI +KeypadEfiReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + EFI_TPL OldTpl; + + ConsoleIn = KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + if (ConsoleIn->KeypadErr) { + return EFI_DEVICE_ERROR; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Call InitKeypad to initialize the keypad + // + Status = InitKeypad (ConsoleIn, ExtendedVerification); + if (EFI_ERROR (Status)) { + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_DEVICE_ERROR; + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +/** + Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke(). + + @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL + @param Key The output buffer for key value + + @retval EFI_SUCCESS success to read key stroke +**/ +EFI_STATUS +EFIAPI +KeypadReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + EFI_KEY_DATA KeyData; + + ConsoleIn = KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (1) { + // + // If there is no pending key, then return. + // + Status = KeypadReadKeyStrokeWorker (ConsoleIn, &KeyData); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If it is partial keystroke, skip it. + // + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + continue; + } + // + // Translate the CTRL-Alpha characters to their corresponding control value + // (ctrl-a = 0x0001 through ctrl-Z = 0x001A) + // + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); + } + } + + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + return EFI_SUCCESS; + } +} + +/** + Event notification function for SIMPLE_TEXT_IN.WaitForKey event + Signal the event if there is key available + + @param Event the event object + @param Context waitting context + +**/ +VOID +EFIAPI +KeypadWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_TPL OldTpl; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + EFI_KEY_DATA KeyData; + + ConsoleIn = (KEYPAD_CONSOLE_IN_DEV *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + KeypadTimerHandler (NULL, ConsoleIn); + + if (!ConsoleIn->KeypadErr) { + // + // WaitforKey doesn't suppor the partial key. + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) { + CopyMem ( + &KeyData, + &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]), + sizeof (EFI_KEY_DATA) + ); + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData); + continue; + } + // + // if there is pending value key, signal the event. + // + gBS->SignalEvent (Event); + break; + } + } + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + +/** + Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event + Signal the event if there is key available + + @param Event event object + @param Context waiting context + +**/ +VOID +EFIAPI +KeypadWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) + +{ + KeypadWaitForKey (Event, Context); +} + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +KeypadEfiResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) + +{ + KEYPAD_CONSOLE_IN_DEV *ConsoleInDev; + + ConsoleInDev = TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + + return ConsoleInDev->ConIn.Reset ( + &ConsoleInDev->ConIn, + ExtendedVerification + ); +} + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to + hardware errors. + @retval EFI_INVALID_PARAMETER KeyData is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) + +{ + KEYPAD_CONSOLE_IN_DEV *ConsoleInDev; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + return KeypadReadKeyStrokeWorker (ConsoleInDev, KeyData); +} + +/** + Set certain state for the input device. + + @param This Protocol instance pointer. + @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the + state for the input device. + + @retval EFI_SUCCESS The device state was set successfully. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could + not have the setting adjusted. + @retval EFI_UNSUPPORTED The device does not have the ability to set its state. + @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) + +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + if (ConsoleInDev->KeypadErr) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } + + if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + + // + // Update the status light + // + ConsoleInDev->ScrollLock = FALSE; + ConsoleInDev->NumLock = FALSE; + ConsoleInDev->CapsLock = FALSE; + ConsoleInDev->IsSupportPartialKey = FALSE; + + if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { + ConsoleInDev->ScrollLock = TRUE; + } + if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { + ConsoleInDev->NumLock = TRUE; + } + if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { + ConsoleInDev->CapsLock = TRUE; + } + if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { + ConsoleInDev->IsSupportPartialKey = TRUE; + } + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; + +} + +/** + Register a notification function for a particular keystroke for the input device. + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the keystroke + information data for the key that was pressed. + @param KeyNotificationFunction Points to the function to be called when the key + sequence is typed specified by KeyData. + @param NotifyHandle Points to the unique handle assigned to the registered notification. + + @retval EFI_SUCCESS The notification function was registered successfully. + @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures. + @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL. + +**/ +EFI_STATUS +EFIAPI +KeypadRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ) +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + KEYPAD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + KEYPAD_CONSOLE_IN_EX_NOTIFY *NewNotify; + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + KEYPAD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify; + Status = EFI_SUCCESS; + goto Exit; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (KEYPAD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYPAD_CONSOLE_IN_EX_NOTIFY)); + if (NewNotify == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + NewNotify->Signature = KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); + InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify; + Status = EFI_SUCCESS; + +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; + +} + +/** + Remove a registered notification function from a particular keystroke. + + @param This Protocol instance pointer. + @param NotificationHandle The handle of the notification function being unregistered. + + + @retval EFI_SUCCESS The notification function was unregistered successfully. + @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid. + +**/ +EFI_STATUS +EFIAPI +KeypadUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ) +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleInDev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + KEYPAD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConsoleInDev = TEXT_INPUT_EX_KEYPAD_CONSOLE_IN_DEV_FROM_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + KEYPAD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (CurrentNotify == NotificationHandle) { + // + // Remove the notification function from NotifyList and free resources + // + RemoveEntryList (&CurrentNotify->NotifyEntry); + + gBS->FreePool (CurrentNotify); + Status = EFI_SUCCESS; + goto Exit; + } + } + + // + // Can not find the specified Notification Handle + // + Status = EFI_INVALID_PARAMETER; +Exit: + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Process key notify. + + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. +**/ +VOID +EFIAPI +KeyNotifyProcessHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + KEYPAD_CONSOLE_IN_DEV *ConsoleIn; + EFI_KEY_DATA KeyData; + LIST_ENTRY *Link; + LIST_ENTRY *NotifyList; + KEYPAD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + EFI_TPL OldTpl; + + ConsoleIn = (KEYPAD_CONSOLE_IN_DEV *) Context; + + // + // Invoke notification functions. + // + NotifyList = &ConsoleIn->NotifyList; + while (TRUE) { + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData); + // + // Leave critical section + // + gBS->RestoreTPL (OldTpl); + if (EFI_ERROR (Status)) { + break; + } + for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) { + CurrentNotify = CR (Link, KEYPAD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYPAD_CONSOLE_IN_EX_NOTIFY_SIGNATURE); + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { + CurrentNotify->KeyNotificationFn (&KeyData); + } + } + } +} + diff --git a/MSM8909Pkg/Drivers/KeypadDxe/Source.txt b/MSM8909Pkg/Drivers/KeypadDxe/Source.txt new file mode 100644 index 0000000..5152b50 --- /dev/null +++ b/MSM8909Pkg/Drivers/KeypadDxe/Source.txt @@ -0,0 +1,2 @@ +URL: https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe +BRANCH: master @ 35dadd7c54 diff --git a/MSM8909Pkg/Include/Configuration/DeviceMemoryMap.h b/MSM8909Pkg/Include/Configuration/DeviceMemoryMap.h index ba462bf..4a3263c 100644 --- a/MSM8909Pkg/Include/Configuration/DeviceMemoryMap.h +++ b/MSM8909Pkg/Include/Configuration/DeviceMemoryMap.h @@ -59,8 +59,6 @@ typedef struct { static ARM_MEMORY_REGION_DESCRIPTOR_EX gDeviceMemoryDescriptorEx[] = { // EFI_RESOURCE_ EFI_RESOURCE_ATTRIBUTE_ ARM_REGION_ATTRIBUTE_ //MemBase, MemSize, MemLabel(32 Char.), BuildHob, ResourceType, ResourceAttribute, MemoryType, CacheAttributes -//------------- Register Regions ---------- -{0x00000000, 0x20000000, "Peripherals", AddMem, MEM_RES, UNCACHEABLE, RtCode, DEVICE}, //------------- DDR ------}, {0x80000000, 0x00010000, "HLOS 0", AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK}, {0x80C00000, 0x00040000, "UEFI Stack", AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK}, @@ -69,7 +67,12 @@ static ARM_MEMORY_REGION_DESCRIPTOR_EX gDeviceMemoryDescriptorEx[] = { {0x80200000, 0x00200000, "UEFI FD", AddMem, SYS_MEM, SYS_MEM_CAP, BsCode, WRITE_BACK}, {0x9eef4000, 0x00708000, "Display Reserved", AddMem, MEM_RES, WRITE_THROUGH, MaxMem, WRITE_THROUGH}, {0x80D00000, 0x0F3B0000, "HLOS 2", AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK}, -// {0x87800000, 0x00240000, "SMEM", AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED}, +{0x87800000, 0x00240000, "SMEM", AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED}, + +//------------- Register Regions ---------- +{0x12001000, 0x00001000, "GIC Distributor", AddDev, MMAP_IO, UNCACHEABLE, MmIO, DEVICE}, +{0x12002000, 0x00001000, "GIC Redistributors", AddDev, MMAP_IO, UNCACHEABLE, MmIO, DEVICE}, +{0xf5224000, 0x00001000, "PinCtrl", AddDev, MMAP_IO, UNCACHEABLE, MmIO, DEVICE}, //------------- Terminator for MMU ---------- {0, 0, "Terminator", 0, 0, 0, 0, 0} diff --git a/MSM8909Pkg/Include/Library/AtomicLib.h b/MSM8909Pkg/Include/Library/AtomicLib.h new file mode 100644 index 0000000..fd27c9f --- /dev/null +++ b/MSM8909Pkg/Include/Library/AtomicLib.h @@ -0,0 +1,61 @@ + +/* + * Copyright (c) 2008-2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __LIB_ATOMIC_H +#define __LIB_ATOMIC_H + +#include + +STATIC inline INTN AtomicAnd(volatile INTN *Address, INTN Value) { + EFI_TPL OriginalTPL; + INTN OldValue; + + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); + OldValue = *Address; + *Address &= Value; + gBS->RestoreTPL (OriginalTPL); + + return OldValue; +} + +STATIC inline INTN AtomicOr(volatile INTN *Address, INTN Value) { + EFI_TPL OriginalTPL; + INTN OldValue; + + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); + OldValue = *Address; + *Address |= Value; + gBS->RestoreTPL (OriginalTPL); + + return OldValue; +} + +STATIC inline INTN AtomicRead(volatile INTN *Address) { + return *Address; +} + +STATIC inline VOID AtomicSet(volatile INTN *Address, INTN Value) { + *Address = Value; +} + +#endif diff --git a/MSM8909Pkg/Include/Library/BitmapLib.h b/MSM8909Pkg/Include/Library/BitmapLib.h new file mode 100644 index 0000000..309a419 --- /dev/null +++ b/MSM8909Pkg/Include/Library/BitmapLib.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __LIB_BITMAP_H +#define __LIB_BITMAP_H + +#include + +#define BIT_SHIFT(x, bit) (((x) >> (bit)) & 1) +#define BITS(x, high, low) ((x) & (((1<<((high)+1))-1) & ~((1<<(low))-1))) +#define BITS_SHIFT(x, high, low) (((x) >> (low)) & ((1<<((high)-(low)+1))-1)) +#define BIT_SET(x, bit) (((x) & (1UL << (bit))) ? 1 : 0) + +#define BITMAP_BITS_PER_WORD (sizeof(UINTN) * 8) +#define BITMAP_NUM_WORDS(x) (((x) + BITMAP_BITS_PER_WORD - 1) / BITMAP_BITS_PER_WORD) +#define BITMAP_WORD(x) ((x) / BITMAP_BITS_PER_WORD) +#define BITMAP_BIT_IN_WORD(x) ((x) & (BITMAP_BITS_PER_WORD - 1)) + +#define BITMAP_BITS_PER_INT (sizeof(UINTN) * 8) +#define BITMAP_BIT_IN_INT(x) ((x) & (BITMAP_BITS_PER_INT - 1)) +#define BITMAP_INT(x) ((x) / BITMAP_BITS_PER_INT) + +#define BIT_MASK(x) (((x) >= sizeof(UINTN) * 8) ? (0UL-1) : ((1UL << (x)) - 1)) + +STATIC inline INTN BitmapSet(UINTN *bitmap, INTN bit) +{ + UINTN mask = 1UL << BITMAP_BIT_IN_INT(bit); + return AtomicOr(&((INTN *)bitmap)[BITMAP_INT(bit)], mask) & mask ? 1 : 0; +} + +STATIC inline INTN BitmapClear(UINTN *bitmap, INTN bit) +{ + UINTN mask = 1UL << BITMAP_BIT_IN_INT(bit); + + return AtomicAnd(&((INTN *)bitmap)[BITMAP_INT(bit)], ~mask) & mask ? 1:0; +} + +STATIC inline INTN BitmapTest(UINTN *bitmap, INTN bit) +{ + return BIT_SET(bitmap[BITMAP_WORD(bit)], BITMAP_BIT_IN_WORD(bit)); +} + +#endif diff --git a/MSM8909Pkg/Include/Library/KeypadDeviceHelperLib.h b/MSM8909Pkg/Include/Library/KeypadDeviceHelperLib.h new file mode 100644 index 0000000..352edf7 --- /dev/null +++ b/MSM8909Pkg/Include/Library/KeypadDeviceHelperLib.h @@ -0,0 +1,168 @@ +#ifndef __LIBRARY_KEYPAD_DEVICE_HELPER_H__ +#define __LIBRARY_KEYPAD_DEVICE_HELPER_H__ + +#include +#include +#include +#include + +#define MAX_SCANCODE 0x18 +#define MAX_UNCODE_CHAR 0x7f +#define MS2NS(ms) (((UINT64)(ms)) * 1000000ULL) + +typedef enum { + KEYSTATE_RELEASED, + KEYSTATE_PRESSED, + KEYSTATE_LONGPRESS_RELEASE, +} KEY_STATE; + +typedef struct { + // keydata to be send to the driver + EFI_KEY_DATA KeyData; + + // the time the current action has been running + UINT64 Time; + + // the current state of the key + KEY_STATE State; + + // the current key has to repeat sending events + BOOLEAN Repeat; + + // the user did a longpress + BOOLEAN Longpress; +} KEY_CONTEXT; + +extern UINTN gBitmapScanCodes[BITMAP_NUM_WORDS(MAX_SCANCODE)]; +extern UINTN gBitmapUnicodeChars[BITMAP_NUM_WORDS(MAX_UNCODE_CHAR)]; + +extern EFI_KEY_DATA gKeyDataPowerDown; +extern EFI_KEY_DATA gKeyDataPowerUp; +extern EFI_KEY_DATA gKeyDataPowerLongpress; + +STATIC inline VOID KeySetState(UINT16 ScanCode, CHAR16 UnicodeChar, BOOLEAN Value) +{ + if (ScanCode && ScanCodeKeyData, sizeof(Context->KeyData), 0); + Context->Time = 0; + Context->State = KEYSTATE_RELEASED; + Context->Repeat = FALSE; + Context->Longpress = FALSE; +} + +STATIC inline VOID LibKeyUpdateKeyStatus(KEY_CONTEXT *Context, KEYPAD_RETURN_API *KeypadReturnApi, BOOLEAN IsPressed, UINT64 Delta) { + // keep track of the actual state + KeySetState(Context->KeyData.Key.ScanCode, Context->KeyData.Key.UnicodeChar, IsPressed); + + // update key time + Context->Time += Delta; + + switch (Context->State) { + case KEYSTATE_RELEASED: + if (IsPressed) { + // change to pressed + Context->Time = 0; + Context->State = KEYSTATE_PRESSED; + } + break; + + case KEYSTATE_PRESSED: + if (IsPressed) { + // keyrepeat + if (Context->Repeat && Context->Time>=MS2NS(200)) { + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &Context->KeyData); + Context->Time = 0; + Context->Repeat = TRUE; + } + + else if (!Context->Longpress && Context->Time>=MS2NS(500)) { + // POWER, handle key combos + if (Context->KeyData.Key.UnicodeChar==CHAR_CARRIAGE_RETURN) { + if (KeyGetState(SCAN_DOWN, 0)) { + // report 's' + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &gKeyDataPowerDown); + } else if (KeyGetState(SCAN_UP, 0)) { + // report 'e' + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &gKeyDataPowerUp); + } else { + // report spacebar + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &gKeyDataPowerLongpress); + } + } + + // post first keyrepeat event + else { + // only start keyrepeat if we're not doing a combo + if (!KeyGetState(0, CHAR_CARRIAGE_RETURN)) { + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &Context->KeyData); + Context->Time = 0; + Context->Repeat = TRUE; + } + } + + Context->Longpress = TRUE; + } + } + + else { + if (!Context->Longpress) { + // we supressed down, so report it now + KeypadReturnApi->PushEfikeyBufTail(KeypadReturnApi, &Context->KeyData); + Context->State = KEYSTATE_LONGPRESS_RELEASE; + } + + else if (Context->Time>=MS2NS(10)) { + // we reported another key already + Context->Time = 0; + Context->Repeat = FALSE; + Context->Longpress = FALSE; + Context->State = KEYSTATE_RELEASED; + } + } + break; + + case KEYSTATE_LONGPRESS_RELEASE: + // change to released + Context->Time = 0; + Context->Repeat = FALSE; + Context->Longpress = FALSE; + Context->State = KEYSTATE_RELEASED; + break; + + default: + ASSERT(FALSE); + break; + } +} + +#endif diff --git a/MSM8909Pkg/Include/Library/KeypadDeviceImplLib.h b/MSM8909Pkg/Include/Library/KeypadDeviceImplLib.h new file mode 100644 index 0000000..98c6c28 --- /dev/null +++ b/MSM8909Pkg/Include/Library/KeypadDeviceImplLib.h @@ -0,0 +1,9 @@ +#ifndef __LIBRARY_KEYPAD_DEVICE_IMPL_H__ +#define __LIBRARY_KEYPAD_DEVICE_IMPL_H__ + +#include + +EFI_STATUS EFIAPI KeypadDeviceImplReset (KEYPAD_DEVICE_PROTOCOL *This); +EFI_STATUS KeypadDeviceImplGetKeys (KEYPAD_DEVICE_PROTOCOL *This, KEYPAD_RETURN_API *KeypadReturnApi, UINT64 Delta); + +#endif diff --git a/MSM8909Pkg/Include/Protocol/KeypadDevice.h b/MSM8909Pkg/Include/Protocol/KeypadDevice.h new file mode 100644 index 0000000..0c11bad --- /dev/null +++ b/MSM8909Pkg/Include/Protocol/KeypadDevice.h @@ -0,0 +1,29 @@ +#ifndef __PROTOCOL_KEYPAD_DEVICE_H__ +#define __PROTOCOL_KEYPAD_DEVICE_H__ + +#include + +#define KEYPAD_DEVICE_PROTOCOL_GUID \ + { 0xb27625b5, 0x0b6c, 0x4614, { 0xaa, 0x3c, 0x33, 0x13, 0xb5, 0x1d, 0x36, 0x46 } } + +typedef struct _KEYPAD_DEVICE_PROTOCOL KEYPAD_DEVICE_PROTOCOL; +typedef struct _KEYPAD_RETURN_API KEYPAD_RETURN_API; + +typedef VOID (EFIAPI *PUSH_EFI_KEY_BUF_TAIL) (KEYPAD_RETURN_API *This, EFI_KEY_DATA *KeyData); + +struct _KEYPAD_RETURN_API { + PUSH_EFI_KEY_BUF_TAIL PushEfikeyBufTail; +}; + + +typedef EFI_STATUS (EFIAPI *KEYPAD_RESET)(KEYPAD_DEVICE_PROTOCOL *This); +typedef EFI_STATUS (EFIAPI *KEYPAD_GET_KEYS)(KEYPAD_DEVICE_PROTOCOL *This, KEYPAD_RETURN_API *KeypadReturnApi, UINT64 Delta); + +struct _KEYPAD_DEVICE_PROTOCOL { + KEYPAD_RESET Reset; + KEYPAD_GET_KEYS GetKeys; +}; + +extern EFI_GUID gEFIDroidKeypadDeviceProtocolGuid; + +#endif diff --git a/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.c b/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.c new file mode 100644 index 0000000..b64a133 --- /dev/null +++ b/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.c @@ -0,0 +1,23 @@ +#include +#include + +UINTN gBitmapScanCodes[BITMAP_NUM_WORDS(MAX_SCANCODE)] = {0}; +UINTN gBitmapUnicodeChars[BITMAP_NUM_WORDS(MAX_UNCODE_CHAR)] = {0}; + +EFI_KEY_DATA gKeyDataPowerDown = { + .Key = { + .UnicodeChar = (CHAR16)'s', + } +}; + +EFI_KEY_DATA gKeyDataPowerUp = { + .Key = { + .UnicodeChar = (CHAR16)'e', + } +}; + +EFI_KEY_DATA gKeyDataPowerLongpress = { + .Key = { + .UnicodeChar = (CHAR16)' ', + } +}; diff --git a/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.inf b/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.inf new file mode 100644 index 0000000..1b06ce2 --- /dev/null +++ b/MSM8909Pkg/Library/KeypadDeviceHelperLib/KeypadDeviceHelperLib.inf @@ -0,0 +1,17 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = KeypadDeviceHelperLib + FILE_GUID = 8C5BCA24-1C7E-4EE2-AA2A-D625C1739251 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = KeypadDeviceHelperLib + +[Packages] + MdePkg/MdePkg.dec + MSM8909Pkg/MSM8909Pkg.dec + +[LibraryClasses] + BaseLib + +[Sources.common] + KeypadDeviceHelperLib.c diff --git a/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c b/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c new file mode 100644 index 0000000..8f2211c --- /dev/null +++ b/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c @@ -0,0 +1,101 @@ +#include + + +#include +#include +#include +#include + +typedef struct { + KEY_CONTEXT EfiKeyContext; + UINT32 PinctrlBase; + UINT32 BankOffset; + UINT32 PinNum; +} KEY_CONTEXT_PRIVATE; + +STATIC KEY_CONTEXT_PRIVATE KeyContextVolumeDown; + +STATIC KEY_CONTEXT_PRIVATE* KeyList[] = { + &KeyContextVolumeDown +}; + +STATIC +VOID +KeypadInitializeKeyContextPrivate ( + KEY_CONTEXT_PRIVATE *Context + ) +{ + Context->PinctrlBase = 0; + Context->BankOffset = 0; + Context->PinNum = 0; +} + +STATIC +KEY_CONTEXT_PRIVATE* +KeypadKeyCodeToKeyContext ( + UINT32 KeyCode + ) +{ + if (KeyCode == 102){ + return &KeyContextVolumeDown; + }else + return NULL; +} + +RETURN_STATUS +EFIAPI +KeypadDeviceImplConstructor ( + VOID + ) +{ + UINTN Index; + KEY_CONTEXT_PRIVATE *StaticContext; + + // Reset all keys + for (Index=0; IndexPinctrlBase = 0xf5224000; + StaticContext->BankOffset = 0x2; + StaticContext->PinNum = 113; + + return RETURN_SUCCESS; +} + +EFI_STATUS EFIAPI KeypadDeviceImplReset (KEYPAD_DEVICE_PROTOCOL *This) +{ + LibKeyInitializeKeyContext(&KeyContextVolumeDown.EfiKeyContext); + KeyContextVolumeDown.EfiKeyContext.KeyData.Key.ScanCode = SCAN_DOWN; + + return EFI_SUCCESS; +} + +EFI_STATUS KeypadDeviceImplGetKeys (KEYPAD_DEVICE_PROTOCOL *This, KEYPAD_RETURN_API *KeypadReturnApi, UINT64 Delta) +{ + BOOLEAN IsPressed; + UINTN Index; + + for (Index = 0; Index < (sizeof(KeyList) / sizeof(KeyList[0])); Index++) { + KEY_CONTEXT_PRIVATE *Context = KeyList[Index]; + + IsPressed = FALSE; + + UINT32 PinAddr = ((Context->PinctrlBase + Context->BankOffset) + 0x4); + + UINT32 PinState = MmioRead32(PinAddr); + + if ( !(PinState & (1 << Context->PinNum)) ) { + IsPressed = TRUE; + } + + LibKeyUpdateKeyStatus( + &Context->EfiKeyContext, KeypadReturnApi, IsPressed, Delta); + } + + return EFI_SUCCESS; +} diff --git a/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf b/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf new file mode 100644 index 0000000..cad89fd --- /dev/null +++ b/MSM8909Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf @@ -0,0 +1,20 @@ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = KeypadDeviceImplLib + FILE_GUID = A66E6466-0BF1-4211-8CD9-9FBCD1F460A6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = KeypadDeviceImplLib + CONSTRUCTOR = KeypadDeviceImplConstructor + +[Sources.common] + KeypadDeviceImplLib.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + MSM8909Pkg/MSM8909Pkg.dec + +[LibraryClasses] + KeypadDeviceHelperLib + TimerLib diff --git a/MSM8909Pkg/MSM8909Pkg.dsc b/MSM8909Pkg/MSM8909Pkg.dsc index 6b10716..4616bee 100644 --- a/MSM8909Pkg/MSM8909Pkg.dsc +++ b/MSM8909Pkg/MSM8909Pkg.dsc @@ -211,6 +211,9 @@ # SoC Drivers # + # MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf + # MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf + # # Virtual Keyboard # diff --git a/MSM8909Pkg/MSM8909Pkg.fdf b/MSM8909Pkg/MSM8909Pkg.fdf index 0f69055..3003d9d 100644 --- a/MSM8909Pkg/MSM8909Pkg.fdf +++ b/MSM8909Pkg/MSM8909Pkg.fdf @@ -136,6 +136,9 @@ READ_LOCK_STATUS = TRUE INF MSM8909Pkg/Drivers/SimpleFbDxe/SimpleFbDxe.inf INF MSM8909Pkg/Drivers/LogoDxe/LogoDxe.inf + # INF MSM8909Pkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf + # INF MSM8909Pkg/Drivers/KeypadDxe/KeypadDxe.inf + # # USB Host Support #