mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
303 lines
6.7 KiB
C
303 lines
6.7 KiB
C
#include <string.h>
|
|
#include "types.h"
|
|
#include "result.h"
|
|
#include "arm/atomics.h"
|
|
#include "kernel/ipc.h"
|
|
#include "kernel/event.h"
|
|
#include "services/applet.h"
|
|
#include "services/hidsys.h"
|
|
#include "services/hid.h"
|
|
#include "services/sm.h"
|
|
#include "runtime/hosversion.h"
|
|
|
|
static Service g_hidsysSrv;
|
|
static u64 g_hidsysRefCnt;
|
|
|
|
static u64 g_hidsysAppletResourceUserId = 0;
|
|
|
|
Result hidsysInitialize(void) {
|
|
atomicIncrement64(&g_hidsysRefCnt);
|
|
|
|
if (serviceIsActive(&g_hidsysSrv))
|
|
return 0;
|
|
|
|
Result rc = smGetService(&g_hidsysSrv, "hid:sys");
|
|
if (R_FAILED(rc))
|
|
return rc;
|
|
|
|
rc = appletGetAppletResourceUserId(&g_hidsysAppletResourceUserId);
|
|
if (R_FAILED(rc))
|
|
g_hidsysAppletResourceUserId = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void hidsysExit(void) {
|
|
if (atomicDecrement64(&g_hidsysRefCnt) == 0) {
|
|
serviceClose(&g_hidsysSrv);
|
|
}
|
|
}
|
|
|
|
Result hidsysEnableAppletToGetInput(bool enable) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmdid;
|
|
u8 permitInput;
|
|
u64 appletResourceUserId;
|
|
} *raw;
|
|
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmdid = 503;
|
|
raw->permitInput = enable != 0;
|
|
raw->appletResourceUserId = g_hidsysAppletResourceUserId;
|
|
|
|
Result rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _hidsysCmdWithResIdAndPid(u64 cmd_id) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u64 AppletResourceUserId;
|
|
} *raw;
|
|
|
|
ipcSendPid(&c);
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = cmd_id;
|
|
raw->AppletResourceUserId = g_hidsysAppletResourceUserId;
|
|
|
|
Result rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _hidsysGetHandle(Handle* handle_out, u64 cmd_id) {
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u64 AppletResourceUserId;
|
|
} *raw;
|
|
|
|
ipcSendPid(&c);
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = cmd_id;
|
|
raw->AppletResourceUserId = g_hidsysAppletResourceUserId;
|
|
|
|
Result rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
|
|
rc = resp->result;
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
*handle_out = r.Handles[0];
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _hidsysGetEvent(Event* event_out, u64 cmd_id, bool autoclear) {
|
|
Handle tmp_handle=0;
|
|
Result rc = 0;
|
|
|
|
rc = _hidsysGetHandle(&tmp_handle, cmd_id);
|
|
if (R_SUCCEEDED(rc)) eventLoadRemote(event_out, tmp_handle, autoclear);
|
|
return rc;
|
|
}
|
|
|
|
Result hidsysAcquireHomeButtonEventHandle(Event* event_out) {
|
|
return _hidsysGetEvent(event_out, 101, false);
|
|
}
|
|
|
|
//These functions don't seem to work in the overlaydisp applet context
|
|
Result hidsysAcquireCaptureButtonEventHandle(Event* event_out) {
|
|
return _hidsysGetEvent(event_out, 141, false);
|
|
}
|
|
|
|
Result hidsysAcquireSleepButtonEventHandle(Event* event_out) {
|
|
return _hidsysGetEvent(event_out, 121, false);
|
|
}
|
|
|
|
Result hidsysActivateHomeButton(void) {
|
|
return _hidsysCmdWithResIdAndPid(111);
|
|
}
|
|
|
|
Result hidsysActivateSleepButton(void) {
|
|
return _hidsysCmdWithResIdAndPid(131);
|
|
}
|
|
|
|
Result hidsysActivateCaptureButton(void) {
|
|
return _hidsysCmdWithResIdAndPid(151);
|
|
}
|
|
|
|
Result hidsysGetUniquePadsFromNpad(HidControllerID id, u64 *UniquePadIds, size_t count, size_t *total_entries) {
|
|
if (hosversionBefore(3,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
Result rc;
|
|
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
u32 id;
|
|
} PACKED *raw;
|
|
|
|
ipcAddRecvStatic(&c, UniquePadIds, sizeof(u64)*count, 0);
|
|
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 321;
|
|
raw->id = hidControllerIDToOfficial(id);
|
|
|
|
rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
u64 total_entries;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
|
|
if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
Result hidsysGetUniquePadIds(u64 *UniquePadIds, size_t count, size_t *total_entries) {
|
|
Result rc;
|
|
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
} *raw;
|
|
|
|
ipcAddRecvStatic(&c, UniquePadIds, sizeof(u64)*count, 0);
|
|
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 703;
|
|
|
|
rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
u64 total_entries;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
|
|
if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
Result hidsysSetNotificationLedPattern(const HidsysNotificationLedPattern *pattern, u64 UniquePadId) {
|
|
if (hosversionBefore(7,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
Result rc;
|
|
|
|
IpcCommand c;
|
|
ipcInitialize(&c);
|
|
|
|
struct {
|
|
u64 magic;
|
|
u64 cmd_id;
|
|
HidsysNotificationLedPattern pattern;
|
|
u64 UniquePadId;
|
|
} *raw;
|
|
|
|
raw = serviceIpcPrepareHeader(&g_hidsysSrv, &c, sizeof(*raw));
|
|
|
|
raw->magic = SFCI_MAGIC;
|
|
raw->cmd_id = 830;
|
|
memcpy(&raw->pattern, pattern, sizeof(*pattern));
|
|
raw->UniquePadId = UniquePadId;
|
|
|
|
rc = serviceIpcDispatch(&g_hidsysSrv);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
IpcParsedCommand r;
|
|
struct {
|
|
u64 magic;
|
|
u64 result;
|
|
} *resp;
|
|
|
|
serviceIpcParse(&g_hidsysSrv, &r, sizeof(*resp));
|
|
resp = r.Raw;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|