Added nfp:user services wrappers. (#237)

* hid: move official/libnx controller converters to hid.h
This commit is contained in:
averne 2019-02-16 03:06:41 +09:00 committed by fincs
parent 17731d750e
commit 7d9601810d
5 changed files with 952 additions and 7 deletions

View File

@ -83,6 +83,7 @@ extern "C" {
#include "switch/services/psc.h"
#include "switch/services/caps.h"
#include "switch/services/capssu.h"
#include "switch/services/nfc.h"
#include "switch/display/binder.h"
#include "switch/display/parcel.h"

View File

@ -600,6 +600,18 @@ typedef struct HidVibrationValue
float freq_high; ///< High Band frequency in Hz.
} HidVibrationValue;
static inline u32 hidControllerIDToOfficial(HidControllerID id) {
if (id < CONTROLLER_HANDHELD) return id;
if (id == CONTROLLER_HANDHELD) return 0x20;
return 0x10;//For CONTROLLER_UNKNOWN and invalid values return this.
}
static inline HidControllerID hidControllerIDFromOfficial(u32 id) {
if (id < 8) return (HidControllerID)id;
if (id == 0x20) return CONTROLLER_HANDHELD;
return CONTROLLER_UNKNOWN;
}
Result hidInitialize(void);
void hidExit(void);
void hidReset(void);

View File

@ -0,0 +1,167 @@
/**
* @file nfc.h
* @brief Nintendo Figurine (amiibo) Platform (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?
u16 mii_name[10+1]; ///< utf-16be, null-terminated
u8 unk_x26;
u8 mii_color;
u8 mii_sex;
u8 mii_height;
u8 mii_width;
u8 unk_x2b[2];
u8 mii_face_shape;
u8 mii_face_color;
u8 mii_wrinkles_style;
u8 mii_makeup_style;
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_x57;
} PACKED NfpuMiiCharInfo;
typedef struct {
NfpuMiiCharInfo mii;
u16 first_write_year;
u8 first_write_month;
u8 first_write_day;
char amiibo_name[10+1]; ///< utf-8, null-terminated
u8 reserved[0x99];
} PACKED NfpuRegisterInfo;
typedef struct {
u64 unk1;
u64 reserved1[3];
u64 unk2;
u64 reserved2[3];
} NfpuInitConfig;
typedef enum {
NfpuState_NonInitialized = 0,
NfpuState_Initialized = 1,
} NfpuState;
typedef enum {
NfpuDeviceState_Initialized = 0,
NfpuDeviceState_SearchingForTag = 1,
NfpuDeviceState_TagFound = 2,
NfpuDeviceState_TagRemoved = 3,
NfpuDeviceState_TagMounted = 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;
Result nfpuInitialize(const NfpuInitConfig *config);
void nfpuExit(void);
Service* nfpuGetInterface(void);
Result nfpuStartDetection(HidControllerID id);
Result nfpuStopDetection(HidControllerID id);
/// Returned event will have autoclear off.
Result nfpuAttachActivateEvent(HidControllerID id, Event *out);
/// Returned event will have autoclear off.
Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out);
/// Returned event will have autoclear on.
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);
Result nfpuOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id);
Result nfpuGetApplicationArea(HidControllerID id, void* buf, size_t buf_size);
Result nfpuSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size);
Result nfpuCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size);
Result nfpuFlush(HidControllerID id);
Result nfpuRestore(HidControllerID id);
/// Calls nfc:user.
Result nfpuIsNfcEnabled(bool *out);

View File

@ -154,12 +154,6 @@ void hidReset(void)
rwlockWriteUnlock(&g_hidLock);
}
static u32 _hidControllerIDToOfficial(HidControllerID id) {
if (id < CONTROLLER_HANDHELD) return id;
if (id == CONTROLLER_HANDHELD) return 0x20;
return 0x10;//For CONTROLLER_UNKNOWN and invalid values return this.
}
Service* hidGetSessionService(void) {
return &g_hidSrv;
}
@ -857,7 +851,7 @@ Result hidAcquireNpadStyleSetUpdateEventHandle(HidControllerID id, Event* event,
raw->magic = SFCI_MAGIC;
raw->cmd_id = 106;
raw->id = _hidControllerIDToOfficial(id);
raw->id = hidControllerIDToOfficial(id);
raw->AppletResourceUserId = AppletResourceUserId;
raw->event_ptr = 0;//Official sw sets this to a ptr, which the sysmodule doesn't seem to use.

771
nx/source/services/nfc.c Normal file
View File

@ -0,0 +1,771 @@
#include <string.h>
#include "types.h"
#include "arm/atomics.h"
#include "kernel/detect.h"
#include "services/hid.h"
#include "services/applet.h"
#include "services/nfc.h"
static u64 g_refCnt;
static Service g_nfpuSrv;
static Service g_nfcuSrv;
static Service g_nfpuInterface;
static Service g_nfcuInterface;
// 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},
};
static Result _nfpuCreateInterface(Service* srv, Service* out);
static Result _nfpuInterfaceInitialize(Service* srv, u64 cmd_id, u64 aruid, const NfpuInitConfig *config);
static Result _nfpuInterfaceFinalize(Service* srv, u64 cmd_id);
static Result _nfpuInterfaceCmdNoInOut(Service* srv, u64 cmd_id);
static Result _nfpuInterfaceCmdInIdNoOut(Service* srv, u64 cmd_id, HidControllerID id);
static Result _nfpuInterfaceCmdInIdOutEvent(Service* srv, u64 cmd_id, HidControllerID id, Event *out);
static Result _nfpuInterfaceCmdInIdOutBuffer(Service* srv, u64 cmd_id, HidControllerID id, void* buf, size_t buf_size);
Result nfpuInitialize(const NfpuInitConfig *config) {
atomicIncrement64(&g_refCnt);
if (serviceIsActive(&g_nfpuInterface) && serviceIsActive(&g_nfcuInterface))
return 0;
if (config == NULL)
config = &g_nfpuDefaultInitConfig;
// If this fails (for example because we're a sysmodule) aruid stays zero
u64 aruid = 0;
appletGetAppletResourceUserId(&aruid);
// nfp:user
Result rc = smGetService(&g_nfpuSrv, "nfp:user");
if (R_SUCCEEDED(rc))
rc = serviceConvertToDomain(&g_nfpuSrv);
if (R_SUCCEEDED(rc))
rc = _nfpuCreateInterface(&g_nfpuSrv, &g_nfpuInterface);
if (R_SUCCEEDED(rc))
rc = _nfpuInterfaceInitialize(&g_nfpuInterface, 0, aruid, config);
// nfc:user
if (R_SUCCEEDED(rc))
rc = smGetService(&g_nfcuSrv, "nfc:user");
if (R_SUCCEEDED(rc))
rc = serviceConvertToDomain(&g_nfcuSrv);
if (R_SUCCEEDED(rc))
rc = _nfpuCreateInterface(&g_nfcuSrv, &g_nfcuInterface);
if (R_SUCCEEDED(rc))
rc = _nfpuInterfaceInitialize(&g_nfcuInterface, kernelAbove400() ? 0 : 400, aruid, config);
if (R_FAILED(rc))
nfpuExit();
return rc;
}
void nfpuExit(void) {
if (atomicDecrement64(&g_refCnt) == 0) {
_nfpuInterfaceFinalize(&g_nfpuInterface, 1);
_nfpuInterfaceFinalize(&g_nfcuInterface, kernelAbove400() ? 1 : 401);
serviceClose(&g_nfpuInterface);
serviceClose(&g_nfcuInterface);
serviceClose(&g_nfpuSrv);
serviceClose(&g_nfcuSrv);
}
}
Service* nfpuGetInterface(void) {
return &g_nfpuInterface;
}
static Result _nfpuCreateInterface(Service* srv, Service* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc))
serviceCreateSubservice(out, srv, &r, 0);
}
return rc;
}
static Result _nfpuInterfaceCmdNoInOut(Service* srv, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _nfpuInterfaceCmdInIdNoOut(Service* srv, u64 cmd_id, HidControllerID id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
raw->id = hidControllerIDToOfficial(id);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _nfpuInterfaceCmdInIdOutEvent(Service* srv, u64 cmd_id, HidControllerID id, Event *out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
raw->id = hidControllerIDToOfficial(id);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc))
eventLoadRemote(out, r.Handles[0], false);
}
return rc;
}
static Result _nfpuInterfaceCmdInIdOutBuffer(Service* srv, u64 cmd_id, HidControllerID id, void* buf, size_t buf_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvStatic(&c, buf, buf_size, 0);
struct {
u64 magic;
u64 cmd_id;
u64 id;
} *raw;
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
raw->id = hidControllerIDToOfficial(id);
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _nfpuInterfaceInitialize(Service* srv, u64 cmd_id, 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(srv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
raw->aruid = aruid;
raw->zero = 0;
Result rc = serviceIpcDispatch(srv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(srv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
static Result _nfpuInterfaceFinalize(Service* srv, u64 cmd_id) {
return _nfpuInterfaceCmdNoInOut(srv, cmd_id);
}
Result nfpuStartDetection(HidControllerID id) {
return _nfpuInterfaceCmdInIdNoOut(&g_nfpuInterface, 3, id);
}
Result nfpuStopDetection(HidControllerID id) {
return _nfpuInterfaceCmdInIdNoOut(&g_nfpuInterface, 4, id);
}
Result nfpuAttachActivateEvent(HidControllerID id, Event *out) {
return _nfpuInterfaceCmdInIdOutEvent(&g_nfpuInterface, 17, id, out);
}
Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out) {
return _nfpuInterfaceCmdInIdOutEvent(&g_nfpuInterface, 18, id, out);
}
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], true);
}
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) {
// This is the maximum number of controllers that can be connected to a console at a time
// Incidentally, this is the biggest value official software (SSBU) was observed using
size_t max_controllers = 9;
if (num_elements > max_controllers)
num_elements = max_controllers;
IpcCommand c;
ipcInitialize(&c);
u64 buf[max_controllers];
memset(buf, 0, max_controllers * sizeof(u64));
ipcAddRecvStatic(&c, buf, max_controllers * sizeof(u64), 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)
*count = resp->count;
if (R_SUCCEEDED(rc) && out) {
for (size_t i=0; i<num_elements; i++)
out[i] = hidControllerIDFromOfficial(buf[i]);
}
}
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;
}
Result nfpuUnmount(HidControllerID id) {
return _nfpuInterfaceCmdInIdNoOut(&g_nfpuInterface, 6, id);
}
Result nfpuGetTagInfo(HidControllerID id, NfpuTagInfo *out) {
return _nfpuInterfaceCmdInIdOutBuffer(&g_nfpuInterface, 13, id, out, sizeof(NfpuTagInfo));
}
Result nfpuGetRegisterInfo(HidControllerID id, NfpuRegisterInfo *out) {
return _nfpuInterfaceCmdInIdOutBuffer(&g_nfpuInterface, 14, id, out, sizeof(NfpuRegisterInfo));
}
Result nfpuGetCommonInfo(HidControllerID id, NfpuCommonInfo *out) {
return _nfpuInterfaceCmdInIdOutBuffer(&g_nfpuInterface, 15, id, out, sizeof(NfpuCommonInfo));
}
Result nfpuGetModelInfo(HidControllerID id, NfpuModelInfo *out) {
return _nfpuInterfaceCmdInIdOutBuffer(&g_nfpuInterface, 16, id, out, sizeof(NfpuModelInfo));
}
Result nfpuOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 id;
u32 app_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 7;
raw->id = hidControllerIDToOfficial(id);
raw->app_id = app_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) && npad_id)
*npad_id = resp->npad_id;
}
return rc;
}
Result nfpuGetApplicationArea(HidControllerID id, void* buf, size_t buf_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buf, buf_size, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u64 id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
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;
}
Result nfpuSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buf, buf_size, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u64 id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 9;
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;
}
Result nfpuCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buf, buf_size, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
u64 id;
u32 app_id;
} PACKED *raw;
raw = serviceIpcPrepareHeader(&g_nfpuInterface, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 12;
raw->id = hidControllerIDToOfficial(id);
raw->app_id = app_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;
}
Result nfpuFlush(HidControllerID id) {
return _nfpuInterfaceCmdInIdNoOut(&g_nfpuInterface, 10, id);
}
Result nfpuRestore(HidControllerID id) {
return _nfpuInterfaceCmdInIdNoOut(&g_nfpuInterface, 11, id);
}
Result nfpuIsNfcEnabled(bool *out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nfcuInterface, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = kernelAbove200() ? 3 : 403;
Result rc = serviceIpcDispatch(&g_nfcuInterface);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u8 flag;
} *resp;
serviceIpcParse(&g_nfcuInterface, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out)
*out = !!resp->flag;
}
return rc;
}