From bc2aeca8e77a72f29195f70644fa196ef08e3d34 Mon Sep 17 00:00:00 2001 From: sonic011gamer Date: Mon, 16 Oct 2023 22:28:55 +0300 Subject: [PATCH] Keys on 7885 --- Platform/Samsung/exynos7885/exynos7885.dsc | 1 + Platform/Samsung/exynos7885/exynos7885.fdf | 3 + .../KeypadDeviceImplLib/KeypadDeviceImplLib.c | 278 ++++++++++++++++++ .../KeypadDeviceImplLib.inf | 20 ++ .../PlatformMemoryMapLib.c | 2 +- .../ExynosPkg/Include/Protocol/KeypadDevice.h | 2 +- 6 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c create mode 100644 Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf diff --git a/Platform/Samsung/exynos7885/exynos7885.dsc b/Platform/Samsung/exynos7885/exynos7885.dsc index 2c370eb..50ea460 100644 --- a/Platform/Samsung/exynos7885/exynos7885.dsc +++ b/Platform/Samsung/exynos7885/exynos7885.dsc @@ -56,6 +56,7 @@ gSimpleInitTokenSpaceGuid.PcdLoggerdUseConsole|FALSE [LibraryClasses.common] + KeypadDeviceImplLib|Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf PlatformMemoryMapLib|Silicon/Samsung/Exynos7885Pkg/Library/PlatformMemoryMapLib/PlatformMemoryMapLib.inf PlatformPeiLib|Silicon/Samsung/Exynos7885Pkg/Library/PlatformPeiLib/PlatformPeiLib.inf PlatformPrePiLib|Silicon/Samsung/Exynos7885Pkg/Library/PlatformPrePiLib/PlatformPrePiLib.inf diff --git a/Platform/Samsung/exynos7885/exynos7885.fdf b/Platform/Samsung/exynos7885/exynos7885.fdf index 7fecbaa..0d7b709 100644 --- a/Platform/Samsung/exynos7885/exynos7885.fdf +++ b/Platform/Samsung/exynos7885/exynos7885.fdf @@ -132,6 +132,9 @@ READ_LOCK_STATUS = TRUE INF Silicon/Samsung/ExynosPkg/Drivers/SimpleFbDxe/SimpleFbDxe.inf + INF Silicon/Samsung/ExynosPkg/Drivers/KeypadDxe/KeypadDxe.inf + INF Silicon/Samsung/ExynosPkg/Drivers/GenericKeypadDeviceDxe/GenericKeypadDeviceDxe.inf + # # USB Host Support # diff --git a/Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c b/Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c new file mode 100644 index 0000000..e5abbe4 --- /dev/null +++ b/Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.c @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + KEY_CONTEXT EfiKeyContext; + UINT32 PioBase; + UINT32 BankOffset; + UINT32 PinNum; +} KEY_CONTEXT_PRIVATE; + + +UINTN gBitmapScanCodes[BITMAP_NUM_WORDS(0x18)] = {0}; +UINTN gBitmapUnicodeChars[BITMAP_NUM_WORDS(0x7f)] = {0}; + + +EFI_KEY_DATA gKeyDataPowerDown = {.Key = { + .UnicodeChar = (CHAR16)'s', + }}; + +EFI_KEY_DATA gKeyDataPowerUp = {.Key = { + .UnicodeChar = (CHAR16)'e', + }}; + +EFI_KEY_DATA gKeyDataPowerLongpress = {.Key = { + .UnicodeChar = (CHAR16)' ', + }}; + + +#define MS2NS(ms) (((UINT64)(ms)) * 1000000ULL) + +STATIC inline VOID +KeySetState(UINT16 ScanCode, CHAR16 UnicodeChar, BOOLEAN Value) +{ + if (ScanCode && ScanCode < 0x18) { + if (Value) + BitmapSet(gBitmapScanCodes, ScanCode); + else + BitmapClear(gBitmapScanCodes, ScanCode); + } + + if (UnicodeChar && UnicodeChar < 0x7f) { + if (Value) + BitmapSet(gBitmapUnicodeChars, ScanCode); + else + BitmapClear(gBitmapUnicodeChars, ScanCode); + } +} + +STATIC inline BOOLEAN KeyGetState(UINT16 ScanCode, CHAR16 UnicodeChar) +{ + if (ScanCode && ScanCode < 0x18) { + if (!BitmapTest(gBitmapScanCodes, ScanCode)) + return FALSE; + } + + if (UnicodeChar && UnicodeChar < 0x7f) { + if (!BitmapTest(gBitmapUnicodeChars, ScanCode)) + return FALSE; + } + + return TRUE; +} + +STATIC inline VOID LibKeyInitializeKeyContext(KEY_CONTEXT *Context) +{ + SetMem(&Context->KeyData, 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; + } +} + + +STATIC KEY_CONTEXT_PRIVATE KeyContextPower; +STATIC KEY_CONTEXT_PRIVATE KeyContextVolumeUp; +STATIC KEY_CONTEXT_PRIVATE KeyContextVolumeDown; + +STATIC KEY_CONTEXT_PRIVATE *KeyList[] = { &KeyContextVolumeDown, &KeyContextVolumeUp, &KeyContextPower }; + +STATIC +VOID KeypadInitializeKeyContextPrivate(KEY_CONTEXT_PRIVATE *Context) +{ + Context->PioBase = 0; + Context->BankOffset = 0; + Context->PinNum = 0; +} + +STATIC +KEY_CONTEXT_PRIVATE *KeypadKeyCodeToKeyContext(UINT32 KeyCode) +{ + if (KeyCode == 114) + return &KeyContextVolumeDown; + else if (KeyCode == 115) + return &KeyContextVolumeUp; + else if (KeyCode == 116) + return &KeyContextPower; + else + return NULL; +} + +RETURN_STATUS +EFIAPI +KeypadDeviceImplConstructor(VOID) +{ + UINTN Index; + KEY_CONTEXT_PRIVATE *StaticContext; + + // Reset all keys + for (Index = 0; Index < (sizeof(KeyList) / sizeof(KeyList[0])); Index++) { + KeypadInitializeKeyContextPrivate(KeyList[Index]); + } + + // Configure keys + + // vol down (gpa1-6) + StaticContext = KeypadKeyCodeToKeyContext(114); + StaticContext->PioBase = 0x11CB0000; + StaticContext->BankOffset = 0x60; + StaticContext->PinNum = 6; + + // vol up (gpa1-5) + StaticContext = KeypadKeyCodeToKeyContext(115); + StaticContext->PioBase = 0x11CB0000; + StaticContext->BankOffset = 0x60; + StaticContext->PinNum = 5; + + // power (gpa1-7) + StaticContext = KeypadKeyCodeToKeyContext(116); + StaticContext->PioBase = 0x11CB0000; + StaticContext->BankOffset = 0x60; + StaticContext->PinNum = 7; + + return RETURN_SUCCESS; +} + +EFI_STATUS EFIAPI KeypadDeviceImplReset(KEYPAD_DEVICE_PROTOCOL *This) +{ + LibKeyInitializeKeyContext(&KeyContextVolumeDown.EfiKeyContext); + KeyContextVolumeDown.EfiKeyContext.KeyData.Key.ScanCode = SCAN_DOWN; + + LibKeyInitializeKeyContext(&KeyContextVolumeUp.EfiKeyContext); + KeyContextVolumeUp.EfiKeyContext.KeyData.Key.ScanCode = SCAN_UP; + + LibKeyInitializeKeyContext(&KeyContextPower.EfiKeyContext); + KeyContextPower.EfiKeyContext.KeyData.Key.UnicodeChar = CHAR_CARRIAGE_RETURN; + + 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->PioBase + 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/Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf b/Silicon/Samsung/Exynos7885Pkg/Library/KeypadDeviceImplLib/KeypadDeviceImplLib.inf new file mode 100644 index 0000000..5d77f14 --- /dev/null +++ b/Silicon/Samsung/Exynos7885Pkg/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 + Silicon/Samsung/Exynos7885Pkg/exynos7885.dec + +[LibraryClasses] + TimerLib + diff --git a/Silicon/Samsung/Exynos7885Pkg/Library/PlatformMemoryMapLib/PlatformMemoryMapLib.c b/Silicon/Samsung/Exynos7885Pkg/Library/PlatformMemoryMapLib/PlatformMemoryMapLib.c index c504fdf..e64a3e4 100644 --- a/Silicon/Samsung/Exynos7885Pkg/Library/PlatformMemoryMapLib/PlatformMemoryMapLib.c +++ b/Silicon/Samsung/Exynos7885Pkg/Library/PlatformMemoryMapLib/PlatformMemoryMapLib.c @@ -5,7 +5,7 @@ static ARM_MEMORY_REGION_DESCRIPTOR_EX gDeviceMemoryDescriptorEx[] = { /* EFI_RESOURCE_ EFI_RESOURCE_ATTRIBUTE_ EFI_MEMORY_TYPE ARM_REGION_ATTRIBUTE_ MemLabel(32 Char.), MemBase, MemSize, BuildHob, ResourceType, ResourceAttribute, MemoryType, CacheAttributes --------------------- Register ---------------------*/ - {"Periphs", 0x00000000, 0x15000000, AddMem, MEM_RES, UNCACHEABLE, RtCode, NS_DEVICE}, + {"Periphs", 0x00000000, 0x80000000, AddMem, MEM_RES, UNCACHEABLE, RtCode, NS_DEVICE}, //--------------------- DDR --------------------- */ diff --git a/Silicon/Samsung/ExynosPkg/Include/Protocol/KeypadDevice.h b/Silicon/Samsung/ExynosPkg/Include/Protocol/KeypadDevice.h index a21d811..8e223a1 100644 --- a/Silicon/Samsung/ExynosPkg/Include/Protocol/KeypadDevice.h +++ b/Silicon/Samsung/ExynosPkg/Include/Protocol/KeypadDevice.h @@ -31,7 +31,7 @@ struct _KEYPAD_DEVICE_PROTOCOL { KEYPAD_GET_KEYS GetKeys; }; -extern EFI_GUID gMediaTekKeypadDeviceProtocolGuid; +extern EFI_GUID gExynosKeypadDeviceProtocolGuid; #endif