From d54c9f9cc884c7d9d3c4bf926871131a63a47e56 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 18 Apr 2021 18:35:36 -0400 Subject: [PATCH] hiddbg: hdls 12.0.0 support, closes #542. --- nx/include/switch/services/hiddbg.h | 46 +++++++++++++--- nx/source/services/hiddbg.c | 83 ++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/hiddbg.h b/nx/include/switch/services/hiddbg.h index 658c13f1..38e74903 100644 --- a/nx/include/switch/services/hiddbg.h +++ b/nx/include/switch/services/hiddbg.h @@ -15,6 +15,12 @@ typedef enum { HiddbgNpadButton_Capture = BIT(19), ///< Capture button } HiddbgNpadButton; +/// HdlsAttribute +typedef enum { + HiddbgHdlsAttribute_HasVirtualSixAxisSensorAcceleration = BIT(0), ///< HasVirtualSixAxisSensorAcceleration + HiddbgHdlsAttribute_HasVirtualSixAxisSensorAngle = BIT(1), ///< HasVirtualSixAxisSensorAngle +} HiddbgHdlsAttribute; + /// State for overriding \ref HidDebugPadState. typedef struct { u32 attributes; ///< Bitfield of \ref HidDebugPadAttribute. @@ -79,18 +85,32 @@ typedef struct { u32 buttons; ///< See \ref HiddbgNpadButton. HidAnalogStickState analog_stick_l; ///< AnalogStickL HidAnalogStickState analog_stick_r; ///< AnalogStickR - u8 unk_x20; ///< Unused for input. Set with output from \ref hiddbgDumpHdlsStates. Not set by \ref hiddbgGetAbstractedPadsState. + u8 indicator; ///< Indicator. Unused for input. Set with output from \ref hiddbgDumpHdlsStates. Not set by \ref hiddbgGetAbstractedPadsState. u8 padding[0x3]; ///< Padding } HiddbgHdlsStateV7; -/// HdlsState, for [9.0.0+]. Converted to/from \ref HiddbgHdlsStateV7 on prior sysvers. +/// HdlsState, for [9.0.0-11.0.1]. typedef struct { u32 battery_level; ///< BatteryLevel for the main PowerInfo, see \ref HidPowerInfo. u32 flags; ///< Used to set the main PowerInfo for \ref HidNpadSystemProperties. BIT(0) -> IsPowered, BIT(1) -> IsCharging. u64 buttons; ///< See \ref HiddbgNpadButton. [9.0.0+] Masked with 0xfffffffff00fffff. HidAnalogStickState analog_stick_l; ///< AnalogStickL HidAnalogStickState analog_stick_r; ///< AnalogStickR - u8 unk_x20; ///< Unused for input. Set with output from \ref hiddbgDumpHdlsStates. + u8 indicator; ///< Indicator. Unused for input. Set with output from \ref hiddbgDumpHdlsStates. + u8 padding[0x3]; ///< Padding +} HiddbgHdlsStateV9; + +/// HdlsState, for [12.0.0+]. +typedef struct { + u32 battery_level; ///< BatteryLevel for the main PowerInfo, see \ref HidPowerInfo. + u32 flags; ///< Used to set the main PowerInfo for \ref HidNpadSystemProperties. BIT(0) -> IsPowered, BIT(1) -> IsCharging. + u64 buttons; ///< See \ref HiddbgNpadButton. [9.0.0+] Masked with 0xfffffffff00fffff. + HidAnalogStickState analog_stick_l; ///< AnalogStickL + HidAnalogStickState analog_stick_r; ///< AnalogStickR + HidVector six_axis_sensor_acceleration; ///< VirtualSixAxisSensorAcceleration + HidVector six_axis_sensor_angle; ///< VirtualSixAxisSensorAngle + u32 attribute; ///< Bitfield of \ref HiddbgHdlsAttribute. + u8 indicator; ///< Indicator. Unused for input. u8 padding[0x3]; ///< Padding } HiddbgHdlsState; @@ -115,7 +135,7 @@ typedef struct { typedef struct { HiddbgHdlsHandle handle; ///< \ref HiddbgHdlsHandle HiddbgHdlsDeviceInfoV7 device; ///< \ref HiddbgHdlsDeviceInfoV7. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. - HiddbgHdlsStateV7 state; ///< \ref HiddbgHdlsState + HiddbgHdlsStateV7 state; ///< \ref HiddbgHdlsStateV7 } HiddbgHdlsStateListEntryV7; /// HdlsStateListV7, for [7.0.0-8.1.0]. This contains a list of all controllers, including non-virtual controllers. @@ -125,14 +145,28 @@ typedef struct { HiddbgHdlsStateListEntryV7 entries[0x10]; ///< \ref HiddbgHdlsStateListEntryV7 } HiddbgHdlsStateListV7; -/// HdlsStateListEntry, for [9.0.0+]. Converted to/from \ref HiddbgHdlsStateListEntryV7 on prior sysvers. +/// HdlsStateListEntry, for [9.0.0-11.0.1]. +typedef struct { + HiddbgHdlsHandle handle; ///< \ref HiddbgHdlsHandle + HiddbgHdlsDeviceInfo device; ///< \ref HiddbgHdlsDeviceInfo. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. + alignas(8) HiddbgHdlsStateV9 state; ///< \ref HiddbgHdlsStateV9 +} HiddbgHdlsStateListEntryV9; + +/// HdlsStateList, for [9.0.0-11.0.1]. +typedef struct { + s32 total_entries; ///< Total entries for the below entries. + u32 pad; ///< Padding + HiddbgHdlsStateListEntryV9 entries[0x10]; ///< \ref HiddbgHdlsStateListEntryV9 +} HiddbgHdlsStateListV9; + +/// HdlsStateListEntry, for [12.0.0+]. typedef struct { HiddbgHdlsHandle handle; ///< \ref HiddbgHdlsHandle HiddbgHdlsDeviceInfo device; ///< \ref HiddbgHdlsDeviceInfo. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. alignas(8) HiddbgHdlsState state; ///< \ref HiddbgHdlsState } HiddbgHdlsStateListEntry; -/// HdlsStateList, for [9.0.0+]. Converted to/from \ref HiddbgHdlsStateListV7 on prior sysvers. +/// HdlsStateList, for [12.0.0+]. /// This contains a list of all controllers, including non-virtual controllers. typedef struct { s32 total_entries; ///< Total entries for the below entries. diff --git a/nx/source/services/hiddbg.c b/nx/source/services/hiddbg.c index 3281666d..4df53700 100644 --- a/nx/source/services/hiddbg.c +++ b/nx/source/services/hiddbg.c @@ -361,7 +361,18 @@ static void _hiddbgConvertHiddbgHdlsStateToV7(HiddbgHdlsStateV7 *out, const Hidd out->buttons = in->buttons; memcpy(&out->analog_stick_l, &in->analog_stick_l, sizeof(in->analog_stick_l)); memcpy(&out->analog_stick_r, &in->analog_stick_r, sizeof(in->analog_stick_r)); - out->unk_x20 = in->unk_x20; + out->indicator = in->indicator; +} + +static void _hiddbgConvertHiddbgHdlsStateToV9(HiddbgHdlsStateV9 *out, const HiddbgHdlsState *in) { + memset(out, 0, sizeof(*out)); + + out->battery_level = in->battery_level; + out->flags = in->flags; + out->buttons = in->buttons; + memcpy(&out->analog_stick_l, &in->analog_stick_l, sizeof(in->analog_stick_l)); + memcpy(&out->analog_stick_r, &in->analog_stick_r, sizeof(in->analog_stick_r)); + out->indicator = in->indicator; } static void _hiddbgConvertHiddbgHdlsStateFromV7(HiddbgHdlsState *out, const HiddbgHdlsStateV7 *in) { @@ -372,7 +383,18 @@ static void _hiddbgConvertHiddbgHdlsStateFromV7(HiddbgHdlsState *out, const Hidd out->buttons = in->buttons; memcpy(&out->analog_stick_l, &in->analog_stick_l, sizeof(in->analog_stick_l)); memcpy(&out->analog_stick_r, &in->analog_stick_r, sizeof(in->analog_stick_r)); - out->unk_x20 = in->unk_x20; + out->indicator = in->indicator; +} + +static void _hiddbgConvertHiddbgHdlsStateFromV9(HiddbgHdlsState *out, const HiddbgHdlsStateV9 *in) { + memset(out, 0, sizeof(*out)); + + out->battery_level = in->battery_level; + out->flags = in->flags; + out->buttons = in->buttons; + memcpy(&out->analog_stick_l, &in->analog_stick_l, sizeof(in->analog_stick_l)); + memcpy(&out->analog_stick_r, &in->analog_stick_r, sizeof(in->analog_stick_r)); + out->indicator = in->indicator; } static void _hiddbgConvertHdlsStateListToV7(HiddbgHdlsStateListV7 *out, const HiddbgHdlsStateList *in) { @@ -388,6 +410,19 @@ static void _hiddbgConvertHdlsStateListToV7(HiddbgHdlsStateListV7 *out, const Hi } } +static void _hiddbgConvertHdlsStateListToV9(HiddbgHdlsStateListV9 *out, const HiddbgHdlsStateList *in) { + s32 count; + memset(out, 0, sizeof(*out)); + out->total_entries = in->total_entries; + count = out->total_entries > 0x10 ? 0x10 : out->total_entries; + + for (s32 i=0; ientries[i].handle = in->entries[i].handle; + memcpy(&out->entries[i].device, &in->entries[i].device, sizeof(in->entries[i].device)); + _hiddbgConvertHiddbgHdlsStateToV9(&out->entries[i].state, &in->entries[i].state); + } +} + static void _hiddbgConvertHdlsStateListFromV7(HiddbgHdlsStateList *out, const HiddbgHdlsStateListV7 *in) { s32 count; memset(out, 0, sizeof(*out)); @@ -401,6 +436,19 @@ static void _hiddbgConvertHdlsStateListFromV7(HiddbgHdlsStateList *out, const Hi } } +static void _hiddbgConvertHdlsStateListFromV9(HiddbgHdlsStateList *out, const HiddbgHdlsStateListV9 *in) { + s32 count; + memset(out, 0, sizeof(*out)); + out->total_entries = in->total_entries; + count = out->total_entries > 0x10 ? 0x10 : out->total_entries; + + for (s32 i=0; ientries[i].handle = in->entries[i].handle; + memcpy(&out->entries[i].device, &in->entries[i].device, sizeof(in->entries[i].device)); + _hiddbgConvertHiddbgHdlsStateFromV9(&out->entries[i].state, &in->entries[i].state); + } +} + static Result _hiddbgAttachHdlsWorkBuffer(TransferMemory *tmem) { return _hiddbgCmdInTmemNoOut(tmem, 324); } @@ -462,6 +510,15 @@ Result hiddbgIsHdlsVirtualDeviceAttached(HiddbgHdlsHandle handle, bool *out) { } } } + else if (hosversionBefore(12,0,0)) { + HiddbgHdlsStateListV9 *stateList = (HiddbgHdlsStateListV9*)(g_hiddbgHdlsTmem.src_addr); + for (s32 i=0; itotal_entries; i++) { + if (stateList->entries[i].handle.handle == handle.handle) { + *out = true; + break; + } + } + } else { HiddbgHdlsStateList *stateList = (HiddbgHdlsStateList*)(g_hiddbgHdlsTmem.src_addr); for (s32 i=0; itotal_entries; i++) { @@ -507,6 +564,11 @@ Result hiddbgDumpHdlsStates(HiddbgHdlsStateList *state) { memcpy(&statev7, g_hiddbgHdlsTmem.src_addr, sizeof(statev7)); _hiddbgConvertHdlsStateListFromV7(state, &statev7); } + else if (hosversionBefore(12,0,0)) { + HiddbgHdlsStateListV9 statev9; + memcpy(&statev9, g_hiddbgHdlsTmem.src_addr, sizeof(statev9)); + _hiddbgConvertHdlsStateListFromV9(state, &statev9); + } else memcpy(state, g_hiddbgHdlsTmem.src_addr, sizeof(*state)); } @@ -542,6 +604,11 @@ Result hiddbgApplyHdlsStateList(const HiddbgHdlsStateList *state) { _hiddbgConvertHdlsStateListToV7(&statev7, state); memcpy(g_hiddbgHdlsTmem.src_addr, &statev7, sizeof(statev7)); } + else if (hosversionBefore(12,0,0)) { + HiddbgHdlsStateListV9 statev9; + _hiddbgConvertHdlsStateListToV9(&statev9, state); + memcpy(g_hiddbgHdlsTmem.src_addr, &statev9, sizeof(statev9)); + } else memcpy(g_hiddbgHdlsTmem.src_addr, state, sizeof(*state)); @@ -592,6 +659,16 @@ static Result _hiddbgSetHdlsStateV7(HiddbgHdlsHandle handle, const HiddbgHdlsSta return serviceDispatchIn(&g_hiddbgSrv, 332, in); } +static Result _hiddbgSetHdlsStateV9(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) { + struct { + HiddbgHdlsStateV9 state; + HiddbgHdlsHandle handle; + } in = { .handle = handle }; + _hiddbgConvertHiddbgHdlsStateToV9(&in.state, state); + + return serviceDispatchIn(&g_hiddbgSrv, 332, in); +} + static Result _hiddbgSetHdlsState(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) { const struct { HiddbgHdlsHandle handle; @@ -610,6 +687,8 @@ Result hiddbgSetHdlsState(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) if (hosversionBefore(9,0,0)) return _hiddbgSetHdlsStateV7(handle, state); + else if (hosversionBefore(12,0,0)) + return _hiddbgSetHdlsStateV9(handle, state); else return _hiddbgSetHdlsState(handle, state); }