diff --git a/nx/include/switch/services/hid.h b/nx/include/switch/services/hid.h index b0018a4b..9515c54c 100644 --- a/nx/include/switch/services/hid.h +++ b/nx/include/switch/services/hid.h @@ -489,6 +489,26 @@ static_assert(sizeof(HIDSharedMemory) == 0x40000, "HID Shared Memory structure h Result hidInitialize(void); void hidExit(void); +void hidReset(void); Handle hidGetSessionService(void); void* hidGetSharedmemAddr(void); + +void hidSetControllerLayout(HIDControllerID id, HIDControllerLayoutType layoutType); +void hidScanInput(void); + +u64 hidKeysHeld(HIDControllerID id); +u64 hidKeysDown(HIDControllerID id); +u64 hidKeysUp(HIDControllerID id); + +u64 hidMouseButtonsHeld(void); +u64 hidMouseButtonsDown(void); +u64 hidMouseButtonsUp(void); + +bool hidKeyboardModifierHeld(HIDKeyboardModifier modifier); +bool hidKeyboardModifierDown(HIDKeyboardModifier modifier); +bool hidKeyboardModifierUp(HIDKeyboardModifier modifier); + +bool hidKeyboardHeld(HIDKeyboardScancode key); +bool hidKeyboardDown(HIDKeyboardScancode key); +bool hidKeyboardUp(HIDKeyboardScancode key); diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 1fa86ffb..8c4f961b 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -5,6 +5,19 @@ static Handle g_hidServiceSession = INVALID_HANDLE; static Handle g_hidIAppletResource = INVALID_HANDLE; static SharedMemory g_hidSharedmem; +static HIDTouchScreenEntry touchEntry; +static HIDMouseEntry mouseEntry; +static HIDKeyboardEntry keyboardEntry; +static HIDControllerInputEntry controllerEntries[10]; + +static u64 mouseOld, mouseHeld, mouseDown, mouseUp; +static u64 keyboardModOld, keyboardModHeld, keyboardModDown, keyboardModUp; +static u32 keyboardOld[8], keyboardHeld[8], keyboardDown[8], keyboardUp[8]; +static u64 controllerOld[10], controllerHeld[10], controllerDown[10], controllerUp[10]; + +static HIDControllerLayoutType controllerLayout[10]; +static u64 touchTimestamp, mouseTimestamp, keyboardTimestamp, controllerTimestamps[10]; + static Result _hidCreateAppletResource(Handle sessionhandle, Handle* handle_out, u64 AppletResourceUserId); static Result _hidGetSharedMemoryHandle(Handle sessionhandle, Handle* handle_out); @@ -41,6 +54,8 @@ Result hidInitialize(void) { g_hidIAppletResource = INVALID_HANDLE; } + hidReset(); + return rc; } @@ -61,6 +76,29 @@ void hidExit(void) shmemClose(&g_hidSharedmem); } +void hidReset(void) +{ + // Reset internal state + memset(&touchEntry, 0, sizeof(HIDTouchScreenEntry)); + memset(&mouseEntry, 0, sizeof(HIDMouseEntry)); + memset(&keyboardEntry, 0, sizeof(HIDKeyboardEntry)); + memset(&controllerEntries, 0, sizeof(HIDControllerInputEntry)); + + mouseOld = mouseHeld = mouseDown = mouseUp = 0; + keyboardModOld = keyboardModHeld = keyboardModDown = keyboardModUp = 0; + for (int i = 0; i < 8; i++) + keyboardOld[i] = keyboardHeld[i] = keyboardDown[i] = keyboardUp[i] = 0; + for (int i = 0; i < 10; i++) + controllerOld[i] = controllerHeld[i] = controllerDown[i] = controllerUp[i] = 0; + + for (int i = 0; i < 10; i++) + controllerLayout[i] = LAYOUT_DEFAULT; + + touchTimestamp = mouseTimestamp = keyboardTimestamp = 0; + for (int i = 0; i < 10; i++) + controllerTimestamps[i] = 0; +} + Handle hidGetSessionService(void) { return g_hidServiceSession; } @@ -69,6 +107,149 @@ void* hidGetSharedmemAddr(void) { return shmemGetAddr(&g_hidSharedmem); } +void hidSetControllerLayout(HIDControllerID id, HIDControllerLayoutType layoutType) +{ + controllerLayout[id] = layoutType; +} + +void hidScanInput(void) +{ + if (g_hidServiceSession == INVALID_HANDLE) return; + HIDSharedMemory *sharedMem = (HIDSharedMemory*)hidGetSharedmemAddr(); + + mouseOld = mouseHeld; + keyboardModOld = keyboardModHeld; + memcpy(keyboardOld, keyboardHeld, sizeof(keyboardOld)); + memcpy(controllerOld, controllerHeld, sizeof(controllerOld)); + + mouseHeld = 0; + keyboardModHeld = 0; + memset(keyboardHeld, 0, sizeof(keyboardHeld)); + memset(controllerHeld, 0, sizeof(controllerHeld)); + memset(&touchEntry, 0, sizeof(HIDTouchScreenEntry)); + memset(&mouseEntry, 0, sizeof(HIDMouseEntry)); + memset(&keyboardEntry, 0, sizeof(HIDKeyboardEntry)); + for (int i = 0; i < 10; i++) + memset(&controllerEntries[i], 0, sizeof(HIDControllerInputEntry)); + + u64 latestTouchEntry = sharedMem->touchscreen.header.latestEntry; + HIDTouchScreenEntry *newTouchEntry = &sharedMem->touchscreen.entries[latestTouchEntry]; + if (newTouchEntry->header.timestamp - touchTimestamp) { + memcpy(&touchEntry, newTouchEntry, sizeof(HIDTouchScreenEntry)); + touchTimestamp = newTouchEntry->header.timestamp; + } + + u64 latestMouseEntry = sharedMem->mouse.header.latestEntry; + HIDMouseEntry *newMouseEntry = &sharedMem->mouse.entries[latestMouseEntry]; + if (newMouseEntry->timestamp - mouseTimestamp) { + memcpy(&mouseEntry, newMouseEntry, sizeof(HIDMouseEntry)); + mouseTimestamp = newMouseEntry->timestamp; + + mouseHeld = mouseEntry.buttons; + } + mouseDown = (~mouseOld) & mouseHeld; + mouseUp = mouseOld & (~mouseHeld); + + u64 latestKeyboardEntry = sharedMem->keyboard.header.latestEntry; + HIDKeyboardEntry *newKeyboardEntry = &sharedMem->keyboard.entries[latestKeyboardEntry]; + if (newKeyboardEntry->timestamp - keyboardTimestamp) { + memcpy(&keyboardEntry, newKeyboardEntry, sizeof(HIDKeyboardEntry)); + keyboardTimestamp = newKeyboardEntry->timestamp; + + keyboardModHeld = keyboardEntry.modifier; + for (int i = 0; i < 8; i++) { + keyboardHeld[i] = keyboardEntry.keys[i]; + } + } + keyboardModDown = (~keyboardModOld) & keyboardModHeld; + keyboardModUp = keyboardModOld & (~keyboardModHeld); + for (int i = 0; i < 8; i++) { + keyboardDown[i] = (~keyboardOld[i]) & keyboardHeld[i]; + keyboardUp[i] = keyboardOld[i] & (~keyboardHeld[i]); + } + + for (int i = 0; i < 10; i++) { + HIDControllerLayout *currentLayout = &sharedMem->controllers[i].layouts[controllerLayout[i]]; + u64 latestControllerEntry = currentLayout->header.latestEntry; + HIDControllerInputEntry *newInputEntry = ¤tLayout->entries[latestControllerEntry]; + if (newInputEntry->timestamp - controllerTimestamps[i]) { + memcpy(&controllerEntries[i], newInputEntry, sizeof(HIDControllerInputEntry)); + controllerTimestamps[i] = newInputEntry->timestamp; + + controllerHeld[i] = controllerEntries[i].buttons; + } + + controllerDown[i] = (~controllerOld[i]) & controllerHeld[i]; + controllerUp[i] = controllerOld[i] & (~controllerHeld[i]); + } +} + +u64 hidKeysHeld(HIDControllerID id) +{ + if (id < 0 || id > 9) return 0; + + return controllerHeld[id]; +} + +u64 hidKeysDown(HIDControllerID id) +{ + if (id < 0 || id > 9) return 0; + + return controllerDown[id]; +} + +u64 hidKeysUp(HIDControllerID id) +{ + if (id < 0 || id > 9) return 0; + + return controllerUp[id]; +} + +u64 hidMouseButtonsHeld(void) +{ + return mouseHeld; +} + +u64 hidMouseButtonsDown(void) +{ + return mouseDown; +} + +u64 hidMouseButtonsUp(void) +{ + return mouseUp; +} + +bool hidKeyboardModifierHeld(HIDKeyboardModifier modifier) +{ + return keyboardModHeld & modifier; +} + +bool hidKeyboardModifierDown(HIDKeyboardModifier modifier) +{ + return keyboardModDown & modifier; +} + +bool hidKeyboardModifierUp(HIDKeyboardModifier modifier) +{ + return keyboardModUp & modifier; +} + +bool hidKeyboardHeld(HIDKeyboardScancode key) +{ + return keyboardHeld[key / 32] & (1 << (key % 32)); +} + +bool hidKeyboardDown(HIDKeyboardScancode key) +{ + return keyboardDown[key / 32] & (1 << (key % 32)); +} + +bool hidKeyboardUp(HIDKeyboardScancode key) +{ + return keyboardUp[key / 32] & (1 << (key % 32)); +} + static Result _hidCreateAppletResource(Handle sessionhandle, Handle* handle_out, u64 AppletResourceUserId) { IpcCommand c; ipcInitialize(&c);