diff --git a/nx/include/switch/services/hid.h b/nx/include/switch/services/hid.h index 29a3124e..8221d448 100644 --- a/nx/include/switch/services/hid.h +++ b/nx/include/switch/services/hid.h @@ -539,6 +539,13 @@ typedef struct HidSharedMemory } HidSharedMemory; static_assert(sizeof(HidSharedMemory) == 0x40000, "Hid Shared Memory structure has incorrect size"); +typedef struct HidVibrationDeviceInfo +{ + u32 unk_x0; + u32 unk_x4; ///< 0x1 for left-joycon, 0x2 for right-joycon. +} HidVibrationDeviceInfo; +static_assert(sizeof(HidVibrationDeviceInfo) == 0x8, "Hid VibrationDeviceInfo structure has incorrect size"); + typedef struct HidVibrationValue { float amp_low; ///< Low Band amplitude. 1.0f: Max amplitude. @@ -597,9 +604,15 @@ Result hidSetNpadJoyAssignmentModeDual(HidControllerID id); Result hidInitializeVibrationDevices(u32 *VibrationDeviceHandles, size_t total_handles, HidControllerID id, HidControllerType type); +/// Gets HidVibrationDeviceInfo for the specified VibrationDeviceHandle. +Result hidGetVibrationDeviceInfo(u32 *VibrationDeviceHandle, HidVibrationDeviceInfo *VibrationDeviceInfo); + /// Send the VibrationValue to the specified VibrationDeviceHandle. Result hidSendVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *VibrationValue); +/// Gets the current HidVibrationValue for the specified VibrationDeviceHandle. +Result hidGetActualVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *VibrationValue); + /// Sets whether vibration is allowed, this also affects the config displayed by System Settings. Result hidPermitVibration(bool flag); diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 81dda643..6765533d 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -616,6 +616,44 @@ static Result _hidActivateVibrationDevice(Service* srv, u32 VibrationDeviceHandl return rc; } +Result hidGetVibrationDeviceInfo(u32 *VibrationDeviceHandle, HidVibrationDeviceInfo *VibrationDeviceInfo) { + Result rc; + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 VibrationDeviceHandle; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 200; + raw->VibrationDeviceHandle = *VibrationDeviceHandle; + + rc = serviceIpcDispatch(&g_hidSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + HidVibrationDeviceInfo VibrationDeviceInfo; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && VibrationDeviceInfo) memcpy(VibrationDeviceInfo, &resp->VibrationDeviceInfo, sizeof(HidVibrationDeviceInfo)); + } + + return rc; +} + Result hidSendVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *VibrationValue) { Result rc; u64 AppletResourceUserId; @@ -662,6 +700,53 @@ Result hidSendVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *Vibr return rc; } +Result hidGetActualVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *VibrationValue) { + Result rc; + u64 AppletResourceUserId; + + rc = appletGetAppletResourceUserId(&AppletResourceUserId); + if (R_FAILED(rc)) + return rc; + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 VibrationDeviceHandle; + u64 AppletResourceUserId; + } *raw; + + ipcSendPid(&c); + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 202; + raw->VibrationDeviceHandle = *VibrationDeviceHandle; + raw->AppletResourceUserId = AppletResourceUserId; + + rc = serviceIpcDispatch(&g_hidSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + HidVibrationValue VibrationValue; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && VibrationValue) memcpy(VibrationValue, &resp->VibrationValue, sizeof(HidVibrationValue)); + } + + return rc; +} + Result hidPermitVibration(bool flag) { IpcCommand c; ipcInitialize(&c);