libnx/nx/source/services/hid.c

1933 lines
64 KiB
C

#define NX_SERVICE_ASSUME_NON_DOMAIN
#include "service_guard.h"
#include <string.h>
#include <stdlib.h>
#include <stdatomic.h>
#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"
#include "../runtime/alloc.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 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 _hidGetVibrationDeviceHandles(HidVibrationDeviceHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style);
static Result _hidCreateActiveVibrationDeviceList(Service* srv_out);
static Result _hidActivateVibrationDevice(Service* srv, HidVibrationDeviceHandle handle);
static u8 _hidGetSixAxisSensorHandleNpadStyleIndex(HidSixAxisSensorHandle handle);
static Result _hidGetSixAxisSensorHandles(HidSixAxisSensorHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style);
static Result _hidGetPalmaOperationResult(HidPalmaConnectionHandle 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));
serviceClose(&g_hidIActiveVibrationDeviceList);
shmemClose(&g_hidSharedmem);
serviceClose(&g_hidIAppletResource);
serviceClose(&g_hidSrv);
}
Service* hidGetServiceSession(void) {
return &g_hidSrv;
}
void* hidGetSharedmemAddr(void) {
return shmemGetAddr(&g_hidSharedmem);
}
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; i<total_entries; i++) {
s32 entrypos = (((tail + (max_states+1)) - total_entries) + i) % max_states;
void* state_entry = (void*)((uintptr_t)in_states + entrypos*(state_offset+entrysize));
void* out_state = (void*)((uintptr_t)states + (total_entries-i-1)*entrysize);
void* out_state_prev = (void*)((uintptr_t)states + (total_entries-i)*entrysize);
u64 sampling_number0=0, sampling_number1=0;
sampling_number0 = atomic_load_explicit((u64*)state_entry, memory_order_acquire);
memcpy(out_state, (void*)((uintptr_t)state_entry + state_offset), entrysize);
sampling_number1 = atomic_load_explicit((u64*)state_entry, memory_order_acquire);
if (sampling_number0 != sampling_number1 || (i>0 && *((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<total; i++) {
if (states[i].count > 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; i<total; i++) {
states[i].sampling_number = tmp_entries[i].sampling_number;
// sdknso would handle button-bitmasking with ControlPadRestriction here.
states[i].buttons = tmp_entries[i].buttons;
memcpy(&states[i].analog_stick_l, &tmp_entries[i].analog_stick_l, sizeof(tmp_entries[i].analog_stick_l)); // sdknso uses index 0 for the src here.
memcpy(&states[i].analog_stick_r, &tmp_entries[i].analog_stick_r, sizeof(tmp_entries[i].analog_stick_r)); // sdknso uses index 0 for the src here.
states[i].attributes = tmp_entries[i].attributes;
states[i].trigger_l = tmp_entries_trigger[i].trigger_l;
states[i].trigger_r = tmp_entries_trigger[i].trigger_r;
}
return total;
}
size_t hidGetNpadStatesPalma(HidNpadIdType id, HidNpadPalmaState *states, size_t count) {
size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->palma_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; i<total; i++) {
states[i].sampling_number = tmp_entries[i].sampling_number;
// sdknso would handle button-bitmasking with ControlPadRestriction here.
states[i].buttons = tmp_entries[i].buttons;
// Leave analog-sticks state at zeros.
states[i].attributes = tmp_entries[i].attributes;
states[i].lark_type_l_and_main = lark_type_l_and_main;
}
return total;
}
size_t hidGetNpadStatesHandheldLark(HidNpadIdType id, HidNpadHandheldLarkState *states, size_t count) {
HidNpadCommonState tmp_entries[17];
HidNpadInternalState *npad = _hidGetNpadInternalState(id);
size_t total = _hidGetNpadStates(&npad->handheld_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; i<total; i++) {
states[i].sampling_number = tmp_entries[i].sampling_number;
// sdknso would handle button-bitmasking with ControlPadRestriction here.
states[i].buttons = tmp_entries[i].buttons;
memcpy(&states[i].analog_stick_l, &tmp_entries[i].analog_stick_l, sizeof(tmp_entries[i].analog_stick_l)); // sdknso uses index 0 for the src here.
memcpy(&states[i].analog_stick_r, &tmp_entries[i].analog_stick_r, sizeof(tmp_entries[i].analog_stick_r)); // sdknso uses index 0 for the src here.
states[i].attributes = tmp_entries[i].attributes;
states[i].lark_type_l_and_main = lark_type_l_and_main;
states[i].lark_type_r = lark_type_r;
}
return total;
}
size_t hidGetNpadStatesLucia(HidNpadIdType id, HidNpadLuciaState *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(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; i<total; i++) {
states[i].sampling_number = tmp_entries[i].sampling_number;
// sdknso would handle button-bitmasking with ControlPadRestriction here.
states[i].buttons = tmp_entries[i].buttons;
// Leave analog-sticks state at zeros.
states[i].attributes = tmp_entries[i].attributes;
states[i].lucia_type = lucia_type;
}
return total;
}
size_t hidGetNpadStatesSystemExt(HidNpadIdType id, HidNpadSystemExtState *states, size_t count) {
size_t total = _hidGetNpadStates(&_hidGetNpadInternalState(id)->system_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; i<total; i++) {
u64 buttons = states[i].buttons;
u64 new_buttons = 0;
if (buttons & HidNpadButton_AnyLeft) new_buttons |= HidNpadButton_Left;
if (buttons & HidNpadButton_AnyUp) new_buttons |= HidNpadButton_Up;
if (buttons & HidNpadButton_AnyRight) new_buttons |= HidNpadButton_Right;
if (buttons & HidNpadButton_AnyDown) new_buttons |= HidNpadButton_Down;
if (buttons & (HidNpadButton_L|HidNpadButton_ZL)) new_buttons |= HidNpadButton_L; // sdknso would mask out this button on the else condition for both of these, but it was already clear anyway.
if (buttons & (HidNpadButton_R|HidNpadButton_ZR)) new_buttons |= HidNpadButton_R;
buttons = new_buttons | (buttons & (HidNpadButton_A|HidNpadButton_B|HidNpadButton_X|HidNpadButton_Y));
// sdknso would handle button-bitmasking with ControlPadRestriction here.
states[i].buttons = buttons;
memset(&states[i].analog_stick_l, 0, sizeof(states[i].analog_stick_l));
memset(&states[i].analog_stick_r, 0, sizeof(states[i].analog_stick_r));
}
return total;
}
size_t hidGetSixAxisSensorStates(HidSixAxisSensorHandle handle, HidSixAxisSensorState *states, size_t count) {
HidNpadSixAxisSensorLifo *lifo = NULL;
HidNpadInternalState *npad = _hidGetNpadInternalState(handle.player_number);
switch(_hidGetSixAxisSensorHandleNpadStyleIndex(handle)) {
default:
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
case 0: // NpadFullKey/NpadPalma
case 5: // NpadGc (not actually returned by GetHandles, NpadFullKey is used instead)
lifo = &npad->full_key_six_axis_sensor_lifo;
break;
case 1: // NpadHandheld/NpadHandheldLark
lifo = &npad->handheld_six_axis_sensor_lifo;
break;
case 2: // NpadJoyDual
if (handle.device_idx==0) lifo = &npad->joy_dual_left_six_axis_sensor_lifo;
else if (handle.device_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;
}
static Result _hidCmdNoIO(Service* srv, u32 cmd_id) {
return serviceDispatch(srv, cmd_id);
}
static Result _hidCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) {
return serviceDispatch(srv, cmd_id,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = handle_out,
);
}
static Result _hidCmdGetSession(Service* srv_out, u32 cmd_id) {
return serviceDispatch(&g_hidSrv, cmd_id,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _hidCmdInAruidNoOut(u32 cmd_id) {
u64 AppletResourceUserId = appletGetAppletResourceUserId();
return serviceDispatchIn(&g_hidSrv, cmd_id, AppletResourceUserId,
.in_send_pid = true,
);
}
static Result _hidCmdInU8NoOut(u8 inval, u32 cmd_id) {
return serviceDispatchIn(&g_hidSrv, cmd_id, inval);
}
static Result _hidCmdInBoolNoOut(bool inval, u32 cmd_id) {
return _hidCmdInU8NoOut(inval!=0, cmd_id);
}
static Result _hidCmdInU32NoOut(Service* srv, u32 inval, u32 cmd_id) {
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _hidCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) {
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _hidCmdInU16U64NoOut(Service* srv, u16 inval0, u64 inval1, u32 cmd_id) {
const struct {
u16 inval0;
u8 pad[6];
u64 inval1;
} in = { inval0, {0}, inval1 };
return serviceDispatchIn(srv, cmd_id, in);
}
static Result _hidCmdInU32U64NoOut(Service* srv, u32 inval0, u64 inval1, u32 cmd_id) {
const struct {
u32 inval0;
u32 pad;
u64 inval1;
} in = { inval0, 0, inval1 };
return serviceDispatchIn(srv, cmd_id, in);
}
static Result _hidCmdInU64U64NoOut(Service* srv, u64 inval0, u64 inval1, u32 cmd_id) {
const struct {
u64 inval0;
u64 inval1;
} in = { inval0, inval1 };
return serviceDispatchIn(srv, cmd_id, in);
}
static Result _hidCmdInU8AruidNoOut(u8 inval, u32 cmd_id) {
const struct {
u8 inval;
u8 pad[7];
u64 AppletResourceUserId;
} in = { inval, {0}, appletGetAppletResourceUserId() };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInBoolAruidNoOut(bool flag, u32 cmd_id) {
return _hidCmdInU8AruidNoOut(flag!=0, cmd_id);
}
static Result _hidCmdInU32AruidNoOut(u32 inval, u32 cmd_id) {
const struct {
u32 inval;
u32 pad;
u64 AppletResourceUserId;
} in = { inval, 0, appletGetAppletResourceUserId() };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInU64AruidNoOut(u64 inval, u32 cmd_id) {
const struct {
u64 AppletResourceUserId;
u64 inval;
} in = { appletGetAppletResourceUserId(), inval };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInU32AruidU64NoOut(u32 in32, u64 in64, u32 cmd_id) {
const struct {
u32 in32;
u32 pad;
u64 AppletResourceUserId;
u64 in64;
} in = { in32, 0, appletGetAppletResourceUserId(), in64 };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInU8U32AruidNoOut(u8 in8, u32 in32, u32 cmd_id) {
const struct {
u8 in8;
u8 pad[3];
u32 in32;
u64 AppletResourceUserId;
} in = { in8, {0}, in32, appletGetAppletResourceUserId() };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInBoolU32AruidNoOut(bool flag, u32 in32, u32 cmd_id) {
return _hidCmdInU8U32AruidNoOut(flag!=0, in32, cmd_id);
}
static Result _hidCmdInU32U32AruidNoOut(u32 val0, u32 val1, u32 cmd_id) {
const struct {
u32 val0, val1;
u64 AppletResourceUserId;
} in = { val0, val1, appletGetAppletResourceUserId() };
return serviceDispatchIn(&g_hidSrv, cmd_id, in,
.in_send_pid = true,
);
}
static Result _hidCmdInU32AruidOutU8(u32 inval, u8 *out, u32 cmd_id) {
const struct {
u32 inval;
u32 pad;
u64 AppletResourceUserId;
} in = { inval, 0, appletGetAppletResourceUserId() };
return serviceDispatchInOut(&g_hidSrv, cmd_id, in, *out,
.in_send_pid = true,
);
}
static Result _hidCmdInU32AruidOutBool(u32 inval, bool *out, u32 cmd_id) {
u8 tmp=0;
Result rc = _hidCmdInU32AruidOutU8(inval, &tmp, cmd_id);
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
static Result _hidCmdInU32AruidOutU64(u32 inval, u64 *out, u32 cmd_id) {
const struct {
u32 inval;
u32 pad;
u64 AppletResourceUserId;
} in = { inval, 0, appletGetAppletResourceUserId() };
return serviceDispatchInOut(&g_hidSrv, cmd_id, in, *out,
.in_send_pid = true,
);
}
static Result _hidCmdInAruidOutU32(u32 *out, u32 cmd_id) {
u64 AppletResourceUserId = appletGetAppletResourceUserId();
return serviceDispatchInOut(&g_hidSrv, cmd_id, AppletResourceUserId, *out,
.in_send_pid = true,
);
}
static Result _hidCmdInAruidOutU64(u64 *out, u32 cmd_id) {
u64 AppletResourceUserId = appletGetAppletResourceUserId();
return serviceDispatchInOut(&g_hidSrv, cmd_id, AppletResourceUserId, *out,
.in_send_pid = true,
);
}
static Result _hidCmdNoInOutU8(u8 *out, u32 cmd_id) {
return serviceDispatchOut(&g_hidSrv, cmd_id, *out);
}
static Result _hidCmdNoInOutBool(bool *out, u32 cmd_id) {
u8 tmp=0;
Result rc = _hidCmdNoInOutU8(&tmp, cmd_id);
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
static Result _hidCmdNoInOutU64(u64 *out, u32 cmd_id) {
return serviceDispatchOut(&g_hidSrv, cmd_id, *out);
}
static Result _hidCreateAppletResource(Service* srv, Service* srv_out) {
u64 AppletResourceUserId = appletGetAppletResourceUserId();
return serviceDispatchIn(srv, 0, AppletResourceUserId,
.in_send_pid = true,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _hidGetSharedMemoryHandle(Service* srv, Handle* handle_out) {
return _hidCmdGetHandle(srv, handle_out, 0);
}
static Result _hidActivateTouchScreen(void) {
return _hidCmdInAruidNoOut(11);
}
static Result _hidActivateMouse(void) {
return _hidCmdInAruidNoOut(21);
}
static Result _hidActivateKeyboard(void) {
return _hidCmdInAruidNoOut(31);
}
Result hidSendKeyboardLockKeyEvent(u32 events) {
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU32AruidNoOut(events, 32);
}
Result hidGetSixAxisSensorHandles(HidSixAxisSensorHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style) {
return _hidGetSixAxisSensorHandles(handles, total_handles, id, style);
}
Result hidStartSixAxisSensor(HidSixAxisSensorHandle handle) {
return _hidCmdInU32AruidNoOut(handle.type_value, 66);
}
Result hidStopSixAxisSensor(HidSixAxisSensorHandle handle) {
return _hidCmdInU32AruidNoOut(handle.type_value, 67);
}
Result hidIsSixAxisSensorFusionEnabled(HidSixAxisSensorHandle handle, bool *out) {
return _hidCmdInU32AruidOutBool(handle.type_value, out, 68);
}
Result hidEnableSixAxisSensorFusion(HidSixAxisSensorHandle handle, bool flag) {
return _hidCmdInBoolU32AruidNoOut(flag, handle.type_value, 69);
}
Result hidSetSixAxisSensorFusionParameters(HidSixAxisSensorHandle handle, float unk0, float unk1) {
if (unk0 < 0.0f || unk0 > 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);
}
static Result _hidActivateGesture(void) {
u32 val=1;
return _hidCmdInU32AruidNoOut(val, 91); // ActivateGesture
}
Result hidSetSupportedNpadStyleSet(u32 style_set) {
return _hidCmdInU32AruidNoOut(style_set, 100);
}
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 hidDisconnectNpad(HidNpadIdType id) {
return _hidCmdInU32AruidNoOut(id, 107);
}
Result hidGetPlayerLedPattern(HidNpadIdType id, u8 *out) {
u32 in=id;
u64 tmp=0;
Result rc = serviceDispatchIn(&g_hidSrv, 108, in, tmp);
if (R_SUCCEEDED(rc) && out) *out = tmp;
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 hidSetNpadJoyAssignmentModeSingle(HidNpadIdType id, HidNpadJoyDeviceType type) {
return _hidCmdInU32AruidU64NoOut(id, type, 123);
}
Result hidSetNpadJoyAssignmentModeDual(HidNpadIdType id) {
return _hidCmdInU32AruidNoOut(id, 124);
}
Result hidMergeSingleJoyAsDualJoy(HidNpadIdType id0, HidNpadIdType id1) {
return _hidCmdInU32U32AruidNoOut(id0, id1, 125);
}
Result hidStartLrAssignmentMode(void) {
return _hidCmdInAruidNoOut(126);
}
Result hidStopLrAssignmentMode(void) {
return _hidCmdInAruidNoOut(127);
}
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;
}
Result hidSwapNpadAssignment(HidNpadIdType id0, HidNpadIdType id1) {
return _hidCmdInU32U32AruidNoOut(id0, id1, 130);
}
Result hidEnableUnintendedHomeButtonInputProtection(HidNpadIdType id, bool flag) {
return _hidCmdInBoolU32AruidNoOut(flag, id, 132);
}
Result hidSetNpadJoyAssignmentModeSingleWithDestination(HidNpadIdType id, HidNpadJoyDeviceType type, bool *flag, HidNpadIdType *dest) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u32 id;
u32 pad;
u64 AppletResourceUserId;
s64 type;
} in = { id, 0, appletGetAppletResourceUserId(), type };
struct {
u8 flag;
u8 pad[3];
u32 id;
} out;
Result rc = serviceDispatchInOut(&g_hidSrv, 133, in, out,
.in_send_pid = true,
);
if (R_SUCCEEDED(rc)) {
if (flag) *flag = out.flag & 1;
if (dest) *dest = out.id;
}
return rc;
}
Result hidSetNpadAnalogStickUseCenterClamp(bool flag) {
if (hosversionBefore(6,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInBoolAruidNoOut(flag, 134);
}
Result hidSetNpadCaptureButtonAssignment(HidNpadStyleTag style, u64 buttons) {
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU32AruidU64NoOut(style, buttons, 135);
}
Result hidClearNpadCaptureButtonAssignment(void) {
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInAruidNoOut(136);
}
Result hidInitializeVibrationDevices(HidVibrationDeviceHandle *handles, s32 total_handles, HidNpadIdType id, HidNpadStyleTag style) {
Result rc=0;
s32 i;
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; i<total_handles; i++) {
rc = _hidActivateVibrationDevice(&g_hidIActiveVibrationDeviceList, handles[i]);
if (R_FAILED(rc))
break;
}
return rc;
}
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,
);
}
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 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 player_number, u8 device_idx) {
return (HidVibrationDeviceHandle){.npad_style_index = npad_style_index, .player_number = player_number, .device_idx = device_idx, .pad = 0};
}
static HidSixAxisSensorHandle _hidMakeSixAxisSensorHandle(u8 npad_style_index, u8 player_number, u8 device_idx) {
return (HidSixAxisSensorHandle){.npad_style_index = npad_style_index, .player_number = player_number, .device_idx = device_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 device_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;
device_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, device_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 device_idx=0;
if (total_handles <= 0 || total_handles > 2)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (style & HidNpadStyleTag_NpadFullKey) {
style_index = 3;
device_idx = 0x2;
}
else if (style & HidNpadStyleTag_NpadHandheld) {
style_index = 4;
device_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;
device_idx = 0x1;
}
else if (style & HidNpadStyleTag_NpadGc) {
style_index = 3;
device_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;
device_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;
device_idx = 0x2;
}
else {
return MAKERESULT(Module_Libnx, LibnxError_BadInput); // sdknso would return 0, and return no handles.
}
handles[0] = _hidMakeSixAxisSensorHandle(style_index, id, device_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;
}
static Result _hidActivateConsoleSixAxisSensor(void) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInAruidNoOut(300);
}
Result hidStartSevenSixAxisSensor(void) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInAruidNoOut(304);
}
Result hidStopSevenSixAxisSensor(void) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInAruidNoOut(305);
}
static Result _hidInitializeSevenSixAxisSensor(TransferMemory *tmem0, TransferMemory *tmem1) {
const struct {
u64 AppletResourceUserId;
u64 size0;
u64 size1;
} in = { appletGetAppletResourceUserId(), tmem0->size, 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*)__libnx_aligned_alloc(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);
__libnx_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);
__libnx_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 hidIsUsbFullKeyControllerEnabled(bool *out) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdNoInOutBool(out, 400);
}
Result hidEnableUsbFullKeyController(bool flag) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInBoolNoOut(flag, 401);
}
Result hidIsUsbFullKeyControllerConnected(HidNpadIdType id, bool *out) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u8 tmp=0;
Result rc = serviceDispatchInOut(&g_hidSrv, 402, id, tmp);
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
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);
}
Result hidGetNpadOfHighestBatteryLevel(const HidNpadIdType *ids, size_t count, HidNpadIdType *out) {
if (hosversionBefore(10,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u64 AppletResourceUserId = appletGetAppletResourceUserId();
u32 tmp=0;
Result rc = serviceDispatchInOut(&g_hidSrv, 407, AppletResourceUserId, tmp,
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
.buffers = { { ids, count*sizeof(HidNpadIdType) } },
.in_send_pid = true,
);
if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc;
}
Result hidGetPalmaConnectionHandle(HidNpadIdType id, HidPalmaConnectionHandle *out) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u64 tmp=0;
Result rc = _hidCmdInU32AruidOutU64(id, &tmp, 500);
if (R_SUCCEEDED(rc) && out) out->handle = tmp;
return rc;
}
Result hidInitializePalma(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 501);
}
Result hidAcquirePalmaOperationCompleteEvent(HidPalmaConnectionHandle handle, Event* out_event, bool autoclear) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Result rc;
Handle tmp_handle = INVALID_HANDLE;
rc = serviceDispatchIn(&g_hidSrv, 502, handle,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &tmp_handle,
);
if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear);
return rc;
}
static Result _hidGetPalmaOperationInfo(HidPalmaConnectionHandle handle, void* buffer, size_t size, u64 *out) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_hidSrv, 503, handle, *out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
}
Result hidGetPalmaOperationInfo(HidPalmaConnectionHandle handle, HidPalmaOperationInfo *out) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
Result rc=0;
Result rc2=0;
u64 tmp=0;
bool old_ver = hosversionBefore(5,1,0);
rc = _hidGetPalmaOperationInfo(handle, out->data, sizeof(out->data), &tmp);
if (R_SUCCEEDED(rc) || old_ver) {
if (old_ver) rc2 = rc;
else rc2 = _hidGetPalmaOperationResult(handle);
out->res = rc2;
if (tmp > (old_ver ? HidPalmaOperationType_SuspendFeature : HidPalmaOperationType_ResetPlayLog)) rc = MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen); // sdknso would Abort here.
else out->type = tmp;
}
return rc;
}
Result hidPlayPalmaActivity(HidPalmaConnectionHandle handle, u16 val) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64U64NoOut(&g_hidSrv, handle.handle, val, 504);
}
Result hidSetPalmaFrModeType(HidPalmaConnectionHandle handle, HidPalmaFrModeType type) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64U64NoOut(&g_hidSrv, handle.handle, type, 505);
}
Result hidReadPalmaStep(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 506);
}
Result hidEnablePalmaStep(HidPalmaConnectionHandle handle, bool flag) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 flag;
u8 pad[7];
HidPalmaConnectionHandle handle;
} in = { flag!=0, {0}, handle };
return serviceDispatchIn(&g_hidSrv, 507, in);
}
Result hidResetPalmaStep(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 508);
}
Result hidReadPalmaApplicationSection(HidPalmaConnectionHandle handle, s32 inval0, u64 size) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (size > sizeof(HidPalmaApplicationSectionAccessBuffer))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
const struct {
HidPalmaConnectionHandle handle;
u64 inval0;
u64 size;
} in = { handle, inval0, size };
return serviceDispatchIn(&g_hidSrv, 509, in);
}
Result hidWritePalmaApplicationSection(HidPalmaConnectionHandle handle, s32 inval0, u64 size, const HidPalmaApplicationSectionAccessBuffer *buf) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
HidPalmaConnectionHandle handle;
u64 inval0;
u64 size;
} in = { handle, inval0, size };
return serviceDispatchIn(&g_hidSrv, 510, in,
.buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In },
.buffers = { { buf, sizeof(*buf) } },
);
}
Result hidReadPalmaUniqueCode(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 511);
}
Result hidSetPalmaUniqueCodeInvalid(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 512);
}
Result hidWritePalmaActivityEntry(HidPalmaConnectionHandle handle, u16 unk, const HidPalmaActivityEntry *entry) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
HidPalmaConnectionHandle handle;
u64 unk;
u64 rgb_led_pattern_index;
u64 wave_set;
u64 wave_index;
} in = { handle, unk, entry->rgb_led_pattern_index, entry->wave_set, entry->wave_index };
return serviceDispatchIn(&g_hidSrv, 513, in);
}
Result hidWritePalmaRgbLedPatternEntry(HidPalmaConnectionHandle handle, u16 unk, const void* buffer, size_t size) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
HidPalmaConnectionHandle handle;
u64 unk;
} in = { handle, unk };
return serviceDispatchIn(&g_hidSrv, 514, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
static Result _hidWritePalmaWaveEntry(HidPalmaConnectionHandle handle, HidPalmaWaveSet wave_set, u16 unk, TransferMemory *tmem, size_t size) {
const struct {
HidPalmaConnectionHandle handle;
u64 wave_set;
u64 unk;
u64 tmem_size;
u64 size;
} in = { handle, wave_set, unk, tmem->size, size };
return serviceDispatchIn(&g_hidSrv, 515, in,
.in_num_handles = 1,
.in_handles = { tmem->handle },
);
}
Result hidWritePalmaWaveEntry(HidPalmaConnectionHandle handle, HidPalmaWaveSet wave_set, u16 unk, const void* buffer, size_t tmem_size, size_t size) {
Result rc=0;
TransferMemory tmem={0};
rc = tmemCreateFromMemory(&tmem, (void*)buffer, tmem_size, Perm_R);
if (R_SUCCEEDED(rc)) rc = _hidWritePalmaWaveEntry(handle, wave_set, unk, &tmem, size);
tmemClose(&tmem);
return rc;
}
Result hidSetPalmaDataBaseIdentificationVersion(HidPalmaConnectionHandle handle, s32 version) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU32U64NoOut(&g_hidSrv, version, handle.handle, 516);
}
Result hidGetPalmaDataBaseIdentificationVersion(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 517);
}
Result hidSuspendPalmaFeature(HidPalmaConnectionHandle handle, u32 features) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU32U64NoOut(&g_hidSrv, features, handle.handle, 518);
}
static Result _hidGetPalmaOperationResult(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 519);
}
Result hidReadPalmaPlayLog(HidPalmaConnectionHandle handle, u16 unk) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU16U64NoOut(&g_hidSrv, unk, handle.handle, 520);
}
Result hidResetPalmaPlayLog(HidPalmaConnectionHandle handle, u16 unk) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU16U64NoOut(&g_hidSrv, unk, handle.handle, 521);
}
Result hidSetIsPalmaAllConnectable(bool flag) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInBoolAruidNoOut(flag, 522);
}
Result hidSetIsPalmaPairedConnectable(bool flag) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInBoolAruidNoOut(flag, 523);
}
Result hidPairPalma(HidPalmaConnectionHandle handle) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 524);
}
static Result _hidSetPalmaBoostMode(bool flag) {
if (hosversionBefore(5,1,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInBoolNoOut(flag, 525);
}
Result hidCancelWritePalmaWaveEntry(HidPalmaConnectionHandle handle) {
if (hosversionBefore(7,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _hidCmdInU64NoOut(&g_hidSrv, handle.handle, 526);
}
Result hidEnablePalmaBoostMode(bool flag) {
if (hosversionBefore(8,0,0))
return _hidSetPalmaBoostMode(flag);
return _hidCmdInBoolAruidNoOut(flag, 527);
}
Result hidGetPalmaBluetoothAddress(HidPalmaConnectionHandle handle, BtdrvAddress *out) {
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_hidSrv, 528, handle, *out);
}
Result hidSetDisallowedPalmaConnection(const BtdrvAddress *addrs, s32 count) {
if (hosversionBefore(8,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u64 AppletResourceUserId = appletGetAppletResourceUserId();
return serviceDispatchIn(&g_hidSrv, 529, AppletResourceUserId,
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
.buffers = { { addrs, count*sizeof(BtdrvAddress) } },
.in_send_pid = true,
);
}
Result hidSetNpadCommunicationMode(HidNpadCommunicationMode mode) {
return _hidCmdInU64AruidNoOut(mode, 1000);
}
Result hidGetNpadCommunicationMode(HidNpadCommunicationMode *out) {
u64 tmp=0;
Result rc = _hidCmdNoInOutU64(&tmp, 1001);
if (R_SUCCEEDED(rc) && out) *out = tmp; // sdknso would Abort when tmp is not 0-3.
return rc;
}
Result hidSetTouchScreenConfiguration(const HidTouchScreenConfigurationForNx *config) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
HidTouchScreenConfigurationForNx config;
u64 AppletResourceUserId;
} in = { *config, appletGetAppletResourceUserId() };
return serviceDispatchIn(&g_hidSrv, 1002, in,
.in_send_pid = true,
);
}
Result hidIsFirmwareUpdateNeededForNotification(bool *out) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
s32 val=1;
const struct {
s32 val;
u32 pad;
u64 AppletResourceUserId;
} in = { val, 0, appletGetAppletResourceUserId() };
u8 tmp=0;
Result rc = serviceDispatchInOut(&g_hidSrv, 1003, in, tmp,
.in_send_pid = true,
);
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}