mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
hid: Updated/added structs and added hidGetNpadStates*().
This commit is contained in:
parent
74b295827f
commit
ddc9538b69
@ -545,8 +545,8 @@ typedef struct HidControllerMAC {
|
|||||||
u64 timestamp_2;
|
u64 timestamp_2;
|
||||||
} HidControllerMAC;
|
} HidControllerMAC;
|
||||||
|
|
||||||
/// HidControllerHeader
|
/// HidNpadStateHeader
|
||||||
typedef struct HidControllerHeader {
|
typedef struct HidNpadStateHeader {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 isHalf;
|
u32 isHalf;
|
||||||
u32 singleColorsDescriptor;
|
u32 singleColorsDescriptor;
|
||||||
@ -557,9 +557,9 @@ typedef struct HidControllerHeader {
|
|||||||
u32 leftColorButtons;
|
u32 leftColorButtons;
|
||||||
u32 rightColorBody;
|
u32 rightColorBody;
|
||||||
u32 rightColorButtons;
|
u32 rightColorButtons;
|
||||||
} HidControllerHeader;
|
} HidNpadStateHeader;
|
||||||
|
|
||||||
/// Info struct extracted from HidControllerHeader.
|
/// Info struct extracted from HidNpadStateHeader.
|
||||||
/// Color fields are zero when not set. This can happen even when the *Set fields are set to true.
|
/// Color fields are zero when not set. This can happen even when the *Set fields are set to true.
|
||||||
typedef struct HidControllerColors
|
typedef struct HidControllerColors
|
||||||
{
|
{
|
||||||
@ -576,19 +576,30 @@ typedef struct HidControllerColors
|
|||||||
|
|
||||||
/// HidControllerLayoutHeader
|
/// HidControllerLayoutHeader
|
||||||
typedef struct HidControllerLayoutHeader {
|
typedef struct HidControllerLayoutHeader {
|
||||||
u64 timestampTicks;
|
u64 timestamp_ticks;
|
||||||
u64 numEntries;
|
u64 total_entries;
|
||||||
u64 latestEntry;
|
u64 latest_entry;
|
||||||
u64 maxEntryIndex;
|
u64 max_entry;
|
||||||
} HidControllerLayoutHeader;
|
} HidControllerLayoutHeader;
|
||||||
|
|
||||||
|
/// HidNpadStateEntry
|
||||||
|
typedef struct HidNpadStateEntry {
|
||||||
|
u64 timestamp;
|
||||||
|
u64 buttons;
|
||||||
|
JoystickPosition joysticks[JOYSTICK_NUM_STICKS];
|
||||||
|
u64 connectionState;
|
||||||
|
} HidNpadStateEntry;
|
||||||
|
|
||||||
|
typedef HidNpadStateEntry HidNpadFullKeyState;
|
||||||
|
typedef HidNpadStateEntry HidNpadHandheldState;
|
||||||
|
typedef HidNpadStateEntry HidNpadJoyDualState;
|
||||||
|
typedef HidNpadStateEntry HidNpadJoyLeftState;
|
||||||
|
typedef HidNpadStateEntry HidNpadJoyRightState;
|
||||||
|
|
||||||
/// HidControllerInputEntry
|
/// HidControllerInputEntry
|
||||||
typedef struct HidControllerInputEntry {
|
typedef struct HidControllerInputEntry {
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
u64 timestamp_2;
|
HidNpadStateEntry state;
|
||||||
u64 buttons;
|
|
||||||
JoystickPosition joysticks[JOYSTICK_NUM_STICKS];
|
|
||||||
u64 connectionState;
|
|
||||||
} HidControllerInputEntry;
|
} HidControllerInputEntry;
|
||||||
|
|
||||||
/// HidControllerLayout
|
/// HidControllerLayout
|
||||||
@ -661,7 +672,7 @@ typedef struct {
|
|||||||
|
|
||||||
/// HidController
|
/// HidController
|
||||||
typedef struct HidController {
|
typedef struct HidController {
|
||||||
HidControllerHeader header;
|
HidNpadStateHeader header;
|
||||||
HidControllerLayout layouts[7];
|
HidControllerLayout layouts[7];
|
||||||
HidControllerSixAxisLayout sixaxis[6];
|
HidControllerSixAxisLayout sixaxis[6];
|
||||||
HidControllerMisc misc;
|
HidControllerMisc misc;
|
||||||
@ -788,6 +799,12 @@ void hidGetControllerPowerInfo(HidControllerID id, HidPowerInfo *info, size_t to
|
|||||||
|
|
||||||
void hidScanInput(void);
|
void hidScanInput(void);
|
||||||
|
|
||||||
|
void hidGetNpadStatesFullKey(u32 id, HidNpadFullKeyState *states, size_t count, size_t *total_out);
|
||||||
|
void hidGetNpadStatesHandheld(u32 id, HidNpadHandheldState *states, size_t count, size_t *total_out);
|
||||||
|
void hidGetNpadStatesJoyDual(u32 id, HidNpadJoyDualState *states, size_t count, size_t *total_out);
|
||||||
|
void hidGetNpadStatesJoyLeft(u32 id, HidNpadJoyLeftState *states, size_t count, size_t *total_out);
|
||||||
|
void hidGetNpadStatesJoyRight(u32 id, HidNpadJoyRightState *states, size_t count, size_t *total_out);
|
||||||
|
|
||||||
u64 hidKeysHeld(HidControllerID id);
|
u64 hidKeysHeld(HidControllerID id);
|
||||||
u64 hidKeysDown(HidControllerID id);
|
u64 hidKeysDown(HidControllerID id);
|
||||||
u64 hidKeysUp(HidControllerID id);
|
u64 hidKeysUp(HidControllerID id);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "services/applet.h"
|
#include "services/applet.h"
|
||||||
#include "services/hid.h"
|
#include "services/hid.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
|
#include "runtime/diag.h"
|
||||||
|
|
||||||
static Service g_hidSrv;
|
static Service g_hidSrv;
|
||||||
static Service g_hidIAppletResource;
|
static Service g_hidIAppletResource;
|
||||||
@ -19,7 +20,7 @@ static HidTouchScreenEntry g_touchEntry;
|
|||||||
static HidMouseEntry *g_mouseEntry;
|
static HidMouseEntry *g_mouseEntry;
|
||||||
static HidMouse g_mouse;
|
static HidMouse g_mouse;
|
||||||
static HidKeyboardEntry g_keyboardEntry;
|
static HidKeyboardEntry g_keyboardEntry;
|
||||||
static HidControllerHeader g_controllerHeaders[10];
|
static HidNpadStateHeader g_controllerHeaders[10];
|
||||||
static HidControllerInputEntry g_controllerEntries[10];
|
static HidControllerInputEntry g_controllerEntries[10];
|
||||||
static HidControllerSixAxisLayout g_sixaxisLayouts[10];
|
static HidControllerSixAxisLayout g_sixaxisLayouts[10];
|
||||||
static HidControllerMisc g_controllerMisc[10];
|
static HidControllerMisc g_controllerMisc[10];
|
||||||
@ -238,14 +239,14 @@ void hidScanInput(void) {
|
|||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
HidControllerLayout *currentLayout = &sharedMem->controllers[i].layouts[g_controllerLayout[i]];
|
HidControllerLayout *currentLayout = &sharedMem->controllers[i].layouts[g_controllerLayout[i]];
|
||||||
memcpy(&g_controllerHeaders[i], &sharedMem->controllers[i].header, sizeof(HidControllerHeader));
|
memcpy(&g_controllerHeaders[i], &sharedMem->controllers[i].header, sizeof(HidNpadStateHeader));
|
||||||
u64 latestControllerEntry = currentLayout->header.latestEntry;
|
u64 latestControllerEntry = currentLayout->header.latest_entry;
|
||||||
HidControllerInputEntry *newInputEntry = ¤tLayout->entries[latestControllerEntry];
|
HidControllerInputEntry *newInputEntry = ¤tLayout->entries[latestControllerEntry];
|
||||||
if ((s64)(newInputEntry->timestamp - g_controllerTimestamps[i]) >= 0) {
|
if ((s64)(newInputEntry->timestamp - g_controllerTimestamps[i]) >= 0) {
|
||||||
memcpy(&g_controllerEntries[i], newInputEntry, sizeof(HidControllerInputEntry));
|
memcpy(&g_controllerEntries[i], newInputEntry, sizeof(HidControllerInputEntry));
|
||||||
g_controllerTimestamps[i] = newInputEntry->timestamp;
|
g_controllerTimestamps[i] = newInputEntry->timestamp;
|
||||||
|
|
||||||
g_controllerHeld[i] |= g_controllerEntries[i].buttons;
|
g_controllerHeld[i] |= g_controllerEntries[i].state.buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i];
|
g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i];
|
||||||
@ -283,7 +284,7 @@ void hidScanInput(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_controllerP1AutoID = CONTROLLER_HANDHELD;
|
g_controllerP1AutoID = CONTROLLER_HANDHELD;
|
||||||
if (g_controllerEntries[CONTROLLER_PLAYER_1].connectionState & CONTROLLER_STATE_CONNECTED)
|
if (g_controllerEntries[CONTROLLER_PLAYER_1].state.connectionState & CONTROLLER_STATE_CONNECTED)
|
||||||
g_controllerP1AutoID = CONTROLLER_PLAYER_1;
|
g_controllerP1AutoID = CONTROLLER_PLAYER_1;
|
||||||
|
|
||||||
rwlockWriteUnlock(&g_hidLock);
|
rwlockWriteUnlock(&g_hidLock);
|
||||||
@ -308,7 +309,7 @@ void hidGetControllerColors(HidControllerID id, HidControllerColors *colors) {
|
|||||||
if (id < 0 || id > 9) return;
|
if (id < 0 || id > 9) return;
|
||||||
if (colors == NULL) return;
|
if (colors == NULL) return;
|
||||||
|
|
||||||
HidControllerHeader *hdr = &g_controllerHeaders[id];
|
HidNpadStateHeader *hdr = &g_controllerHeaders[id];
|
||||||
|
|
||||||
memset(colors, 0, sizeof(HidControllerColors));
|
memset(colors, 0, sizeof(HidControllerColors));
|
||||||
|
|
||||||
@ -338,7 +339,7 @@ bool hidIsControllerConnected(HidControllerID id) {
|
|||||||
if (id < 0 || id > 9) return 0;
|
if (id < 0 || id > 9) return 0;
|
||||||
|
|
||||||
rwlockReadLock(&g_hidLock);
|
rwlockReadLock(&g_hidLock);
|
||||||
bool flag = (g_controllerEntries[id].connectionState & CONTROLLER_STATE_CONNECTED) != 0;
|
bool flag = (g_controllerEntries[id].state.connectionState & CONTROLLER_STATE_CONNECTED) != 0;
|
||||||
rwlockReadUnlock(&g_hidLock);
|
rwlockReadUnlock(&g_hidLock);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
@ -394,6 +395,82 @@ void hidGetControllerPowerInfo(HidControllerID id, HidPowerInfo *info, size_t to
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HidController *_hidNpadSharedmemGetInternalState(u32 id) {
|
||||||
|
if (id >= 0x8) id = id==0x10 ? 0x9 : 0x8;
|
||||||
|
|
||||||
|
HidSharedMemory *sharedmem = (HidSharedMemory*)hidGetSharedmemAddr();
|
||||||
|
if (sharedmem == NULL) return NULL;
|
||||||
|
return &sharedmem->controllers[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidGetNpadStates(u32 id, u32 layout, HidNpadStateEntry *states, size_t count, size_t *total_out) {
|
||||||
|
if (total_out) *total_out = 0;
|
||||||
|
|
||||||
|
if (id >= 0x8 && (id!=0x10 && id!=0x20))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
|
||||||
|
HidController *npad = _hidNpadSharedmemGetInternalState(id);
|
||||||
|
if (npad == NULL)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
HidControllerLayout *states_buf = &npad->layouts[layout];
|
||||||
|
|
||||||
|
s32 total_entries = (s32)atomic_load_explicit(&states_buf->header.max_entry, memory_order_acquire);
|
||||||
|
if (total_entries < 0) total_entries = 0;
|
||||||
|
if (total_entries > count) total_entries = count;
|
||||||
|
s32 latest_entry = (s32)atomic_load_explicit(&states_buf->header.latest_entry, memory_order_acquire);
|
||||||
|
|
||||||
|
for (s32 i=0; i<total_entries; i++) {
|
||||||
|
s32 entrypos = (((latest_entry + 0x12) - total_entries) + i) % 0x11;
|
||||||
|
|
||||||
|
u64 timestamp0=0, timestamp1=0;
|
||||||
|
|
||||||
|
timestamp0 = atomic_load_explicit(&states_buf->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
memcpy(&states[total_entries-i-1], &states_buf->entries[entrypos].state, sizeof(HidNpadStateEntry));
|
||||||
|
timestamp1 = atomic_load_explicit(&states_buf->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
|
||||||
|
if (timestamp0 != timestamp1 || (i>0 && states[total_entries-i-1].timestamp - states[total_entries-i].timestamp != 1)) {
|
||||||
|
s32 tmpcount = (s32)atomic_load_explicit(&states_buf->header.max_entry, memory_order_acquire);
|
||||||
|
tmpcount = total_entries < tmpcount ? tmpcount : total_entries;
|
||||||
|
total_entries = tmpcount < count ? tmpcount : count;
|
||||||
|
latest_entry = (s32)atomic_load_explicit(&states_buf->header.latest_entry, memory_order_acquire);
|
||||||
|
|
||||||
|
i=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_out) *total_out = total_entries;
|
||||||
|
|
||||||
|
// sdknso would handle button-bitmasking with ControlPadRestriction here.
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hidGetNpadStatesFullKey(u32 id, HidNpadFullKeyState *states, size_t count, size_t *total_out) {
|
||||||
|
Result rc = _hidGetNpadStates(id, 0, states, count, total_out);
|
||||||
|
if (R_FAILED(rc)) diagAbortWithResult(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hidGetNpadStatesHandheld(u32 id, HidNpadHandheldState *states, size_t count, size_t *total_out) {
|
||||||
|
Result rc = _hidGetNpadStates(id, 1, states, count, total_out);
|
||||||
|
if (R_FAILED(rc)) diagAbortWithResult(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hidGetNpadStatesJoyDual(u32 id, HidNpadJoyDualState *states, size_t count, size_t *total_out) {
|
||||||
|
Result rc = _hidGetNpadStates(id, 2, states, count, total_out);
|
||||||
|
if (R_FAILED(rc)) diagAbortWithResult(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hidGetNpadStatesJoyLeft(u32 id, HidNpadJoyLeftState *states, size_t count, size_t *total_out) {
|
||||||
|
Result rc = _hidGetNpadStates(id, 3, states, count, total_out);
|
||||||
|
if (R_FAILED(rc)) diagAbortWithResult(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hidGetNpadStatesJoyRight(u32 id, HidNpadJoyRightState *states, size_t count, size_t *total_out) {
|
||||||
|
Result rc = _hidGetNpadStates(id, 4, states, count, total_out);
|
||||||
|
if (R_FAILED(rc)) diagAbortWithResult(rc);
|
||||||
|
}
|
||||||
|
|
||||||
u64 hidKeysHeld(HidControllerID id) {
|
u64 hidKeysHeld(HidControllerID id) {
|
||||||
if (id==CONTROLLER_P1_AUTO) return hidKeysHeld(g_controllerP1AutoID);
|
if (id==CONTROLLER_P1_AUTO) return hidKeysHeld(g_controllerP1AutoID);
|
||||||
if (id < 0 || id > 9) return 0;
|
if (id < 0 || id > 9) return 0;
|
||||||
@ -569,8 +646,8 @@ void hidJoystickRead(JoystickPosition *pos, HidControllerID id, HidControllerJoy
|
|||||||
}
|
}
|
||||||
|
|
||||||
rwlockReadLock(&g_hidLock);
|
rwlockReadLock(&g_hidLock);
|
||||||
pos->dx = g_controllerEntries[id].joysticks[stick].dx;
|
pos->dx = g_controllerEntries[id].state.joysticks[stick].dx;
|
||||||
pos->dy = g_controllerEntries[id].joysticks[stick].dy;
|
pos->dy = g_controllerEntries[id].state.joysticks[stick].dy;
|
||||||
rwlockReadUnlock(&g_hidLock);
|
rwlockReadUnlock(&g_hidLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user