From c9326f6bce1f47fde3ab3db22a4a6e531dc2513b Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Wed, 13 May 2020 22:09:55 +0100 Subject: [PATCH] hid: add hidWaitForAnyEvent, allow user to override irrst usage check (#454) --- libctru/include/3ds/services/hid.h | 8 ++++ libctru/include/3ds/services/irrst.h | 3 ++ libctru/source/services/hid.c | 60 +++++++++++++++++++++------- libctru/source/services/irrst.c | 5 ++- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/libctru/include/3ds/services/hid.h b/libctru/include/3ds/services/hid.h index f06da12..62a71f2 100644 --- a/libctru/include/3ds/services/hid.h +++ b/libctru/include/3ds/services/hid.h @@ -146,6 +146,14 @@ void hidGyroRead(angularRate* rate); */ void hidWaitForEvent(HID_Event id, bool nextEvent); +/** + * @brief Waits for any HID or IRRST event. + * @param nextEvents Whether to discard the current events and wait for the next events. + * @param cancelEvent Optional additional handle to wait on, otherwise 0. + * @param timeout Timeout. + */ +Result hidWaitForAnyEvent(bool nextEvents, Handle cancelEvent, s64 timeout); + /// Compatibility macro for hidScanInput. #define scanKeys hidScanInput /// Compatibility macro for hidKeysHeld. diff --git a/libctru/include/3ds/services/irrst.h b/libctru/include/3ds/services/irrst.h index 5cfb3ba..e643801 100644 --- a/libctru/include/3ds/services/irrst.h +++ b/libctru/include/3ds/services/irrst.h @@ -14,6 +14,9 @@ extern Handle irrstMemHandle; /// IRRST's shared memory. extern vu32* irrstSharedMem; +/// IRRST's state update event +extern Handle irrstEvent; + /// Initializes IRRST. Result irrstInit(void); diff --git a/libctru/source/services/hid.c b/libctru/source/services/hid.c index f371df5..79fb501 100644 --- a/libctru/source/services/hid.c +++ b/libctru/source/services/hid.c @@ -29,9 +29,16 @@ static angularRate gRate; static int hidRefCount; +static bool usingIrrst; + +bool __attribute__((weak)) hidShouldUseIrrst(void) +{ + bool val; + return R_SUCCEEDED(APT_CheckNew3DS(&val)) && val; +} + Result hidInit(void) { - bool val=false; Result ret=0; if (AtomicPostIncrement(&hidRefCount)) return 0; @@ -52,17 +59,12 @@ Result hidInit(void) goto cleanup1; } - if(R_FAILED(ret=svcMapMemoryBlock(hidMemHandle, (u32)hidSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2; + if(R_FAILED(ret=svcMapMemoryBlock(hidMemHandle, (u32)hidSharedMem, MEMPERM_READ, MEMPERM_DONTCARE)))goto cleanup2; - APT_CheckNew3DS(&val); - - if(val) - { + usingIrrst = hidShouldUseIrrst(); + if(usingIrrst) ret = irrstInit(); - } - // Reset internal state. - kOld = kHeld = kDown = kUp = 0; return ret; cleanup2: @@ -83,19 +85,17 @@ void hidExit(void) { if (AtomicDecrement(&hidRefCount)) return; + // Reset internal state. + kOld = kHeld = kDown = kUp = 0; + // Unmap HID sharedmem and close handles. - bool val=false; int i; for(i=0; i<5; i++)svcCloseHandle(hidEvents[i]); svcUnmapMemoryBlock(hidMemHandle, (u32)hidSharedMem); svcCloseHandle(hidMemHandle); svcCloseHandle(hidHandle); - APT_CheckNew3DS(&val); - - if(val) - { + if(usingIrrst) irrstExit(); - } if(hidSharedMem != NULL) { @@ -115,6 +115,36 @@ void hidWaitForEvent(HID_Event id, bool nextEvent) svcClearEvent(hidEvents[id]); } +Result hidWaitForAnyEvent(bool nextEvents, Handle cancelEvent, s64 timeout) +{ + Handle events[HIDEVENT_MAX + 2]; + u32 numEvents = HIDEVENT_MAX + (irrstEvent != 0 ? 1 : 0) + (cancelEvent ? 1 : 0); + + if (nextEvents) + { + for (u32 i = 0; i < HIDEVENT_MAX; i++) + svcClearEvent(hidEvents[i]); + svcClearEvent(irrstEvent); + } + + memcpy(events, hidEvents, sizeof(hidEvents)); + events[HIDEVENT_MAX] = irrstEvent; + events[HIDEVENT_MAX + 1] = cancelEvent; + + s32 idx; + Result res = svcWaitSynchronizationN(&idx, events, numEvents, false, timeout); + + if (res == 0 && !nextEvents) + { + // No timeout & next event + for (u32 i = 0; i < HIDEVENT_MAX; i++) + svcClearEvent(hidEvents[i]); + svcClearEvent(irrstEvent); + } + + return res; +} + u32 hidCheckSectionUpdateTime(vu32 *sharedmem_section, u32 id) { s64 tick0=0, tick1=0; diff --git a/libctru/source/services/irrst.c b/libctru/source/services/irrst.c index 9e09797..6ea6e83 100644 --- a/libctru/source/services/irrst.c +++ b/libctru/source/services/irrst.c @@ -48,8 +48,6 @@ Result irrstInit(void) if(R_FAILED(ret = svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000))) goto cleanup2; - // Reset internal state. - kHeld = 0; return 0; cleanup2: @@ -70,6 +68,9 @@ void irrstExit(void) { if (AtomicDecrement(&irrstRefCount)) return; + // Reset internal state. + kHeld = 0; + svcCloseHandle(irrstEvent); // Unmap ir:rst sharedmem and close handles. svcUnmapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem);