diff --git a/nx/include/switch/services/hid.h b/nx/include/switch/services/hid.h index 254fc580..69bbdc32 100644 --- a/nx/include/switch/services/hid.h +++ b/nx/include/switch/services/hid.h @@ -555,14 +555,49 @@ typedef struct HidControllerSixAxisLayout HidControllerSixAxisEntry entries[17]; } HidControllerSixAxisLayout; +/// Controller flags. +typedef struct { + u32 powerInfo : 6; ///< Use \ref hidGetControllerPowerInfo instead of accessing this directly. + + u32 bit6 : 1; ///< Unused + u32 bit7 : 1; ///< Unused + u32 bit8 : 1; ///< Unused + u32 unsupportedButtonPressed_NpadSystem : 1; ///< Unsupported button pressed with controller NpadSystem. + u32 unsupportedButtonPressed_NpadSystemExt : 1; ///< Unsupported button pressed with controller NpadSystemExt. + + u32 abxyButtonOriented : 1; + u32 slSrButtonOriented : 1; + u32 plusButtonCapability : 1; ///< [4.0.0+] + u32 minusButtonCapability : 1; ///< [4.0.0+] + u32 directionalButtonsSupported : 1; ///< [8.0.0+] + + u32 unused; + + u32 unintendedHomeButtonInputProtectionDisabled : 1; +} HidFlags; + +typedef struct { + u32 deviceType; + u32 pad; + HidFlags flags; + u32 batteryCharge[3]; + u8 unk_1[0x20]; + HidControllerMAC macLeft; + HidControllerMAC macRight; +} HidControllerMisc; + +typedef struct { + bool powerConnected; + bool isCharging; + u32 batteryCharge; ///< Battery charge, always 0-4. +} HidPowerInfo; + typedef struct HidController { HidControllerHeader header; HidControllerLayout layouts[7]; HidControllerSixAxisLayout sixaxis[6]; - u8 unk_1[0x40]; - HidControllerMAC macLeft; - HidControllerMAC macRight; + HidControllerMisc misc; u8 unk_2[0xDF8]; } HidController; @@ -628,6 +663,15 @@ HidControllerType hidGetControllerType(HidControllerID id); void hidGetControllerColors(HidControllerID id, HidControllerColors *colors); bool hidIsControllerConnected(HidControllerID id); +/// Gets the DeviceType for the specified controller. +u32 hidGetControllerDeviceType(HidControllerID id); + +/// Gets the flags for the specified controller. +void hidGetControllerFlags(HidControllerID id, HidFlags *flags); + +/// Gets the \ref HidPowerInfo for the specified controller. info is the output array, where total_info is the number of entries. total_info must be 1 or 2: former for the main battery info, latter for reading left/right Joy-Con PowerInfo. +void hidGetControllerPowerInfo(HidControllerID id, HidPowerInfo *info, size_t total_info); + void hidScanInput(void); u64 hidKeysHeld(HidControllerID id); diff --git a/nx/include/switch/services/hiddbg.h b/nx/include/switch/services/hiddbg.h index f914de4b..3a23c409 100644 --- a/nx/include/switch/services/hiddbg.h +++ b/nx/include/switch/services/hiddbg.h @@ -8,34 +8,43 @@ #include "../services/hid.h" #include "../services/sm.h" -/// HdlsNpadAssignment -typedef struct { - u8 unk_x0[0x208]; ///< Unknown -} HiddbgHdlsNpadAssignment; - -/// HdlsStateList -typedef struct { - u8 unk_x0[0x408]; ///< Unknown -} HiddbgHdlsStateList; - /// HdlsDeviceInfo typedef struct { u32 type; ///< See \ref HidControllerType, only one bit can be set. u32 singleColorBody; ///< RGBA Single Body Color u32 singleColorButtons; ///< RGBA Single Buttons Color u8 unk_xc; ///< Unknown - u8 pad[0x3]; + u8 pad[0x3]; ///< Padding } HiddbgHdlsDeviceInfo; /// HdlsState typedef struct { u8 unk_x0[0x8]; ///< Unknown - u32 unk_x8; ///< Unknown, written to HidController +0x419C. + u32 batteryCharge; ///< batteryCharge for the main PowerInfo, see \ref HidPowerInfo. u32 buttons; ///< See \ref HidControllerKeys. JoystickPosition joysticks[JOYSTICK_NUM_STICKS]; ///< \ref JoystickPosition u32 unused; ///< Unused } HiddbgHdlsState; +/// HdlsNpadAssignment +typedef struct { + u8 unk_x0[0x208]; ///< Unknown +} HiddbgHdlsNpadAssignment; + +/// HdlsStateListEntry +typedef struct { + u64 HdlsHandle; ///< HdlsHandle + HiddbgHdlsDeviceInfo device; ///< \ref HiddbgHdlsDeviceInfo. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. + HiddbgHdlsState state; ///< \ref HiddbgHdlsState +} HiddbgHdlsStateListEntry; + +/// HdlsStateList. This contains a list of all controllers, including non-virtual controllers. +typedef struct { + s32 total_entries; ///< Total entries for the below entries. + u32 pad; ///< Padding + HiddbgHdlsStateListEntry entries[0x10]; ///< \ref HiddbgHdlsStateListEntry +} HiddbgHdlsStateList; + Result hiddbgInitialize(void); void hiddbgExit(void); @@ -55,6 +64,7 @@ Result hiddbgDumpHdlsStates(HiddbgHdlsStateList *state); Result hiddbgApplyHdlsNpadAssignmentState(const HiddbgHdlsNpadAssignment *state, bool flag); /// Sets state for \ref HiddbgHdlsStateList. Only available with [7.0.0+]. +/// The HiddbgHdlsState will be applied for each HdlsHandle. If a HdlsHandle is not found, code similar to \ref hiddbgAttachHdlsVirtualDevice will run with the \ref HiddbgHdlsDeviceInfo, then it will continue with applying state with the new device. Result hiddbgApplyHdlsStateList(const HiddbgHdlsStateList *state); /// Attach a device with the input info, where the output handle is written to HdlsHandle. Only available with [7.0.0+]. diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 05d73fa9..c6620dd4 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -25,6 +25,7 @@ static HidKeyboardEntry g_keyboardEntry; static HidControllerHeader g_controllerHeaders[10]; static HidControllerInputEntry g_controllerEntries[10]; static HidControllerSixAxisLayout g_sixaxisLayouts[10]; +static HidControllerMisc g_controllerMisc[10]; static u64 g_mouseOld, g_mouseHeld, g_mouseDown, g_mouseUp; static u64 g_keyboardModOld, g_keyboardModHeld, g_keyboardModDown, g_keyboardModUp; @@ -142,6 +143,7 @@ void hidReset(void) memset(&g_keyboardEntry, 0, sizeof(HidKeyboardEntry)); memset(g_controllerHeaders, 0, sizeof(g_controllerHeaders)); memset(g_controllerEntries, 0, sizeof(g_controllerEntries)); + memset(g_controllerMisc, 0, sizeof(g_controllerMisc)); memset(g_sixaxisLayouts, 0, sizeof(g_sixaxisLayouts)); memset(g_sixaxisEnabled, 0, sizeof(g_sixaxisEnabled)); @@ -209,6 +211,7 @@ void hidScanInput(void) { memset(&g_mouse, 0, sizeof(HidMouse)); memset(&g_keyboardEntry, 0, sizeof(HidKeyboardEntry)); memset(g_controllerEntries, 0, sizeof(g_controllerEntries)); + memset(g_controllerMisc, 0, sizeof(g_controllerMisc)); memset(g_sixaxisLayouts, 0, sizeof(g_sixaxisLayouts)); u64 latestTouchEntry = sharedMem->touchscreen.header.latestEntry; @@ -266,6 +269,8 @@ void hidScanInput(void) { g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i]; g_controllerUp[i] = g_controllerOld[i] & (~g_controllerHeld[i]); + memcpy(&g_controllerMisc[i], &sharedMem->controllers[i].misc, sizeof(HidControllerMisc)); + if (g_sixaxisEnabled[i]) { u32 type = g_controllerHeaders[i].type; HidControllerSixAxisLayout *sixaxis = NULL; @@ -356,6 +361,57 @@ bool hidIsControllerConnected(HidControllerID id) { return flag; } +u32 hidGetControllerDeviceType(HidControllerID id) { + if (id==CONTROLLER_P1_AUTO) + return hidGetControllerDeviceType(g_controllerP1AutoID); + if (id < 0 || id > 9) return 0; + + rwlockReadLock(&g_hidLock); + u32 type = g_controllerMisc[id].deviceType; + rwlockReadUnlock(&g_hidLock); + return type; +} + +void hidGetControllerFlags(HidControllerID id, HidFlags *flags) { + if (id==CONTROLLER_P1_AUTO) { + hidGetControllerFlags(g_controllerP1AutoID, flags); + return; + } + if (id < 0 || id > 9) return; + + rwlockReadLock(&g_hidLock); + *flags = g_controllerMisc[id].flags; + rwlockReadUnlock(&g_hidLock); +} + +void hidGetControllerPowerInfo(HidControllerID id, HidPowerInfo *info, size_t total_info) { + size_t i; + size_t indexbase; + HidFlags flags; + + if (id==CONTROLLER_P1_AUTO) { + hidGetControllerPowerInfo(g_controllerP1AutoID, info, total_info); + return; + } + if (id < 0 || id > 9) return; + + if (total_info == 0) return; + if (total_info > 2) total_info = 2; + indexbase = total_info-1; + + hidGetControllerFlags(id, &flags); + + for (i=0; i 4) info->batteryCharge = 4; + } +} + u64 hidKeysHeld(HidControllerID id) { if (id==CONTROLLER_P1_AUTO) return hidKeysHeld(g_controllerP1AutoID); if (id < 0 || id > 9) return 0;