mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-05 02:52:13 +02:00
Added nfp:user services wrappers.
This commit is contained in:
parent
17731d750e
commit
47a950d9b4
@ -83,6 +83,7 @@ extern "C" {
|
||||
#include "switch/services/psc.h"
|
||||
#include "switch/services/caps.h"
|
||||
#include "switch/services/capssu.h"
|
||||
#include "switch/services/nfpu.h"
|
||||
|
||||
#include "switch/display/binder.h"
|
||||
#include "switch/display/parcel.h"
|
||||
|
148
nx/include/switch/services/nfpu.h
Normal file
148
nx/include/switch/services/nfpu.h
Normal file
@ -0,0 +1,148 @@
|
||||
/**
|
||||
* @file nfpu.h
|
||||
* @brief Near Field Proximity (nfp:user) service IPC wrapper.
|
||||
* @author averne
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
#include "../services/hid.h"
|
||||
|
||||
typedef struct {
|
||||
u8 uuid[10];
|
||||
u8 uuid_length;
|
||||
u8 reserved1[0x15];
|
||||
u32 protocol;
|
||||
u32 tag_type;
|
||||
u8 reserved2[0x30];
|
||||
} PACKED NfpuTagInfo;
|
||||
|
||||
typedef struct {
|
||||
u16 last_write_year;
|
||||
u8 last_write_month;
|
||||
u8 last_write_day;
|
||||
u16 write_counter;
|
||||
u16 version;
|
||||
u32 application_area_size;
|
||||
u8 reserved[0x34];
|
||||
} PACKED NfpuCommonInfo;
|
||||
|
||||
typedef struct {
|
||||
u8 amiibo_id[0x8];
|
||||
u8 reserved[0x38];
|
||||
} PACKED NfpuModelInfo;
|
||||
|
||||
typedef struct {
|
||||
u8 unk_x0[0x10]; // Hash?
|
||||
u8 mii_name[2*(10+1)]; ///< utf-16be, null-terminated
|
||||
u8 unk_x26;
|
||||
u8 mii_color;
|
||||
u8 mii_sex;
|
||||
u8 mii_height;
|
||||
u8 mii_width;
|
||||
u8 unk_x1b[2];
|
||||
u8 mii_face_shape;
|
||||
u8 mii_face_color;
|
||||
u8 mii_wrinkles;
|
||||
u8 mii_makeup;
|
||||
u8 mii_hair_style;
|
||||
u8 mii_hair_color;
|
||||
u8 mii_has_hair_flipped;
|
||||
u8 mii_eye_style;
|
||||
u8 mii_eye_color;
|
||||
u8 mii_eye_size;
|
||||
u8 mii_eye_thickness;
|
||||
u8 mii_eye_angle;
|
||||
u8 mii_eye_pos_x;
|
||||
u8 mii_eye_pos_y;
|
||||
u8 mii_eyebrow_style;
|
||||
u8 mii_eyebrow_color;
|
||||
u8 mii_eyebrow_size;
|
||||
u8 mii_eyebrow_thickness;
|
||||
u8 mii_eyebrow_angle;
|
||||
u8 mii_eyebrow_pos_x;
|
||||
u8 mii_eyebrow_pos_y;
|
||||
u8 mii_nose_style;
|
||||
u8 mii_nose_size;
|
||||
u8 mii_nose_pos;
|
||||
u8 mii_mouth_style;
|
||||
u8 mii_mouth_color;
|
||||
u8 mii_mouth_size;
|
||||
u8 mii_mouth_thickness;
|
||||
u8 mii_mouth_pos;
|
||||
u8 mii_facial_hair_color;
|
||||
u8 mii_beard_style;
|
||||
u8 mii_mustache_style;
|
||||
u8 mii_mustache_size;
|
||||
u8 mii_mustache_pos;
|
||||
u8 mii_glasses_style;
|
||||
u8 mii_glasses_color;
|
||||
u8 mii_glasses_size;
|
||||
u8 mii_glasses_pos;
|
||||
u8 mii_has_mole;
|
||||
u8 mii_mole_size;
|
||||
u8 mii_mole_pos_x;
|
||||
u8 mii_mole_pos_y;
|
||||
u8 unk_x46[5]; // Zero + Mii ID?
|
||||
char amiibo_name[10+1]; ///< utf-8, null-terminated
|
||||
u8 reserved[0x99];
|
||||
} PACKED NfpuRegisterInfo;
|
||||
|
||||
typedef enum {
|
||||
NfpuState_NonInitialized = 0,
|
||||
NfpuState_Initialized = 1,
|
||||
} NfpuState;
|
||||
|
||||
typedef enum {
|
||||
NfpuDeviceState_Initialized = 0,
|
||||
NfpuDeviceState_SearchingForTag = 1,
|
||||
NfpuDeviceState_TagFound = 2,
|
||||
NfpuDeviceState_TagRemoved = 3,
|
||||
NfpuDeviceState_TagNearby = 4,
|
||||
NfpuDeviceState_Unavailable = 5,
|
||||
NfpuDeviceState_Finalized = 6,
|
||||
} NfpuDeviceState;
|
||||
|
||||
typedef enum {
|
||||
NfpuDeviceType_Amiibo = 0,
|
||||
} NfpuDeviceType;
|
||||
|
||||
typedef enum {
|
||||
NfpuMountTarget_Rom = 1,
|
||||
NfpuMountTarget_Ram = 2,
|
||||
NfpuMountTarget_All = 3,
|
||||
} NfpuMountTarget;
|
||||
|
||||
typedef struct {
|
||||
u64 unk1;
|
||||
u64 reserved1[3];
|
||||
u64 unk2;
|
||||
u64 reserved2[3];
|
||||
} NfpuInitConfig;
|
||||
|
||||
const NfpuInitConfig *nfpuGetDefaultInitConfig(void);
|
||||
|
||||
Result nfpuInitialize(void);
|
||||
void nfpuExit(void);
|
||||
Service *nfpuGetInterface(void);
|
||||
|
||||
Result nfpuStartDetection(HidControllerID id);
|
||||
Result nfpuStopDetection(HidControllerID id);
|
||||
|
||||
Result nfpuAttachActivateEvent(HidControllerID id, Event *out);
|
||||
Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out);
|
||||
Result nfpuAttachAvailabilityChangeEvent(Event *out);
|
||||
|
||||
Result nfpuGetState(NfpuState *out);
|
||||
Result nfpuGetDeviceState(HidControllerID id, NfpuDeviceState *out);
|
||||
Result nfpuListDevices(u32 *count, HidControllerID *out, size_t num_elements);
|
||||
Result nfpuGetNpadId(HidControllerID id, u32 *out);
|
||||
|
||||
Result nfpuMount(HidControllerID id, NfpuDeviceType device_type, NfpuMountTarget mount_target);
|
||||
Result nfpuUnmount(HidControllerID id);
|
||||
|
||||
Result nfpuGetTagInfo(HidControllerID id, NfpuTagInfo *out);
|
||||
Result nfpuGetRegisterInfo(HidControllerID id, NfpuRegisterInfo *out);
|
||||
Result nfpuGetCommonInfo(HidControllerID id, NfpuCommonInfo *out);
|
||||
Result nfpuGetModelInfo(HidControllerID id, NfpuModelInfo *out);
|
568
nx/source/services/nfpu.c
Normal file
568
nx/source/services/nfpu.c
Normal file
@ -0,0 +1,568 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "arm/atomics.h"
|
||||
#include "services/hid.h"
|
||||
#include "services/applet.h"
|
||||
#include "services/nfpu.h"
|
||||
|
||||
static u64 g_refCnt;
|
||||
static Service g_nfpuSrv;
|
||||
static Service g_nfpuInterface;
|
||||
|
||||
static Result _nfpuCreateInterface(void);
|
||||
static Result _nfpuInterfaceInitialize(u64 aruid, const NfpuInitConfig *config);
|
||||
static Result _nfpuInterfaceFinalize(void);
|
||||
|
||||
static Result _nfpuInterfaceCmdNoInOut(u64 cmd_id);
|
||||
static Result _nfpuInterfaceCmdInIdNoOut(HidControllerID id, u64 cmd_id);
|
||||
static Result _nfpuInterfaceCmdInIdOutEvent(HidControllerID id, Event *out, u64 cmd_id);
|
||||
static Result _nfpuInterfaceCmdInIdOutBuffer(HidControllerID id, void *buf, size_t buf_size, u64 cmd_id);
|
||||
|
||||
static Result _nfpuInterfaceInitialize(u64 aruid, const NfpuInitConfig *config);
|
||||
static Result _nfpuInterfaceFinalize(void);
|
||||
|
||||
|
||||
// This is the data passed by every application this was tested with
|
||||
static const NfpuInitConfig g_nfpuDefaultInitConfig = {
|
||||
.unk1 = 0x00000001000a0003,
|
||||
.reserved1 = {0},
|
||||
.unk2 = 0x0000000300040003,
|
||||
.reserved2 = {0},
|
||||
};
|
||||
|
||||
const NfpuInitConfig *nfpuGetDefaultInitConfig(void) {
|
||||
return &g_nfpuDefaultInitConfig;
|
||||
}
|
||||
|
||||
Result nfpuInitialize(void) {
|
||||
atomicIncrement64(&g_refCnt);
|
||||
|
||||
if (serviceIsActive(&g_nfpuInterface))
|
||||
return 0;
|
||||
|
||||
// If this fails (for example because we're a sysmodule) aruid stays zero
|
||||
u64 aruid = 0;
|
||||
appletGetAppletResourceUserId(&aruid);
|
||||
|
||||
Result rc = smGetService(&g_nfpuSrv, "nfp:user");
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = serviceConvertToDomain(&g_nfpuSrv);
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = _nfpuCreateInterface();
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = _nfpuInterfaceInitialize(aruid, &g_nfpuDefaultInitConfig);
|
||||
|
||||
if (R_FAILED(rc))
|
||||
nfpuExit();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void nfpuExit(void) {
|
||||
if (atomicDecrement64(&g_refCnt) == 0) {
|
||||
_nfpuInterfaceFinalize();
|
||||
serviceClose(&g_nfpuInterface);
|
||||
serviceClose(&g_nfpuSrv);
|
||||
}
|
||||
}
|
||||
|
||||
Service *nfpuGetInterface(void) {
|
||||
return &g_nfpuInterface;
|
||||
}
|
||||
|
||||
static Result _nfpuCreateInterface(void) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuSrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 0;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuSrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuSrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
serviceCreateSubservice(&g_nfpuInterface, &g_nfpuSrv, &r, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32 _hidControllerIDToOfficial(HidControllerID id) {
|
||||
if (id < CONTROLLER_HANDHELD) return id;
|
||||
if (id == CONTROLLER_HANDHELD) return 0x20;
|
||||
return 0x10;
|
||||
}
|
||||
|
||||
static HidControllerID _hidOfficialToControllerID(u64 id) {
|
||||
if (id < 8) return id;
|
||||
if (id == 0x20) return CONTROLLER_HANDHELD;
|
||||
return CONTROLLER_UNKNOWN;
|
||||
}
|
||||
|
||||
static Result _nfpuInterfaceCmdNoInOut(u64 cmd_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = cmd_id;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _nfpuInterfaceCmdInIdNoOut(HidControllerID id, u64 cmd_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = cmd_id;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _nfpuInterfaceCmdInIdOutEvent(HidControllerID id, Event *out, u64 cmd_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = cmd_id;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
eventLoadRemote(out, r.Handles[0], true);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _nfpuInterfaceCmdInIdOutBuffer(HidControllerID id, void *buf, size_t buf_size, u64 cmd_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
ipcAddRecvStatic(&c, buf, buf_size, 0);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = cmd_id;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _nfpuInterfaceInitialize(u64 aruid, const NfpuInitConfig *config) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
ipcAddSendBuffer(&c, config, sizeof(NfpuInitConfig), BufferType_Normal);
|
||||
ipcSendPid(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 aruid;
|
||||
u64 zero;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 0;
|
||||
raw->aruid = aruid;
|
||||
raw->zero = 0;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline Result _nfpuInterfaceFinalize(void) {
|
||||
return _nfpuInterfaceCmdNoInOut(1);
|
||||
}
|
||||
|
||||
inline Result nfpuStartDetection(HidControllerID id) {
|
||||
return _nfpuInterfaceCmdInIdNoOut(id, 3);
|
||||
}
|
||||
|
||||
inline Result nfpuStopDetection(HidControllerID id) {
|
||||
return _nfpuInterfaceCmdInIdNoOut(id, 4);
|
||||
}
|
||||
|
||||
inline Result nfpuAttachActivateEvent(HidControllerID id, Event *out) {
|
||||
return _nfpuInterfaceCmdInIdOutEvent(id, out, 17);
|
||||
}
|
||||
|
||||
inline Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out) {
|
||||
return _nfpuInterfaceCmdInIdOutEvent(id, out, 18);
|
||||
}
|
||||
|
||||
Result nfpuAttachAvailabilityChangeEvent(Event *out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 23;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
eventLoadRemote(out, r.Handles[0], false);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result nfpuGetState(NfpuState *out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 19;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 state;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && out)
|
||||
*out = resp->state;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result nfpuGetDeviceState(HidControllerID id, NfpuDeviceState *out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 20;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 state;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && out)
|
||||
*out = resp->state;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result nfpuListDevices(u32 *count, HidControllerID *out, size_t num_elements) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
size_t buf_size = num_elements * sizeof(u64);
|
||||
u64 *buf = malloc(buf_size);
|
||||
ipcAddRecvStatic(&c, buf, buf_size, 0);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 2;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 count;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
if (R_SUCCEEDED(rc) && count && out) {
|
||||
*count = resp->count;
|
||||
for (u32 i=0; i<resp->count; i++)
|
||||
out[i] = _hidOfficialToControllerID(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result nfpuGetNpadId(HidControllerID id, u32 *out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 21;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 npad_id;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc) && out)
|
||||
*out = resp->npad_id;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result nfpuMount(HidControllerID id, NfpuDeviceType device_type, NfpuMountTarget mount_target) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 id;
|
||||
u32 device_type;
|
||||
u32 mount_target;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 5;
|
||||
raw->id = _hidControllerIDToOfficial(id);
|
||||
raw->device_type = device_type;
|
||||
raw->mount_target = mount_target;
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nfpuInterface);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nfpuInterface, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
inline Result nfpuUnmount(HidControllerID id) {
|
||||
return _nfpuInterfaceCmdInIdNoOut(id, 6);
|
||||
}
|
||||
|
||||
inline Result nfpuGetTagInfo(HidControllerID id, NfpuTagInfo *out) {
|
||||
return _nfpuInterfaceCmdInIdOutBuffer(id, out, sizeof(NfpuTagInfo), 13);
|
||||
}
|
||||
|
||||
inline Result nfpuGetRegisterInfo(HidControllerID id, NfpuRegisterInfo *out) {
|
||||
return _nfpuInterfaceCmdInIdOutBuffer(id, out, sizeof(NfpuRegisterInfo), 14);
|
||||
}
|
||||
|
||||
inline Result nfpuGetCommonInfo(HidControllerID id, NfpuCommonInfo *out) {
|
||||
return _nfpuInterfaceCmdInIdOutBuffer(id, out, sizeof(NfpuCommonInfo), 15);
|
||||
}
|
||||
|
||||
inline Result nfpuGetModelInfo(HidControllerID id, NfpuModelInfo *out) {
|
||||
return _nfpuInterfaceCmdInIdOutBuffer(id, out, sizeof(NfpuModelInfo), 16);
|
||||
}
|
Loading…
Reference in New Issue
Block a user