#define NX_SERVICE_ASSUME_NON_DOMAIN #include "service_guard.h" #include #include "kernel/tmem.h" #include "services/hiddbg.h" #include "runtime/hosversion.h" static Service g_hiddbgSrv; static bool g_hiddbgHdlsInitialized; static TransferMemory g_hiddbgHdlsTmem; static void* g_hiddbgHdlsWorkmem; static const u32 g_hiddbgDeviceTypeInternalTable[] = { BIT(20), // DeviceType 0 Invalid BIT(0*4+2), // DeviceType 1 JoyRight BIT(0*4+1), // DeviceType 2 JoyLeft BIT(1*4+0), // DeviceType 3 FullKey BIT(1*4+1), // DeviceType 4 JoyLeft BIT(1*4+2), // DeviceType 5 JoyRight BIT(8), // DeviceType 6 FullKey BIT(11), // DeviceType 7 LarkLeft (HVC) BIT(12), // DeviceType 8 LarkRight (HVC) BIT(13), // DeviceType 9 LarkLeft (NES) BIT(14), // DeviceType 10 LarkRight (NES) BIT(15), // DeviceType 11 Invalid BIT(16), // DeviceType 12 Palma (Invalid for DeviceTypeInternal) BIT(9), // DeviceType 13 FullKey BIT(20), // DeviceType 14 Invalid BIT(10), // DeviceType 15 FullKey BIT(18), // DeviceType 16 Invalid BIT(19), // DeviceType 17 Invalid BIT(20), // DeviceType 18 Invalid BIT(21), // DeviceType 19 ::HidDeviceTypeBits_System with HidControllerType |= TYPE_PROCONTROLLER. BIT(22), // DeviceType 20 ::HidDeviceTypeBits_System with HidControllerType |= TYPE_JOYCON_PAIR. BIT(23), // DeviceType 21 ::HidDeviceType System with HidControllerType |= TYPE_JOYCON_PAIR. }; NX_GENERATE_SERVICE_GUARD(hiddbg); Result _hiddbgInitialize(void) { return smGetService(&g_hiddbgSrv, "hid:dbg"); } void _hiddbgCleanup(void) { serviceClose(&g_hiddbgSrv); } Service* hiddbgGetServiceSession(void) { return &g_hiddbgSrv; } static Result _hiddbgCmdNoIO(u32 cmd_id) { return serviceDispatch(&g_hiddbgSrv, cmd_id); } static Result _hiddbgCmdInU8NoOut(u8 inval, u32 cmd_id) { return serviceDispatchIn(&g_hiddbgSrv, cmd_id, inval); } static Result _hiddbgCmdInBoolNoOut(bool inval, u32 cmd_id) { return _hiddbgCmdInU8NoOut(inval!=0, cmd_id); } static Result _hiddbgCmdInU64NoOut(u64 inval, u32 cmd_id) { return serviceDispatchIn(&g_hiddbgSrv, cmd_id, inval); } static Result _hiddbgCmdInHandle64NoOut(Handle handle, u64 inval, u32 cmd_id) { return serviceDispatchIn(&g_hiddbgSrv, cmd_id, inval, .in_num_handles = 1, .in_handles = { handle }, ); } static Result _hiddbgCmdInHandle64OutU64(Handle handle, u64 inval, u64 *out, u32 cmd_id) { return serviceDispatchInOut(&g_hiddbgSrv, cmd_id, inval, *out, .in_num_handles = 1, .in_handles = { handle }, ); } static Result _hiddbgCmdInTmemNoOut(TransferMemory *tmem, u32 cmd_id) { return _hiddbgCmdInHandle64NoOut(tmem->handle, tmem->size, cmd_id); } static Result _hiddbgCmdInTmemOutU64(TransferMemory *tmem, u64 *out, u32 cmd_id) { return _hiddbgCmdInHandle64OutU64(tmem->handle, tmem->size, out, cmd_id); } Result hiddbgSetDebugPadAutoPilotState(const HiddbgDebugPadAutoPilotState *state) { return serviceDispatchIn(&g_hiddbgSrv, 1, *state); } Result hiddbgUnsetDebugPadAutoPilotState(void) { return _hiddbgCmdNoIO(2); } Result hiddbgSetTouchScreenAutoPilotState(const HidTouchState *states, s32 count) { return serviceDispatch(&g_hiddbgSrv, 11, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { states, count*sizeof(HidTouchState) } }, ); } Result hiddbgUnsetTouchScreenAutoPilotState(void) { return _hiddbgCmdNoIO(12); } Result hiddbgSetMouseAutoPilotState(const HiddbgMouseAutoPilotState *state) { return serviceDispatchIn(&g_hiddbgSrv, 21, *state); } Result hiddbgUnsetMouseAutoPilotState(void) { return _hiddbgCmdNoIO(22); } Result hiddbgSetKeyboardAutoPilotState(const HiddbgKeyboardAutoPilotState *state) { return serviceDispatchIn(&g_hiddbgSrv, 31, *state); } Result hiddbgUnsetKeyboardAutoPilotState(void) { return _hiddbgCmdNoIO(32); } Result hiddbgDeactivateHomeButton(void) { return _hiddbgCmdNoIO(110); } Result hiddbgSetSleepButtonAutoPilotState(const HiddbgSleepButtonAutoPilotState *state) { return serviceDispatchIn(&g_hiddbgSrv, 121, *state); } Result hiddbgUnsetSleepButtonAutoPilotState(void) { return _hiddbgCmdNoIO(122); } Result hiddbgUpdateControllerColor(u32 colorBody, u32 colorButtons, HidsysUniquePadId unique_pad_id) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u32 colorBody; u32 colorButtons; HidsysUniquePadId unique_pad_id; } in = { colorBody, colorButtons, unique_pad_id }; return serviceDispatchIn(&g_hiddbgSrv, 221, in); } Result hiddbgUpdateDesignInfo(u32 colorBody, u32 colorButtons, u32 colorLeftGrip, u32 colorRightGrip, u8 inval, HidsysUniquePadId unique_pad_id) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u32 colorBody; u32 colorButtons; u32 colorLeftGrip; u32 colorRightGrip; u8 inval; u8 pad[7]; HidsysUniquePadId unique_pad_id; } in = { colorBody, colorButtons, colorLeftGrip, colorRightGrip, inval, {0}, unique_pad_id }; return serviceDispatchIn(&g_hiddbgSrv, 224, in); } Result hiddbgAcquireOperationEventHandle(Event* out_event, bool autoclear, HidsysUniquePadId unique_pad_id) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Handle tmp_handle = INVALID_HANDLE; Result rc = 0; rc = serviceDispatchIn(&g_hiddbgSrv, 228, unique_pad_id, .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, .out_handles = &tmp_handle, ); if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); return rc; } static Result _hiddbgReadSerialFlash(TransferMemory *tmem, u32 offset, u64 size, HidsysUniquePadId unique_pad_id) { const struct { u32 offset; u32 pad; u64 size; HidsysUniquePadId unique_pad_id; } in = { offset, 0, size, unique_pad_id }; return serviceDispatchIn(&g_hiddbgSrv, 229, in, .in_num_handles = 1, .in_handles = { tmem->handle }, ); } static Result _hiddbgWriteSerialFlash(TransferMemory *tmem, u32 offset, u64 tmem_size, u64 size, HidsysUniquePadId unique_pad_id) { const struct { u32 offset; u32 pad; u64 tmem_size; u64 size; HidsysUniquePadId unique_pad_id; } in = { offset, 0, tmem_size, size, unique_pad_id }; return serviceDispatchIn(&g_hiddbgSrv, 230, in, .in_num_handles = 1, .in_handles = { tmem->handle }, ); } // sdk-nso doesn't use hiddbgAcquireOperationEventHandle/hiddbgGetOperationResult in the *SerialFlash impl, those are used seperately by the user. [9.0.0+] sdk-nso no longer exposes *SerialFlash and related functionality. Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, HidsysUniquePadId unique_pad_id) { Result rc=0; Event tmpevent={0}; TransferMemory tmem; size_t sizealign = (size+0x1000) & ~0xfff; if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); rc = tmemCreate(&tmem, sizealign, Perm_Rw); if (R_FAILED(rc)) return rc; rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, unique_pad_id); // *Must* be used before _hiddbgReadSerialFlash. if (R_SUCCEEDED(rc)) rc = _hiddbgReadSerialFlash(&tmem, offset, size, unique_pad_id); if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, UINT64_MAX); if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(unique_pad_id); if (R_SUCCEEDED(rc)) memcpy(buffer, tmem.src_addr, size); eventClose(&tmpevent); tmemClose(&tmem); return rc; } Result hiddbgWriteSerialFlash(u32 offset, void* buffer, size_t tmem_size, size_t size, HidsysUniquePadId unique_pad_id) { Result rc=0; Event tmpevent={0}; TransferMemory tmem; if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); rc = tmemCreateFromMemory(&tmem, buffer, tmem_size, Perm_R); if (R_FAILED(rc)) return rc; rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, unique_pad_id); // *Must* be used before _hiddbgWriteSerialFlash. if (R_SUCCEEDED(rc)) rc = _hiddbgWriteSerialFlash(&tmem, offset, tmem_size, size, unique_pad_id); if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, UINT64_MAX); if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(unique_pad_id); eventClose(&tmpevent); tmemClose(&tmem); return rc; } Result hiddbgGetOperationResult(HidsysUniquePadId unique_pad_id) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hiddbgCmdInU64NoOut(unique_pad_id.id, 231); } Result hiddbgGetUniquePadDeviceTypeSetInternal(HidsysUniquePadId unique_pad_id, u32 *out) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 tmp=0; Result rc = serviceDispatchInOut(&g_hiddbgSrv, 234, unique_pad_id, tmp); if (R_SUCCEEDED(rc) && out) { // Pre-9.0.0 output is an u32, with [9.0.0+] it's an u8. if (hosversionBefore(9,0,0)) *out = tmp; else *out = tmp & 0xFF; } return rc; } Result hiddbgGetAbstractedPadHandles(HiddbgAbstractedPadHandle *handles, s32 count, s32 *total_out) { if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchOut(&g_hiddbgSrv, 301, *total_out, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, .buffers = { { handles, count*sizeof(HiddbgAbstractedPadHandle) } }, ); } Result hiddbgGetAbstractedPadState(HiddbgAbstractedPadHandle handle, HiddbgAbstractedPadState *state) { if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchInOut(&g_hiddbgSrv, 302, handle, *state); } Result hiddbgGetAbstractedPadsState(HiddbgAbstractedPadHandle *handles, HiddbgAbstractedPadState *states, s32 count, s32 *total_out) { if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchOut(&g_hiddbgSrv, 303, *total_out, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out, SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out, }, .buffers = { { handles, count*sizeof(HiddbgAbstractedPadHandle) }, { states, count*sizeof(HiddbgAbstractedPadState) }, }, ); } Result hiddbgSetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId, const HiddbgAbstractedPadState *state) { if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { s8 AbstractedVirtualPadId; u8 pad[7]; HiddbgAbstractedPadState state; } in = { AbstractedVirtualPadId, {0}, *state }; return serviceDispatchIn(&g_hiddbgSrv, 321, in); } Result hiddbgUnsetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId) { if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hiddbgCmdInU8NoOut(AbstractedVirtualPadId, 322); } Result hiddbgUnsetAllAutoPilotVirtualPadState(void) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hiddbgCmdNoIO(323); } static u32 _hiddbgConvertDeviceTypeToDeviceTypeInternal(u8 deviceType) { if (deviceType >= sizeof(g_hiddbgDeviceTypeInternalTable)/sizeof(u32)) return g_hiddbgDeviceTypeInternalTable[0]; return g_hiddbgDeviceTypeInternalTable[deviceType]; } static u8 _hiddbgConvertDeviceTypeInternalToDeviceType(u32 deviceType) { for (u32 i=0; ideviceTypeInternal = _hiddbgConvertDeviceTypeToDeviceTypeInternal(in->deviceType); out->singleColorBody = in->singleColorBody; out->singleColorButtons = in->singleColorButtons; out->npadInterfaceType = in->npadInterfaceType; } static void _hiddbgConvertHdlsDeviceInfoFromV7(HiddbgHdlsDeviceInfo *out, const HiddbgHdlsDeviceInfoV7 *in) { memset(out, 0, sizeof(*out)); out->deviceType = _hiddbgConvertDeviceTypeInternalToDeviceType(in->deviceTypeInternal); out->npadInterfaceType = in->npadInterfaceType; out->singleColorBody = in->singleColorBody; out->singleColorButtons = in->singleColorButtons; //Leave color*Grip at zero since V7 doesn't have those. } static void _hiddbgConvertHiddbgHdlsStateToV7(HiddbgHdlsStateV7 *out, const HiddbgHdlsState *in) { memset(out, 0, sizeof(*out)); out->is_powered = (in->flags & BIT(0)) != 0; out->flags = (in->flags & BIT(1)) != 0; out->battery_level = in->battery_level; 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 _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) { memset(out, 0, sizeof(*out)); out->battery_level = in->battery_level; out->flags = (in->is_powered & 1) | ((in->flags & 1)<<1); 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 _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) { 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; _hiddbgConvertHdlsDeviceInfoToV7(&out->entries[i].device, &in->entries[i].device); _hiddbgConvertHiddbgHdlsStateToV7(&out->entries[i].state, &in->entries[i].state); } } 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)); 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; _hiddbgConvertHdlsDeviceInfoFromV7(&out->entries[i].device, &in->entries[i].device); _hiddbgConvertHiddbgHdlsStateFromV7(&out->entries[i].state, &in->entries[i].state); } } 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(HiddbgHdlsSessionId *session_id, TransferMemory *tmem) { if (hosversionBefore(13,0,0)) return _hiddbgCmdInTmemNoOut(tmem, 324); else return _hiddbgCmdInTmemOutU64(tmem, &session_id->id, 324); } Result hiddbgAttachHdlsWorkBuffer(HiddbgHdlsSessionId *session_id, void *buffer, size_t size) { Result rc=0; if (session_id) session_id->id = 0; if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); rc = tmemCreateFromMemory(&g_hiddbgHdlsTmem, buffer, size, Perm_Rw); if (R_FAILED(rc)) return rc; rc = _hiddbgAttachHdlsWorkBuffer(session_id, &g_hiddbgHdlsTmem); if (R_FAILED(rc)) tmemClose(&g_hiddbgHdlsTmem); if (R_SUCCEEDED(rc)) { g_hiddbgHdlsInitialized = true; g_hiddbgHdlsWorkmem = buffer; } return rc; } Result hiddbgReleaseHdlsWorkBuffer(HiddbgHdlsSessionId session_id) { Result rc=0; if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); g_hiddbgHdlsInitialized = false; if (hosversionBefore(13,0,0)) rc = _hiddbgCmdNoIO(325); else rc = _hiddbgCmdInU64NoOut(session_id.id, 325); tmemClose(&g_hiddbgHdlsTmem); g_hiddbgHdlsWorkmem = NULL; return rc; } Result hiddbgIsHdlsVirtualDeviceAttached(HiddbgHdlsSessionId session_id, HiddbgHdlsHandle handle, bool *out) { Result rc = 0; if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(13,0,0)) rc = _hiddbgCmdNoIO(327); else rc = _hiddbgCmdInU64NoOut(session_id.id, 327); if (R_FAILED(rc)) return rc; if (out) { *out = false; if (hosversionBefore(9,0,0)) { HiddbgHdlsStateListV7 *stateList = (HiddbgHdlsStateListV7*)g_hiddbgHdlsWorkmem; for (s32 i=0; itotal_entries; i++) { if (stateList->entries[i].handle.handle == handle.handle) { *out = true; break; } } } else if (hosversionBefore(12,0,0)) { HiddbgHdlsStateListV9 *stateList = (HiddbgHdlsStateListV9*)g_hiddbgHdlsWorkmem; for (s32 i=0; itotal_entries; i++) { if (stateList->entries[i].handle.handle == handle.handle) { *out = true; break; } } } else { HiddbgHdlsStateList *stateList = (HiddbgHdlsStateList*)g_hiddbgHdlsWorkmem; for (s32 i=0; itotal_entries; i++) { if (stateList->entries[i].handle.handle == handle.handle) { *out = true; break; } } } } return rc; } Result hiddbgDumpHdlsNpadAssignmentState(HiddbgHdlsSessionId session_id, HiddbgHdlsNpadAssignment *state) { Result rc=0; if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(13,0,0)) rc = _hiddbgCmdNoIO(326); else rc = _hiddbgCmdInU64NoOut(session_id.id, 326); if (R_FAILED(rc)) return rc; if (state) memcpy(state, g_hiddbgHdlsWorkmem, sizeof(*state)); return rc; } Result hiddbgDumpHdlsStates(HiddbgHdlsSessionId session_id, HiddbgHdlsStateList *state) { Result rc=0; if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(13,0,0)) rc = _hiddbgCmdNoIO(327); else rc = _hiddbgCmdInU64NoOut(session_id.id, 327); if (R_FAILED(rc)) return rc; if (state) { if (hosversionBefore(9,0,0)) { HiddbgHdlsStateListV7 statev7; memcpy(&statev7, g_hiddbgHdlsWorkmem, sizeof(statev7)); _hiddbgConvertHdlsStateListFromV7(state, &statev7); } else if (hosversionBefore(12,0,0)) { HiddbgHdlsStateListV9 statev9; memcpy(&statev9, g_hiddbgHdlsWorkmem, sizeof(statev9)); _hiddbgConvertHdlsStateListFromV9(state, &statev9); } else memcpy(state, g_hiddbgHdlsWorkmem, sizeof(*state)); } return rc; } Result hiddbgApplyHdlsNpadAssignmentState(HiddbgHdlsSessionId session_id, const HiddbgHdlsNpadAssignment *state, bool flag) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (state==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); memcpy(g_hiddbgHdlsWorkmem, state, sizeof(*state)); if (hosversionBefore(13,0,0)) return _hiddbgCmdInBoolNoOut(flag, 328); else { const struct { u8 flag; u8 pad[7]; HiddbgHdlsSessionId session_id; } in = { flag, {0}, session_id }; return serviceDispatchIn(&g_hiddbgSrv, 328, in); } } Result hiddbgApplyHdlsStateList(HiddbgHdlsSessionId session_id, const HiddbgHdlsStateList *state) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (state==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (hosversionBefore(9,0,0)) { HiddbgHdlsStateListV7 statev7; _hiddbgConvertHdlsStateListToV7(&statev7, state); memcpy(g_hiddbgHdlsWorkmem, &statev7, sizeof(statev7)); } else if (hosversionBefore(12,0,0)) { HiddbgHdlsStateListV9 statev9; _hiddbgConvertHdlsStateListToV9(&statev9, state); memcpy(g_hiddbgHdlsWorkmem, &statev9, sizeof(statev9)); } else memcpy(g_hiddbgHdlsWorkmem, state, sizeof(*state)); if (hosversionBefore(13,0,0)) return _hiddbgCmdNoIO(329); else return _hiddbgCmdInU64NoOut(session_id.id, 329); } static Result _hiddbgAttachHdlsVirtualDeviceV7(HiddbgHdlsHandle *handle, const HiddbgHdlsDeviceInfoV7 *info) { return serviceDispatchInOut(&g_hiddbgSrv, 330, *info, *handle); } static Result _hiddbgAttachHdlsVirtualDevice(HiddbgHdlsHandle *handle, const HiddbgHdlsDeviceInfo *info) { return serviceDispatchInOut(&g_hiddbgSrv, 330, *info, *handle); } Result hiddbgAttachHdlsVirtualDevice(HiddbgHdlsHandle *handle, const HiddbgHdlsDeviceInfo *info) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(9,0,0)) { HiddbgHdlsDeviceInfoV7 infov7; _hiddbgConvertHdlsDeviceInfoToV7(&infov7, info); return _hiddbgAttachHdlsVirtualDeviceV7(handle, &infov7); } else return _hiddbgAttachHdlsVirtualDevice(handle, info); } Result hiddbgDetachHdlsVirtualDevice(HiddbgHdlsHandle handle) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return _hiddbgCmdInU64NoOut(handle.handle, 331); } static Result _hiddbgSetHdlsStateV7(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) { struct { HiddbgHdlsStateV7 state; HiddbgHdlsHandle handle; } in = { .handle = handle }; _hiddbgConvertHiddbgHdlsStateToV7(&in.state, state); return serviceDispatchIn(&g_hiddbgSrv, 332, in); } static Result _hiddbgSetHdlsStateV9(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) { struct { HiddbgHdlsHandle handle; HiddbgHdlsStateV9 state; } 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; HiddbgHdlsState state; } in = { handle, *state }; return serviceDispatchIn(&g_hiddbgSrv, 332, in); } Result hiddbgSetHdlsState(HiddbgHdlsHandle handle, const HiddbgHdlsState *state) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(9,0,0)) return _hiddbgSetHdlsStateV7(handle, state); else if (hosversionBefore(12,0,0)) return _hiddbgSetHdlsStateV9(handle, state); else return _hiddbgSetHdlsState(handle, state); }