From a3933c7a8536fac828542b429cba228083877cbd Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 6 Mar 2018 18:08:57 -0500 Subject: [PATCH] Added hid vibration. --- nx/include/switch/services/hid.h | 10 +++ nx/source/services/hid.c | 130 +++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/nx/include/switch/services/hid.h b/nx/include/switch/services/hid.h index c675bb16..0450afa1 100644 --- a/nx/include/switch/services/hid.h +++ b/nx/include/switch/services/hid.h @@ -539,6 +539,12 @@ typedef struct HidSharedMemory } HidSharedMemory; static_assert(sizeof(HidSharedMemory) == 0x40000, "Hid Shared Memory structure has incorrect size"); +typedef struct HidVibrationValue +{ + float values[4]; +} HidVibrationValue; +static_assert(sizeof(HidVibrationValue) == 0x10, "Hid VibrationValue structure has incorrect size"); + Result hidInitialize(void); void hidExit(void); void hidReset(void); @@ -580,3 +586,7 @@ Result hidSetNpadJoyAssignmentModeSingleByDefault(HidControllerID id); /// When used, both joy-cons in a pair should be used with this (CONTROLLER_PLAYER_1 and CONTROLLER_PLAYER_2 for example). /// id must be CONTROLLER_PLAYER_*. Result hidSetNpadJoyAssignmentModeDual(HidControllerID id); + +Result hidInitializeVibrationDevice(u32 *VibrationDeviceHandle, HidControllerID id, HidControllerLayoutType type); + +Result hidSendVibrationValue(u32 *VibrationDeviceHandle, HidVibrationValue *VibrationValue); diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index fb7d2b38..993deac5 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -540,3 +540,133 @@ Result hidSetNpadJoyAssignmentModeDual(HidControllerID id) { return rc; } +static Result _hidCreateActiveVibrationDeviceList(Service* srv_out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 203; + + Result rc = serviceIpcDispatch(&g_hidSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(srv_out, r.Handles[0]); + } + } + + return rc; +} + +static Result _hidActivateVibrationDevice(Service* srv, u32 VibrationDeviceHandle) { + 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 = 0; + raw->VibrationDeviceHandle = VibrationDeviceHandle; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result hidSendVibrationValue(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; + HidVibrationValue VibrationValue; + u64 AppletResourceUserId; + } *raw; + + ipcSendPid(&c); + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 201; + raw->VibrationDeviceHandle = *VibrationDeviceHandle; + raw->AppletResourceUserId = AppletResourceUserId; + memcpy(&raw->VibrationValue, VibrationValue, sizeof(HidVibrationValue)); + + rc = serviceIpcDispatch(&g_hidSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result hidInitializeVibrationDevice(u32 *VibrationDeviceHandle, HidControllerID id, HidControllerLayoutType type) { + Result rc=0; + Service srv; + + //TODO: Is type correct? + *VibrationDeviceHandle = (type & 0xff) | (id & 0xff)<<8; + + rc = _hidCreateActiveVibrationDeviceList(&srv); + if (R_FAILED(rc)) + return rc; + + rc = _hidActivateVibrationDevice(&srv, *VibrationDeviceHandle); + serviceClose(&srv); + return rc; +} +