#define NX_SERVICE_ASSUME_NON_DOMAIN #include "service_guard.h" #include #include #include #include #include "kernel/shmem.h" #include "kernel/mutex.h" #include "kernel/rwlock.h" #include "services/applet.h" #include "services/hid.h" #include "runtime/hosversion.h" #include "runtime/diag.h" static Service g_hidSrv; static Service g_hidIAppletResource; static Service g_hidIActiveVibrationDeviceList; static SharedMemory g_hidSharedmem; static Mutex g_hidVibrationMutex; static u8* g_sevenSixAxisSensorBuffer; static TransferMemory g_sevenSixAxisSensorTmem0; static TransferMemory g_sevenSixAxisSensorTmem1; static bool g_scanInputInitialized; static RwLock g_hidLock; static HidTouchScreenState g_touchScreenState; static HidMouseState g_mouseState; static HidKeyboardState g_keyboardState; static HidNpadCommonState g_controllerEntries[10]; static u64 g_mouseOld, g_mouseHeld, g_mouseDown, g_mouseUp; static u64 g_keyboardModOld, g_keyboardModHeld, g_keyboardModDown, g_keyboardModUp; static u64 g_keyboardOld[4], g_keyboardHeld[4], g_keyboardDown[4], g_keyboardUp[4]; static u64 g_controllerOld[10], g_controllerHeld[10], g_controllerDown[10], g_controllerUp[10]; static HidControllerID g_controllerP1AutoID; static Result _hidCreateAppletResource(Service* srv, Service* srv_out); static Result _hidGetSharedMemoryHandle(Service* srv, Handle* handle_out); static Result _hidActivateTouchScreen(void); static Result _hidActivateMouse(void); static Result _hidActivateKeyboard(void); static Result _hidActivateNpad(void); static Result _hidActivateGesture(void); static Result _hidSetDualModeAll(void); static u8 _hidGetSixAxisSensorHandleNpadStyleIndex(HidSixAxisSensorHandle handle); NX_GENERATE_SERVICE_GUARD(hid); Result _hidInitialize(void) { Result rc=0; Handle sharedmem_handle; rc = smGetService(&g_hidSrv, "hid"); if (R_FAILED(rc)) return rc; rc = _hidCreateAppletResource(&g_hidSrv, &g_hidIAppletResource); if (R_SUCCEEDED(rc)) rc = _hidGetSharedMemoryHandle(&g_hidIAppletResource, &sharedmem_handle); if (R_SUCCEEDED(rc)) { shmemLoadRemote(&g_hidSharedmem, sharedmem_handle, 0x40000, Perm_R); rc = shmemMap(&g_hidSharedmem); } return rc; } void _hidCleanup(void) { if (g_sevenSixAxisSensorBuffer != NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); g_scanInputInitialized = false; serviceClose(&g_hidIActiveVibrationDeviceList); shmemClose(&g_hidSharedmem); serviceClose(&g_hidIAppletResource); serviceClose(&g_hidSrv); } static void _hidReset(void) { // Reset internal state memset(&g_touchScreenState, 0, sizeof(HidTouchScreenState)); memset(&g_mouseState, 0, sizeof(HidMouseState)); memset(&g_keyboardState, 0, sizeof(HidKeyboardState)); memset(g_controllerEntries, 0, sizeof(g_controllerEntries)); g_mouseOld = g_mouseHeld = g_mouseDown = g_mouseUp = 0; g_keyboardModOld = g_keyboardModHeld = g_keyboardModDown = g_keyboardModUp = 0; for (u32 i = 0; i < 4; i++) g_keyboardOld[i] = g_keyboardHeld[i] = g_keyboardDown[i] = g_keyboardUp[i] = 0; for (u32 i = 0; i < 10; i++) g_controllerOld[i] = g_controllerHeld[i] = g_controllerDown[i] = g_controllerUp[i] = 0; g_controllerP1AutoID = CONTROLLER_HANDHELD; } void hidReset(void) { rwlockWriteLock(&g_hidLock); _hidReset(); rwlockWriteUnlock(&g_hidLock); } Service* hidGetServiceSession(void) { return &g_hidSrv; } void* hidGetSharedmemAddr(void) { return shmemGetAddr(&g_hidSharedmem); } void hidScanInput(void) { rwlockWriteLock(&g_hidLock); if (!g_scanInputInitialized) { Result rc; hidInitializeNpad(); hidInitializeTouchScreen(); hidInitializeKeyboard(); hidInitializeMouse(); _hidReset(); rc = hidSetSupportedNpadStyleSet(HidNpadStyleSet_NpadStandard | HidNpadStyleTag_NpadSystemExt | HidNpadStyleTag_NpadSystem); if (R_FAILED(rc)) diagAbortWithResult(rc); static const HidNpadIdType idbuf[] = { HidNpadIdType_No1, HidNpadIdType_No2, HidNpadIdType_No3, HidNpadIdType_No4, HidNpadIdType_No5, HidNpadIdType_No6, HidNpadIdType_No7, HidNpadIdType_No8, HidNpadIdType_Handheld, }; rc = hidSetSupportedNpadIdType(idbuf, sizeof(idbuf)/sizeof(*idbuf)); if (R_FAILED(rc)) diagAbortWithResult(rc); rc = _hidSetDualModeAll(); if (R_FAILED(rc)) diagAbortWithResult(rc); rc = hidSetNpadJoyHoldType(HidNpadJoyHoldType_Vertical); if (R_FAILED(rc)) diagAbortWithResult(rc); g_scanInputInitialized = true; } g_mouseOld = g_mouseHeld; g_keyboardModOld = g_keyboardModHeld; memcpy(g_keyboardOld, g_keyboardHeld, sizeof(g_keyboardOld)); memcpy(g_controllerOld, g_controllerHeld, sizeof(g_controllerOld)); g_mouseHeld = 0; g_keyboardModHeld = 0; memset(g_keyboardHeld, 0, sizeof(g_keyboardHeld)); memset(g_controllerHeld, 0, sizeof(g_controllerHeld)); memset(&g_touchScreenState, 0, sizeof(HidTouchScreenState)); memset(&g_mouseState, 0, sizeof(HidMouseState)); memset(&g_keyboardState, 0, sizeof(HidKeyboardState)); memset(g_controllerEntries, 0, sizeof(g_controllerEntries)); if (hidGetTouchScreenStates(&g_touchScreenState, 1)) { if (g_touchScreenState.count >= 1) g_controllerHeld[CONTROLLER_HANDHELD] |= KEY_TOUCH; } if (hidGetMouseStates(&g_mouseState, 1)) { g_mouseHeld = g_mouseState.buttons; g_mouseDown = (~g_mouseOld) & g_mouseHeld; g_mouseUp = g_mouseOld & (~g_mouseHeld); } if (hidGetKeyboardStates(&g_keyboardState, 1)) { g_keyboardModHeld = g_keyboardState.modifiers; for (u32 i = 0; i < 4; i++) { g_keyboardHeld[i] = g_keyboardState.keys[i]; } g_keyboardModDown = (~g_keyboardModOld) & g_keyboardModHeld; g_keyboardModUp = g_keyboardModOld & (~g_keyboardModHeld); for (u32 i = 0; i < 4; i++) { g_keyboardDown[i] = (~g_keyboardOld[i]) & g_keyboardHeld[i]; g_keyboardUp[i] = g_keyboardOld[i] & (~g_keyboardHeld[i]); } } for (u32 i = 0; i < 10; i++) { HidNpadIdType id = hidControllerIDToNpadIdType(i); u32 style_set = hidGetNpadStyleSet(id); size_t total_out=0; if (style_set & HidNpadStyleTag_NpadFullKey) { HidNpadFullKeyState state={0}; total_out = hidGetNpadStatesFullKey(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadHandheld) { HidNpadHandheldState state={0}; total_out = hidGetNpadStatesHandheld(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadJoyDual) { HidNpadJoyDualState state={0}; total_out = hidGetNpadStatesJoyDual(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadJoyLeft) { HidNpadJoyLeftState state={0}; total_out = hidGetNpadStatesJoyLeft(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadJoyRight) { HidNpadJoyRightState state={0}; total_out = hidGetNpadStatesJoyRight(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadSystemExt) { HidNpadSystemExtState state={0}; total_out = hidGetNpadStatesSystemExt(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } else if (style_set & HidNpadStyleTag_NpadSystem) { HidNpadSystemState state={0}; total_out = hidGetNpadStatesSystem(id, &state, 1); if (total_out) { g_controllerHeld[i] |= state.buttons; memcpy(&g_controllerEntries[i], &state, sizeof(state)); } } g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i]; g_controllerUp[i] = g_controllerOld[i] & (~g_controllerHeld[i]); } g_controllerP1AutoID = CONTROLLER_HANDHELD; if (g_controllerEntries[CONTROLLER_PLAYER_1].attributes & HidNpadAttribute_IsConnected) g_controllerP1AutoID = CONTROLLER_PLAYER_1; rwlockWriteUnlock(&g_hidLock); } static HidNpadInternalState* _hidGetNpadInternalState(HidNpadIdType id) { HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr(); if (sharedmem == NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_NotInitialized)); if (id <= HidNpadIdType_No8) return &sharedmem->npad.entries[id].internal_state; else if (id == HidNpadIdType_Handheld) return &sharedmem->npad.entries[8].internal_state; else if (id == HidNpadIdType_Other) return &sharedmem->npad.entries[9].internal_state; else diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_BadInput)); } u32 hidGetNpadStyleSet(HidNpadIdType id) { return atomic_load_explicit(&_hidGetNpadInternalState(id)->style_set, memory_order_acquire); } HidNpadJoyAssignmentMode hidGetNpadJoyAssignment(HidNpadIdType id) { HidNpadInternalState *npad = _hidGetNpadInternalState(id); HidNpadJoyAssignmentMode tmp = atomic_load_explicit(&npad->joy_assignment_mode, memory_order_acquire); if (tmp != HidNpadJoyAssignmentMode_Dual && tmp != HidNpadJoyAssignmentMode_Single) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); return tmp; } Result hidGetNpadControllerColorSingle(HidNpadIdType id, HidNpadControllerColor *color) { Result rc = 0; HidNpadInternalState *npad = _hidGetNpadInternalState(id); HidColorAttribute attribute = npad->full_key_color.attribute; if (attribute==HidColorAttribute_NoController) rc = MAKERESULT(202, 604); else if (attribute==HidColorAttribute_ReadError) rc = MAKERESULT(202, 603); else if (attribute!=HidColorAttribute_Ok) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); if (R_SUCCEEDED(rc)) *color = npad->full_key_color.full_key; return rc; } Result hidGetNpadControllerColorSplit(HidNpadIdType id, HidNpadControllerColor *color_left, HidNpadControllerColor *color_right) { Result rc = 0; HidNpadInternalState *npad = _hidGetNpadInternalState(id); HidColorAttribute attribute = npad->joy_color.attribute; if (attribute==HidColorAttribute_NoController) rc = MAKERESULT(202, 604); else if (attribute==HidColorAttribute_ReadError) rc = MAKERESULT(202, 603); else if (attribute!=HidColorAttribute_Ok) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); if (R_SUCCEEDED(rc)) { *color_left = npad->joy_color.left; *color_right = npad->joy_color.right; } return rc; } u32 hidGetNpadDeviceType(HidNpadIdType id) { return atomic_load_explicit(&_hidGetNpadInternalState(id)->device_type, memory_order_acquire); } void hidGetNpadSystemProperties(HidNpadIdType id, HidNpadSystemProperties *out) { *out = atomic_load_explicit(&_hidGetNpadInternalState(id)->system_properties, memory_order_acquire); } void hidGetNpadSystemButtonProperties(HidNpadIdType id, HidNpadSystemButtonProperties *out) { *out = atomic_load_explicit(&_hidGetNpadInternalState(id)->system_button_properties, memory_order_acquire); } static void _hidGetNpadPowerInfo(HidNpadInternalState *npad, HidPowerInfo *info, u64 is_charging, u64 is_powered, u32 i) { *info = (HidPowerInfo){ .battery_level = atomic_load_explicit(&npad->battery_level[i], memory_order_acquire), .is_charging = (is_charging & BIT(i)) != 0, .is_powered = (is_powered & BIT(i)) != 0, }; if (info->battery_level > 4) info->battery_level = 4; // sdknso would Abort when this occurs. } void hidGetNpadPowerInfoSingle(HidNpadIdType id, HidPowerInfo *info) { HidNpadInternalState *npad = _hidGetNpadInternalState(id); HidNpadSystemProperties properties; properties = atomic_load_explicit(&npad->system_properties, memory_order_acquire); _hidGetNpadPowerInfo(npad, info, properties.is_charging, properties.is_powered, 0); } void hidGetNpadPowerInfoSplit(HidNpadIdType id, HidPowerInfo *info_left, HidPowerInfo *info_right) { HidNpadInternalState *npad = _hidGetNpadInternalState(id); HidNpadSystemProperties properties; properties = atomic_load_explicit(&npad->system_properties, memory_order_acquire); _hidGetNpadPowerInfo(npad, info_left, properties.is_charging, properties.is_powered, 1); _hidGetNpadPowerInfo(npad, info_right, properties.is_charging, properties.is_powered, 2); } u32 hidGetAppletFooterUiAttributesSet(HidNpadIdType id) { return atomic_load_explicit(&_hidGetNpadInternalState(id)->applet_footer_ui_attribute, memory_order_acquire); } HidAppletFooterUiType hidGetAppletFooterUiTypes(HidNpadIdType id) { return atomic_load_explicit(&_hidGetNpadInternalState(id)->applet_footer_ui_type, memory_order_acquire); } static size_t _hidGetStates(HidCommonLifoHeader *header, void* in_states, size_t max_states, size_t state_offset, size_t sampling_number_offset, void* states, size_t entrysize, size_t count) { s32 total_entries = (s32)atomic_load_explicit(&header->count, memory_order_acquire); if (total_entries < 0) total_entries = 0; if (total_entries > count) total_entries = count; s32 tail = (s32)atomic_load_explicit(&header->tail, memory_order_acquire); for (s32 i=0; i0 && *((u64*)((uintptr_t)out_state+sampling_number_offset)) - *((u64*)((uintptr_t)out_state_prev+sampling_number_offset)) != 1)) { s32 tmpcount = (s32)atomic_load_explicit(&header->count, memory_order_acquire); tmpcount = total_entries < tmpcount ? tmpcount : total_entries; total_entries = tmpcount < count ? tmpcount : count; tail = (s32)atomic_load_explicit(&header->tail, memory_order_acquire); i=-1; } } return total_entries; } void hidInitializeTouchScreen(void) { Result rc = _hidActivateTouchScreen(); if (R_FAILED(rc)) diagAbortWithResult(rc); } size_t hidGetTouchScreenStates(HidTouchScreenState *states, size_t count) { HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr(); if (sharedmem == NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_NotInitialized)); size_t total = _hidGetStates(&sharedmem->touchscreen.lifo.header, sharedmem->touchscreen.lifo.storage, 17, offsetof(HidTouchScreenStateAtomicStorage,state), offsetof(HidTouchScreenState,sampling_number), states, sizeof(HidTouchScreenState), count); size_t max_touches = sizeof(states[0].touches)/sizeof(states[0].touches[0]); for (size_t i=0; i max_touches) states[i].count = max_touches; } return total; } void hidInitializeMouse(void) { Result rc = _hidActivateMouse(); if (R_FAILED(rc)) diagAbortWithResult(rc); } size_t hidGetMouseStates(HidMouseState *states, size_t count) { HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr(); if (sharedmem == NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_NotInitialized)); size_t total = _hidGetStates(&sharedmem->mouse.lifo.header, sharedmem->mouse.lifo.storage, 17, offsetof(HidMouseStateAtomicStorage,state), offsetof(HidMouseState,sampling_number), states, sizeof(HidMouseState), count); return total; } void hidInitializeKeyboard(void) { Result rc = _hidActivateKeyboard(); if (R_FAILED(rc)) diagAbortWithResult(rc); } size_t hidGetKeyboardStates(HidKeyboardState *states, size_t count) { HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr(); if (sharedmem == NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_NotInitialized)); size_t total = _hidGetStates(&sharedmem->keyboard.lifo.header, sharedmem->keyboard.lifo.storage, 17, offsetof(HidKeyboardStateAtomicStorage,state), offsetof(HidKeyboardState,sampling_number), states, sizeof(HidKeyboardState), count); return total; } void hidInitializeNpad(void) { Result rc = _hidActivateNpad(); if (R_FAILED(rc)) diagAbortWithResult(rc); } static size_t _hidGetNpadStates(HidNpadCommonLifo *lifo, HidNpadCommonState *states, size_t count) { if (count > 17) count = 17; return _hidGetStates(&lifo->header, lifo->storage, 17, offsetof(HidNpadCommonStateAtomicStorage,state), offsetof(HidNpadCommonState,sampling_number), states, sizeof(HidNpadCommonState), count); } size_t hidGetNpadStatesFullKey(HidNpadIdType id, HidNpadFullKeyState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->full_key_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesHandheld(HidNpadIdType id, HidNpadHandheldState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->handheld_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesJoyDual(HidNpadIdType id, HidNpadJoyDualState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->joy_dual_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesJoyLeft(HidNpadIdType id, HidNpadJoyLeftState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->joy_left_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesJoyRight(HidNpadIdType id, HidNpadJoyRightState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->joy_right_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesGc(HidNpadIdType id, HidNpadGcState *states, size_t count) { HidNpadCommonState tmp_entries[17]; HidNpadGcTriggerState tmp_entries_trigger[17]; HidNpadInternalState *npad = _hidGetNpadInternalState(id); size_t total = _hidGetNpadStates(&npad->full_key_lifo, tmp_entries, count); size_t total2 = _hidGetStates(&npad->gc_trigger_lifo.header, npad->gc_trigger_lifo.storage, 17, offsetof(HidNpadGcTriggerStateAtomicStorage,state), offsetof(HidNpadGcTriggerState,sampling_number), tmp_entries_trigger, sizeof(HidNpadGcTriggerState), total); if (total2 < total) total = total2; memset(states, 0, sizeof(HidNpadGcState) * total); for (size_t i=0; ipalma_lifo, states, count); // sdknso doesn't handle ControlPadRestriction with this. return total; } size_t hidGetNpadStatesLark(HidNpadIdType id, HidNpadLarkState *states, size_t count) { HidNpadCommonState tmp_entries[17]; HidNpadInternalState *npad = _hidGetNpadInternalState(id); size_t total = _hidGetNpadStates(&npad->full_key_lifo, tmp_entries, count); memset(states, 0, sizeof(HidNpadLarkState) * total); HidNpadLarkType lark_type_l_and_main = atomic_load_explicit(&npad->lark_type_l_and_main, memory_order_acquire); if (!(lark_type_l_and_main>=HidNpadLarkType_H1 && lark_type_l_and_main<=HidNpadLarkType_NR)) lark_type_l_and_main = HidNpadLarkType_Invalid; for (size_t i=0; ihandheld_lifo, tmp_entries, count); memset(states, 0, sizeof(HidNpadHandheldLarkState) * total); HidNpadLarkType lark_type_l_and_main = atomic_load_explicit(&npad->lark_type_l_and_main, memory_order_acquire); if (!(lark_type_l_and_main>=HidNpadLarkType_H1 && lark_type_l_and_main<=HidNpadLarkType_NR)) lark_type_l_and_main = HidNpadLarkType_Invalid; HidNpadLarkType lark_type_r = atomic_load_explicit(&npad->lark_type_r, memory_order_acquire); if (!(lark_type_r>=HidNpadLarkType_H1 && lark_type_r<=HidNpadLarkType_NR)) lark_type_r = HidNpadLarkType_Invalid; for (size_t i=0; ifull_key_lifo, tmp_entries, count); memset(states, 0, sizeof(HidNpadLuciaState) * total); HidNpadLuciaType lucia_type = atomic_load_explicit(&npad->lucia_type, memory_order_acquire); if (!(lucia_type>=HidNpadLuciaType_J && lucia_type<=HidNpadLuciaType_U)) lucia_type = HidNpadLuciaType_Invalid; for (size_t i=0; isystem_ext_lifo, states, count); // sdknso would handle button-bitmasking with ControlPadRestriction here. return total; } size_t hidGetNpadStatesSystem(HidNpadIdType id, HidNpadSystemState *states, size_t count) { size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->system_ext_lifo, states, count); for (size_t i=0; ifull_key_six_axis_sensor_lifo; break; case 1: // NpadHandheld/NpadHandheldLark lifo = &npad->handheld_six_axis_sensor_lifo; break; case 2: // NpadJoyDual if (handle.idx==0) lifo = &npad->joy_dual_left_six_axis_sensor_lifo; else if (handle.idx==1) lifo = &npad->joy_dual_right_six_axis_sensor_lifo; else diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); break; case 3: // NpadJoyLeft lifo = &npad->joy_left_six_axis_sensor_lifo; break; case 4: // NpadJoyRight lifo = &npad->joy_right_six_axis_sensor_lifo; break; case 29: // System(Ext) (not actually returned by GetHandles) case 30: return 0; } size_t total = _hidGetStates(&lifo->header, lifo->storage, 17, offsetof(HidSixAxisSensorStateAtomicStorage,state), offsetof(HidSixAxisSensorState,sampling_number), states, sizeof(HidSixAxisSensorState), count); return total; } void hidInitializeGesture(void) { Result rc = _hidActivateGesture(); if (R_FAILED(rc)) diagAbortWithResult(rc); } size_t hidGetGestureStates(HidGestureState *states, size_t count) { HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr(); if (sharedmem == NULL) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_NotInitialized)); size_t total = _hidGetStates(&sharedmem->gesture.lifo.header, sharedmem->gesture.lifo.storage, 17, offsetof(HidGestureDummyStateAtomicStorage,state), offsetof(HidGestureState,sampling_number), states, sizeof(HidGestureState), count); return total; } bool hidIsControllerConnected(HidControllerID id) { if (id==CONTROLLER_P1_AUTO) return hidIsControllerConnected(g_controllerP1AutoID); if (id < 0 || id > 9) return 0; rwlockReadLock(&g_hidLock); bool flag = (g_controllerEntries[id].attributes & HidNpadAttribute_IsConnected) != 0; rwlockReadUnlock(&g_hidLock); return flag; } u64 hidKeysHeld(HidControllerID id) { if (id==CONTROLLER_P1_AUTO) return hidKeysHeld(g_controllerP1AutoID); if (id < 0 || id > 9) return 0; rwlockReadLock(&g_hidLock); u64 tmp = g_controllerHeld[id]; rwlockReadUnlock(&g_hidLock); return tmp; } u64 hidKeysDown(HidControllerID id) { if (id==CONTROLLER_P1_AUTO) return hidKeysDown(g_controllerP1AutoID); if (id < 0 || id > 9) return 0; rwlockReadLock(&g_hidLock); u64 tmp = g_controllerDown[id]; rwlockReadUnlock(&g_hidLock); return tmp; } u64 hidKeysUp(HidControllerID id) { if (id==CONTROLLER_P1_AUTO) return hidKeysUp(g_controllerP1AutoID); if (id < 0 || id > 9) return 0; rwlockReadLock(&g_hidLock); u64 tmp = g_controllerUp[id]; rwlockReadUnlock(&g_hidLock); return tmp; } u64 hidMouseButtonsHeld(void) { rwlockReadLock(&g_hidLock); u64 tmp = g_mouseHeld; rwlockReadUnlock(&g_hidLock); return tmp; } u64 hidMouseButtonsDown(void) { rwlockReadLock(&g_hidLock); u64 tmp = g_mouseDown; rwlockReadUnlock(&g_hidLock); return tmp; } u64 hidMouseButtonsUp(void) { rwlockReadLock(&g_hidLock); u64 tmp = g_mouseUp; rwlockReadUnlock(&g_hidLock); return tmp; } void hidMouseRead(MousePosition *pos) { rwlockReadLock(&g_hidLock); pos->x = g_mouseState.x; pos->y = g_mouseState.y; pos->velocityX = g_mouseState.delta_x; pos->velocityY = g_mouseState.delta_y; pos->scrollVelocityX = g_mouseState.wheel_delta_x; pos->scrollVelocityY = g_mouseState.wheel_delta_y; rwlockReadUnlock(&g_hidLock); } u32 hidMouseMultiRead(MousePosition *entries, u32 num_entries) { HidMouseState temp_states[17]; if (!entries || !num_entries) return 0; if (num_entries > 17) num_entries = 17; memset(entries, 0, sizeof(MousePosition) * num_entries); size_t total = hidGetMouseStates(temp_states, num_entries); for (size_t i=0; i= g_touchScreenState.count) { memset(pos, 0, sizeof(touchPosition)); return; } pos->id = g_touchScreenState.touches[point_id].finger_id; pos->px = g_touchScreenState.touches[point_id].x; pos->py = g_touchScreenState.touches[point_id].y; pos->dx = g_touchScreenState.touches[point_id].diameter_x; pos->dy = g_touchScreenState.touches[point_id].diameter_y; pos->angle = g_touchScreenState.touches[point_id].rotation_angle; } } void hidJoystickRead(JoystickPosition *pos, HidControllerID id, HidControllerJoystick stick) { if (id == CONTROLLER_P1_AUTO) return hidJoystickRead(pos, g_controllerP1AutoID, stick); if (pos) { if (id < 0 || id > 9 || stick >= JOYSTICK_NUM_STICKS) { memset(pos, 0, sizeof(*pos)); return; } rwlockReadLock(&g_hidLock); memcpy(pos, stick==JOYSTICK_LEFT ? &g_controllerEntries[id].analog_stick_l : &g_controllerEntries[id].analog_stick_r, sizeof(HidAnalogStickState)); rwlockReadUnlock(&g_hidLock); } } u32 hidSixAxisSensorValuesRead(SixAxisSensorValues *values, HidControllerID id, u32 num_entries) { HidSixAxisSensorState temp_states[17]; if (!values || !num_entries) return 0; if (id == CONTROLLER_P1_AUTO) id = g_controllerP1AutoID; memset(values, 0, sizeof(SixAxisSensorValues) * num_entries); if (id < 0 || id > 9) return 0; if (num_entries > 17) num_entries = 17; HidNpadIdType npad_id = hidControllerIDToNpadIdType(id); u32 style_set = hidGetNpadStyleSet(npad_id); size_t num_handles = 1; size_t handle_idx = 0; style_set &= -style_set; // retrieve least significant set bit if (style_set == HidNpadStyleTag_NpadJoyDual) { u32 device_type = hidGetNpadDeviceType(npad_id); num_handles = 2; if (device_type & HidDeviceTypeBits_JoyLeft) handle_idx = 0; else if (device_type & HidDeviceTypeBits_JoyRight) handle_idx = 1; else return 0; } HidSixAxisSensorHandle handles[2]; Result rc = hidGetSixAxisSensorHandles(handles, num_handles, npad_id, style_set); if (R_FAILED(rc)) return 0; size_t total = hidGetSixAxisSensorStates(handles[handle_idx], temp_states, num_entries); for (size_t i=0; i 1.0f) return MAKERESULT(Module_Libnx, LibnxError_BadInput); const struct { HidSixAxisSensorHandle handle; float unk0; float unk1; u32 pad; u64 AppletResourceUserId; } in = { handle, unk0, unk1, 0, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_hidSrv, 70, in, .in_send_pid = true, ); } Result hidGetSixAxisSensorFusionParameters(HidSixAxisSensorHandle handle, float *unk0, float *unk1) { Result rc; const struct { HidSixAxisSensorHandle handle; u32 pad; u64 AppletResourceUserId; } in = { handle, 0, appletGetAppletResourceUserId() }; struct { float unk0; float unk1; } out; rc = serviceDispatchInOut(&g_hidSrv, 71, in, out, .in_send_pid = true, ); if (R_SUCCEEDED(rc) && unk0) *unk0 = out.unk0; if (R_SUCCEEDED(rc) && unk1) *unk1 = out.unk1; return rc; } Result hidResetSixAxisSensorFusionParameters(HidSixAxisSensorHandle handle) { return _hidCmdInU32AruidNoOut(handle.type_value, 72); } Result hidSetGyroscopeZeroDriftMode(HidSixAxisSensorHandle handle, HidGyroscopeZeroDriftMode mode) { const struct { HidSixAxisSensorHandle handle; u32 mode; u64 AppletResourceUserId; } in = { handle, mode, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_hidSrv, 79, in, .in_send_pid = true, ); } Result hidGetGyroscopeZeroDriftMode(HidSixAxisSensorHandle handle, HidGyroscopeZeroDriftMode *mode) { Result rc; const struct { HidSixAxisSensorHandle handle; u32 pad; u64 AppletResourceUserId; } in = { handle, 0, appletGetAppletResourceUserId() }; u32 tmp=0; rc = serviceDispatchInOut(&g_hidSrv, 80, in, tmp, .in_send_pid = true, ); if (R_SUCCEEDED(rc) && mode) *mode = tmp; return rc; } Result hidResetGyroscopeZeroDriftMode(HidSixAxisSensorHandle handle) { return _hidCmdInU32AruidNoOut(handle.type_value, 81); } Result hidIsSixAxisSensorAtRest(HidSixAxisSensorHandle handle, bool *out) { return _hidCmdInU32AruidOutBool(handle.type_value, out, 82); } Result hidIsFirmwareUpdateAvailableForSixAxisSensor(HidSixAxisSensorHandle handle, bool *out) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hidCmdInU32AruidOutBool(handle.type_value, out, 83); } Result hidSetSupportedNpadStyleSet(u32 style_set) { return _hidCmdInU32AruidNoOut(style_set, 100); } static Result _hidActivateGesture(void) { u32 val=1; return _hidCmdInU32AruidNoOut(val, 91); // ActivateGesture } Result hidGetSupportedNpadStyleSet(u32 *style_set) { u32 tmp=0; Result rc = _hidCmdInAruidOutU32(&tmp, 101); if (R_SUCCEEDED(rc) && style_set) *style_set = tmp; return rc; } Result hidSetSupportedNpadIdType(const HidNpadIdType *ids, size_t count) { u64 AppletResourceUserId = appletGetAppletResourceUserId(); return serviceDispatchIn(&g_hidSrv, 102, AppletResourceUserId, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, .buffers = { { ids, count*sizeof(HidNpadIdType) } }, .in_send_pid = true, ); } static Result _hidActivateNpad(void) { u32 revision=0x0; if (hosversionBefore(5,0,0)) return _hidCmdInAruidNoOut(103); // ActivateNpad revision = 0x1; // [5.0.0+] if (hosversionAtLeast(6,0,0)) revision = 0x2; // [6.0.0+] if (hosversionAtLeast(8,0,0)) revision = 0x3; // [8.0.0+] return _hidCmdInU32AruidNoOut(revision, 109); // ActivateNpadWithRevision } Result hidAcquireNpadStyleSetUpdateEventHandle(HidNpadIdType id, Event* out_event, bool autoclear) { Result rc; Handle tmp_handle = INVALID_HANDLE; const struct { u32 id; u32 pad; u64 AppletResourceUserId; u64 event_ptr; // Official sw sets this to a ptr, which the sysmodule doesn't seem to use. } in = { id, 0, appletGetAppletResourceUserId(), 0 }; rc = serviceDispatchIn(&g_hidSrv, 106, in, .in_send_pid = true, .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, .out_handles = &tmp_handle, ); if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); return rc; } Result hidSetNpadJoyHoldType(HidNpadJoyHoldType type) { return _hidCmdInU64AruidNoOut(type, 120); } Result hidGetNpadJoyHoldType(HidNpadJoyHoldType *type) { u64 tmp=0; Result rc = _hidCmdInAruidOutU64(&tmp, 121); if (R_SUCCEEDED(rc) && type) *type = tmp; return rc; } Result hidSetNpadJoyAssignmentModeSingleByDefault(HidNpadIdType id) { return _hidCmdInU32AruidNoOut(id, 122); } Result hidSetNpadJoyAssignmentModeDual(HidNpadIdType id) { return _hidCmdInU32AruidNoOut(id, 124); } Result hidMergeSingleJoyAsDualJoy(HidNpadIdType id0, HidNpadIdType id1) { const struct { u32 id0, id1; u64 AppletResourceUserId; } in = { id0, id1, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_hidSrv, 125, in, .in_send_pid = true, ); } Result hidSetNpadHandheldActivationMode(HidNpadHandheldActivationMode mode) { return _hidCmdInU64AruidNoOut(mode, 128); } Result hidGetNpadHandheldActivationMode(HidNpadHandheldActivationMode *out) { u64 tmp=0; Result rc = _hidCmdInAruidOutU64(&tmp, 129); if (R_SUCCEEDED(rc) && out) *out = tmp; // Official sw would abort if tmp isn't 0-2. return rc; } static Result _hidCreateActiveVibrationDeviceList(Service* srv_out) { return _hidCmdGetSession(srv_out, 203); } static Result _hidActivateVibrationDevice(Service* srv, HidVibrationDeviceHandle handle) { return _hidCmdInU32NoOut(srv, handle.type_value, 0); } Result hidGetVibrationDeviceInfo(HidVibrationDeviceHandle handle, HidVibrationDeviceInfo *out) { return serviceDispatchInOut(&g_hidSrv, 200, handle, *out); } Result hidSendVibrationValue(HidVibrationDeviceHandle handle, const HidVibrationValue *value) { const struct { HidVibrationDeviceHandle handle; HidVibrationValue value; u32 pad; u64 AppletResourceUserId; } in = { handle, *value, 0, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_hidSrv, 201, in, .in_send_pid = true, ); } Result hidGetActualVibrationValue(HidVibrationDeviceHandle handle, HidVibrationValue *out) { const struct { HidVibrationDeviceHandle handle; u32 pad; u64 AppletResourceUserId; } in = { handle, 0, appletGetAppletResourceUserId() }; return serviceDispatchInOut(&g_hidSrv, 202, in, *out, .in_send_pid = true, ); } Result hidPermitVibration(bool flag) { return _hidCmdInBoolNoOut(flag, 204); } Result hidIsVibrationPermitted(bool *flag) { return _hidCmdNoInOutBool(flag, 205); } Result hidSendVibrationValues(const HidVibrationDeviceHandle *handles, const HidVibrationValue *values, s32 count) { u64 AppletResourceUserId = appletGetAppletResourceUserId(); return serviceDispatchIn(&g_hidSrv, 206, AppletResourceUserId, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In, SfBufferAttr_HipcPointer | SfBufferAttr_In, }, .buffers = { { handles, count*sizeof(HidVibrationDeviceHandle) }, { values, count*sizeof(HidVibrationValue) }, }, ); } Result hidSendVibrationGcErmCommand(HidVibrationDeviceHandle handle, HidVibrationGcErmCommand cmd) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { HidVibrationDeviceHandle handle; u32 pad; u64 AppletResourceUserId; u64 cmd; } in = { handle, 0, appletGetAppletResourceUserId(), cmd }; return serviceDispatchIn(&g_hidSrv, 207, in, .in_send_pid = true, ); } Result hidGetActualVibrationGcErmCommand(HidVibrationDeviceHandle handle, HidVibrationGcErmCommand *out) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { HidVibrationDeviceHandle handle; u32 pad; u64 AppletResourceUserId; } in = { handle, 0, appletGetAppletResourceUserId() }; u64 tmp=0; Result rc = serviceDispatchInOut(&g_hidSrv, 208, in, tmp, .in_send_pid = true, ); if (R_SUCCEEDED(rc) && out) *out = tmp; return rc; } Result hidBeginPermitVibrationSession(void) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hidCmdInU64NoOut(&g_hidSrv, appletGetAppletResourceUserId(), 209); } Result hidEndPermitVibrationSession(void) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hidCmdNoIO(&g_hidSrv, 210); } Result hidIsVibrationDeviceMounted(HidVibrationDeviceHandle handle, bool *flag) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; const struct { HidVibrationDeviceHandle handle; u32 pad; u64 AppletResourceUserId; } in = { handle, 0, appletGetAppletResourceUserId() }; u8 tmp=0; rc = serviceDispatchInOut(&g_hidSrv, 211, in, tmp, .in_send_pid = true, ); if (R_SUCCEEDED(rc) && flag) *flag = tmp & 1; return rc; } static HidVibrationDeviceHandle _hidMakeVibrationDeviceHandle(u8 npad_style_index, u8 npad_id_type, u8 device_idx) { return (HidVibrationDeviceHandle){.npad_style_index = npad_style_index, .player_number = npad_id_type, .device_idx = device_idx, .pad = 0}; } static HidSixAxisSensorHandle _hidMakeSixAxisSensorHandle(u8 npad_style_index, u8 npad_id_type, u8 idx) { return (HidSixAxisSensorHandle){.npad_style_index = npad_style_index, .npad_id_type = npad_id_type, .idx = idx, .pad = 0}; } static u8 _hidGetSixAxisSensorHandleNpadStyleIndex(HidSixAxisSensorHandle handle) { return handle.npad_style_index - 3; } static Result _hidGetVibrationDeviceHandles(HidVibrationDeviceHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style) { Result rc=0; s32 max_handles=1; u32 style_index=0; u8 idx=0; if (total_handles <= 0 || total_handles > 2) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (style & HidNpadStyleTag_NpadFullKey) { style_index = 3; max_handles = 2; } else if (style & HidNpadStyleTag_NpadHandheld) { style_index = 4; max_handles = 2; } else if (style & HidNpadStyleTag_NpadJoyDual) { style_index = 5; max_handles = 2; } else if (style & HidNpadStyleTag_NpadJoyLeft) { style_index = 6; } else if (style & HidNpadStyleTag_NpadJoyRight) { style_index = 7; idx = 0x1; } else if (style & HidNpadStyleTag_NpadGc) { style_index = 8; } else if (style & HidNpadStyleTag_Npad10) { style_index = 0xd; } else if (style & (HidNpadStyleTag_NpadLark | HidNpadStyleTag_NpadLucia)) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else if (style & HidNpadStyleTag_NpadHandheldLark) { style_index = 4; max_handles = 2; } else if (style & HidNpadStyleTag_NpadSystem) { style_index = 0x21; max_handles = 2; } else if (style & HidNpadStyleTag_NpadSystemExt) { style_index = 0x20; max_handles = 2; } else if (style & HidNpadStyleTag_NpadPalma) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else { return MAKERESULT(Module_Libnx, LibnxError_BadInput); } handles[0] = _hidMakeVibrationDeviceHandle(style_index, id, idx); if (total_handles > 1) { if (max_handles > 1) { handles[1] = _hidMakeVibrationDeviceHandle(style_index, id, 0x1); } else { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would just return 0 here. } } return rc; } static Result _hidGetSixAxisSensorHandles(HidSixAxisSensorHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style) { Result rc=0; s32 max_handles=1; u32 style_index=0; u8 idx=0; if (total_handles <= 0 || total_handles > 2) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (style & HidNpadStyleTag_NpadFullKey) { style_index = 3; idx = 0x2; } else if (style & HidNpadStyleTag_NpadHandheld) { style_index = 4; idx = 0x2; } else if (style & HidNpadStyleTag_NpadJoyDual) { style_index = 5; max_handles = 2; } else if (style & HidNpadStyleTag_NpadJoyLeft) { style_index = 6; } else if (style & HidNpadStyleTag_NpadJoyRight) { style_index = 7; idx = 0x1; } else if (style & HidNpadStyleTag_NpadGc) { style_index = 3; idx = 0x2; } else if (style & HidNpadStyleTag_Npad10) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else if (style & (HidNpadStyleTag_NpadLark | HidNpadStyleTag_NpadLucia)) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else if (style & HidNpadStyleTag_NpadHandheldLark) { style_index = 4; idx = 0x2; } else if (style & HidNpadStyleTag_NpadSystem) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else if (style & HidNpadStyleTag_NpadSystemExt) { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } else if (style & HidNpadStyleTag_NpadPalma) { style_index = 3; idx = 0x2; } else { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles. } handles[0] = _hidMakeSixAxisSensorHandle(style_index, id, idx); if (total_handles > 1) { if (max_handles > 1) { handles[1] = _hidMakeSixAxisSensorHandle(style_index, id, 0x1); } else { return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would just return 0 here. } } return rc; } Result hidInitializeVibrationDevices(HidVibrationDeviceHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style) { Result rc=0; s32 i; if (id == (HidNpadIdType)CONTROLLER_HANDHELD) id = HidNpadIdType_Handheld; // Correct enum value for old users passing HidControllerID instead (avoids a hid sysmodule fatal later on) rc = _hidGetVibrationDeviceHandles(handles, total_handles, id, style); if (R_FAILED(rc)) return rc; mutexLock(&g_hidVibrationMutex); if (!serviceIsActive(&g_hidIActiveVibrationDeviceList)) { rc = _hidCreateActiveVibrationDeviceList(&g_hidIActiveVibrationDeviceList); } mutexUnlock(&g_hidVibrationMutex); if (R_FAILED(rc)) return rc; for (i=0; isize, tmem1->size }; return serviceDispatchIn(&g_hidSrv, 306, in, .in_send_pid = true, .in_num_handles = 2, .in_handles = { tmem0->handle, tmem1->handle }, ); } Result hidInitializeSevenSixAxisSensor(void) { Result rc=0; size_t bufsize = 0x80000; if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (g_sevenSixAxisSensorBuffer != NULL) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); if (hosversionBefore(10,0,0)) { // No longer used by sdknso on [10.0.0+]. rc = _hidActivateConsoleSixAxisSensor(); if (R_FAILED(rc)) return rc; } g_sevenSixAxisSensorBuffer = (u8*)memalign(0x1000, bufsize); if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); memset(g_sevenSixAxisSensorBuffer, 0, bufsize); rc = tmemCreateFromMemory(&g_sevenSixAxisSensorTmem0, g_sevenSixAxisSensorBuffer, 0x1000, Perm_R); if (R_SUCCEEDED(rc)) rc = tmemCreateFromMemory(&g_sevenSixAxisSensorTmem1, &g_sevenSixAxisSensorBuffer[0x1000], bufsize-0x1000, Perm_None); if (R_SUCCEEDED(rc)) rc = _hidInitializeSevenSixAxisSensor(&g_sevenSixAxisSensorTmem0, &g_sevenSixAxisSensorTmem1); if (R_FAILED(rc)) { tmemClose(&g_sevenSixAxisSensorTmem0); tmemClose(&g_sevenSixAxisSensorTmem1); free(g_sevenSixAxisSensorBuffer); g_sevenSixAxisSensorBuffer = NULL; } return rc; } Result hidFinalizeSevenSixAxisSensor(void) { Result rc=0; if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); rc = _hidCmdInAruidNoOut(307); tmemClose(&g_sevenSixAxisSensorTmem0); tmemClose(&g_sevenSixAxisSensorTmem1); free(g_sevenSixAxisSensorBuffer); g_sevenSixAxisSensorBuffer = NULL; return rc; } Result hidSetSevenSixAxisSensorFusionStrength(float strength) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { float strength; u64 AppletResourceUserId; } in = { strength, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_hidSrv, 308, in, .in_send_pid = true, ); } Result hidGetSevenSixAxisSensorFusionStrength(float *strength) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u64 AppletResourceUserId = appletGetAppletResourceUserId(); return serviceDispatchInOut(&g_hidSrv, 309, AppletResourceUserId, *strength, .in_send_pid = true, ); } Result hidResetSevenSixAxisSensorTimestamp(void) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _hidCmdInAruidNoOut(310); } Result hidGetSevenSixAxisSensorStates(HidSevenSixAxisSensorState *states, size_t count, size_t *total_out) { if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (states == NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); HidSevenSixAxisSensorStates *states_buf = (HidSevenSixAxisSensorStates*)g_sevenSixAxisSensorBuffer; size_t total = _hidGetStates(&states_buf->header, states_buf->storage, 0x21, offsetof(HidSevenSixAxisSensorStateEntry,state), offsetof(HidSevenSixAxisSensorState,sampling_number), states, sizeof(HidSevenSixAxisSensorState), count); if (total_out) *total_out = total; return 0; } Result hidIsSevenSixAxisSensorAtRest(bool *out) { if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); HidSharedMemory *shared_mem = (HidSharedMemory*)hidGetSharedmemAddr(); *out = shared_mem->console_six_axis_sensor.is_seven_six_axis_sensor_at_rest & 1; return 0; } Result hidGetSensorFusionError(float *out) { if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); HidSharedMemory *shared_mem = (HidSharedMemory*)hidGetSharedmemAddr(); *out = shared_mem->console_six_axis_sensor.verticalization_error; return 0; } Result hidGetGyroBias(UtilFloat3 *out) { if (g_sevenSixAxisSensorBuffer == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); HidSharedMemory *shared_mem = (HidSharedMemory*)hidGetSharedmemAddr(); *out = shared_mem->console_six_axis_sensor.gyro_bias; return 0; } Result hidGetNpadInterfaceType(HidNpadIdType id, u8 *out) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 tmp = id; return serviceDispatchInOut(&g_hidSrv, 405, tmp, *out); }