Changed the nfpu prefix to nfp. Changed the nfcu prefix to nfc. Renamed nfpuIsNfcEnabled to nfcIsNfcEnabled. Added nfpSetServiceType/nfcSetServiceType and the enums for it. Moved nfc service init/exit into seperate funcs nfcInitialize/nfcExit. Renamed NfpuInitConfig to NfcRequiredMcuVersionData, removed it from nfpInitialize() input, and handle it properly as an array. Minor other changes.

This commit is contained in:
yellows8 2019-10-13 19:20:34 -04:00
parent 1a0b5569ab
commit 67ccc66f15
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 285 additions and 188 deletions

View File

@ -10,6 +10,46 @@
#include "../sf/service.h" #include "../sf/service.h"
#include "../services/hid.h" #include "../services/hid.h"
/// NfpServiceType
typedef enum {
NfpServiceType_NotInitialized = 0, ///< Same as ::NfpServiceType_User during \ref nfpInitialize.
NfpServiceType_User = 1, ///< Initializes nfp:user.
NfpServiceType_Debug = 2, ///< Initializes nfp:dbg.
NfpServiceType_System = 3, ///< Initializes nfp:sys.
} NfpServiceType;
/// NfcServiceType
typedef enum {
NfcServiceType_NotInitialized = 0, ///< Same as ::NfcServiceType_User during \ref nfcInitialize.
NfcServiceType_User = 1, ///< Initializes nfc:user.
NfcServiceType_System = 3, ///< Initializes nfc:sys.
} NfcServiceType;
typedef enum {
NfpState_NonInitialized = 0,
NfpState_Initialized = 1,
} NfpState;
typedef enum {
NfpDeviceState_Initialized = 0,
NfpDeviceState_SearchingForTag = 1,
NfpDeviceState_TagFound = 2,
NfpDeviceState_TagRemoved = 3,
NfpDeviceState_TagMounted = 4,
NfpDeviceState_Unavailable = 5,
NfpDeviceState_Finalized = 6,
} NfpDeviceState;
typedef enum {
NfpDeviceType_Amiibo = 0,
} NfpDeviceType;
typedef enum {
NfpMountTarget_Rom = 1,
NfpMountTarget_Ram = 2,
NfpMountTarget_All = 3,
} NfpMountTarget;
typedef struct { typedef struct {
u8 uuid[10]; u8 uuid[10];
u8 uuid_length; u8 uuid_length;
@ -17,7 +57,7 @@ typedef struct {
u32 protocol; u32 protocol;
u32 tag_type; u32 tag_type;
u8 reserved2[0x30]; u8 reserved2[0x30];
} PACKED NfpuTagInfo; } PACKED NfpTagInfo;
typedef struct { typedef struct {
u16 last_write_year; u16 last_write_year;
@ -27,12 +67,12 @@ typedef struct {
u16 version; u16 version;
u32 application_area_size; u32 application_area_size;
u8 reserved[0x34]; u8 reserved[0x34];
} PACKED NfpuCommonInfo; } PACKED NfpCommonInfo;
typedef struct { typedef struct {
u8 amiibo_id[0x8]; u8 amiibo_id[0x8];
u8 reserved[0x38]; u8 reserved[0x38];
} PACKED NfpuModelInfo; } PACKED NfpModelInfo;
typedef struct { typedef struct {
u8 unk_x0[0x10]; // Hash? u8 unk_x0[0x10]; // Hash?
@ -86,97 +126,95 @@ typedef struct {
u8 mii_mole_pos_x; u8 mii_mole_pos_x;
u8 mii_mole_pos_y; u8 mii_mole_pos_y;
u8 unk_x57; u8 unk_x57;
} PACKED NfpuMiiCharInfo; } PACKED NfpMiiCharInfo;
typedef struct { typedef struct {
NfpuMiiCharInfo mii; NfpMiiCharInfo mii;
u16 first_write_year; u16 first_write_year;
u8 first_write_month; u8 first_write_month;
u8 first_write_day; u8 first_write_day;
char amiibo_name[10+1]; ///< utf-8, null-terminated char amiibo_name[10+1]; ///< utf-8, null-terminated
u8 reserved[0x99]; u8 reserved[0x99];
} PACKED NfpuRegisterInfo; } PACKED NfpRegisterInfo;
typedef struct { typedef struct {
u64 unk1; u64 version;
u64 reserved1[3]; u64 reserved[3];
u64 unk2; } NfcRequiredMcuVersionData;
u64 reserved2[3];
} NfpuInitConfig;
typedef enum { /**
NfpuState_NonInitialized = 0, * @brief Sets the \ref NfpServiceType for initialization. Call this function before \ref nfpInitialize, if needed.
NfpuState_Initialized = 1, * @note By default ::NfpServiceType_NotInitialized will be used.
} NfpuState; */
void nfpSetServiceType(NfpServiceType serviceType);
typedef enum { /**
NfpuDeviceState_Initialized = 0, * @brief Sets the \ref NfcServiceType for initialization. Call this function before \ref nfcInitialize, if needed.
NfpuDeviceState_SearchingForTag = 1, * @note By default ::NfcServiceType_NotInitialized will be used.
NfpuDeviceState_TagFound = 2, */
NfpuDeviceState_TagRemoved = 3, void nfcSetServiceType(NfcServiceType serviceType);
NfpuDeviceState_TagMounted = 4,
NfpuDeviceState_Unavailable = 5,
NfpuDeviceState_Finalized = 6,
} NfpuDeviceState;
typedef enum { /// Initialize nfp:*.
NfpuDeviceType_Amiibo = 0, Result nfpInitialize(void);
} NfpuDeviceType;
typedef enum { /// Exit nfp:*.
NfpuMountTarget_Rom = 1, void nfpExit(void);
NfpuMountTarget_Ram = 2,
NfpuMountTarget_All = 3,
} NfpuMountTarget;
/// Initialize nfp:user and nfc:user. /// Initialize nfc:*.
Result nfpuInitialize(const NfpuInitConfig *config); Result nfcInitialize(void);
/// Exit nfp:user and nfc:user. /// Exit nfc:*..
void nfpuExit(void); void nfcExit(void);
/// Gets the Service object for the actual nfp:user service session. /// Gets the Service object for the actual nfp:* service session.
Service* nfpuGetServiceSession(void); Service* nfpGetServiceSession(void);
/// Gets the Service object for the interface from nfp:user. /// Gets the Service object for the interface from nfp:*.
Service* nfpuGetServiceSession_Interface(void); Service* nfpGetServiceSession_Interface(void);
/// Gets the Service object for the actual nfc:user service session. /// Gets the Service object for the actual nfc:* service session.
Service* nfcuGetServiceSession(void); Service* nfcGetServiceSession(void);
/// Gets the Service object for the interface from nfc:user. /// Gets the Service object for the interface from nfc:*.
Service* nfcuGetServiceSession_Interface(void); Service* nfcGetServiceSession_Interface(void);
Result nfpuListDevices(s32 *count, HidControllerID *out, size_t num_elements); Result nfpListDevices(s32 *count, HidControllerID *out, size_t num_elements);
Result nfpuStartDetection(HidControllerID id); Result nfpStartDetection(HidControllerID id);
Result nfpuStopDetection(HidControllerID id); Result nfpStopDetection(HidControllerID id);
Result nfpuMount(HidControllerID id, NfpuDeviceType device_type, NfpuMountTarget mount_target); Result nfpMount(HidControllerID id, NfpDeviceType device_type, NfpMountTarget mount_target);
Result nfpuUnmount(HidControllerID id); Result nfpUnmount(HidControllerID id);
Result nfpuOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id); /// Not available with ::NfpServiceType_System.
Result nfpuGetApplicationArea(HidControllerID id, void* buf, size_t buf_size); Result nfpOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id);
Result nfpuSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size);
Result nfpuFlush(HidControllerID id);
Result nfpuRestore(HidControllerID id);
Result nfpuCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size);
Result nfpuGetTagInfo(HidControllerID id, NfpuTagInfo *out); /// Not available with ::NfpServiceType_System.
Result nfpuGetRegisterInfo(HidControllerID id, NfpuRegisterInfo *out); Result nfpGetApplicationArea(HidControllerID id, void* buf, size_t buf_size);
Result nfpuGetCommonInfo(HidControllerID id, NfpuCommonInfo *out);
Result nfpuGetModelInfo(HidControllerID id, NfpuModelInfo *out); /// Not available with ::NfpServiceType_System.
Result nfpSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size);
Result nfpFlush(HidControllerID id);
Result nfpRestore(HidControllerID id);
/// Not available with ::NfpServiceType_System.
Result nfpCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size);
Result nfpGetTagInfo(HidControllerID id, NfpTagInfo *out);
Result nfpGetRegisterInfo(HidControllerID id, NfpRegisterInfo *out);
Result nfpGetCommonInfo(HidControllerID id, NfpCommonInfo *out);
Result nfpGetModelInfo(HidControllerID id, NfpModelInfo *out);
/// Returned event will have autoclear off. /// Returned event will have autoclear off.
Result nfpuAttachActivateEvent(HidControllerID id, Event *out_event); Result nfpAttachActivateEvent(HidControllerID id, Event *out_event);
/// Returned event will have autoclear off. /// Returned event will have autoclear off.
Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out_event); Result nfpAttachDeactivateEvent(HidControllerID id, Event *out_event);
Result nfpuGetState(NfpuState *out); Result nfpGetState(NfpState *out);
Result nfpuGetDeviceState(HidControllerID id, NfpuDeviceState *out); Result nfpGetDeviceState(HidControllerID id, NfpDeviceState *out);
Result nfpuGetNpadId(HidControllerID id, u32 *out); Result nfpGetNpadId(HidControllerID id, u32 *out);
/// Returned event will have autoclear on. /// Returned event will have autoclear on.
/// Only available with [3.0.0+]. /// Only available with [3.0.0+].
Result nfpuAttachAvailabilityChangeEvent(Event *out_event); Result nfpAttachAvailabilityChangeEvent(Event *out_event);
/// Calls nfc:user. /// This uses nfc:*.
Result nfpuIsNfcEnabled(bool *out); Result nfcIsNfcEnabled(bool *out);

View File

@ -5,92 +5,139 @@
#include "services/applet.h" #include "services/applet.h"
#include "services/nfc.h" #include "services/nfc.h"
static Service g_nfpuSrv; static NfpServiceType g_nfpServiceType = NfpServiceType_NotInitialized;
static Service g_nfcuSrv; static NfcServiceType g_nfcServiceType = NfcServiceType_NotInitialized;
static Service g_nfpuInterface; static Service g_nfpSrv;
static Service g_nfcuInterface; static Service g_nfpInterface;
static Service g_nfcSrv;
static Service g_nfcInterface;
// This is the data passed by every application this was tested with static const NfcRequiredMcuVersionData g_nfcVersionData[2] = {
static const NfpuInitConfig g_nfpuDefaultInitConfig = { {
.unk1 = 0x00000001000a0003, .version = 0x00000001000a0003,
.reserved1 = {0}, .reserved = {0},
.unk2 = 0x0000000300040003, },
.reserved2 = {0}, {
.version = 0x0000000300040003,
.reserved = {0},
},
}; };
static Result _nfpuCreateInterface(Service* srv, Service* srv_out); static Result _nfpCreateInterface(Service* srv, Service* srv_out);
static Result _nfpuInterfaceInitialize(Service* srv, u64 aruid, const NfpuInitConfig *config, u32 cmd_id); static Result _nfpInterfaceInitialize(Service* srv, u64 aruid, const NfcRequiredMcuVersionData *version, s32 count, u32 cmd_id);
static Result _nfpuInterfaceFinalize(Service* srv, u32 cmd_id); static Result _nfpInterfaceFinalize(Service* srv, u32 cmd_id);
static Result _nfpuCmdNoIO(Service* srv, u32 cmd_id); static Result _nfpCmdNoIO(Service* srv, u32 cmd_id);
static Result _nfpuCmdInIdNoOut(Service* srv, HidControllerID id, u32 cmd_id); static Result _nfpCmdInIdNoOut(Service* srv, HidControllerID id, u32 cmd_id);
static Result _nfpuCmdInIdOutEvent(Service* srv, HidControllerID id, Event *out_event, u32 cmd_id); static Result _nfpCmdInIdOutEvent(Service* srv, HidControllerID id, Event *out_event, u32 cmd_id);
static Result _nfpuCmdInIdOutBuffer(Service* srv, HidControllerID id, void* buf, size_t buf_size, u32 cmd_id); static Result _nfpCmdInIdOutBuffer(Service* srv, HidControllerID id, void* buf, size_t buf_size, u32 cmd_id);
NX_GENERATE_SERVICE_GUARD_PARAMS(nfpu, (const NfpuInitConfig *config), (config)); NX_GENERATE_SERVICE_GUARD(nfp);
Result _nfpuInitialize(const NfpuInitConfig *config) { void nfpSetServiceType(NfpServiceType serviceType) {
if (config == NULL) g_nfpServiceType = serviceType;
config = &g_nfpuDefaultInitConfig; }
void nfcSetServiceType(NfcServiceType serviceType) {
g_nfcServiceType = serviceType;
}
Result _nfpInitialize(void) {
Result rc=0;
u64 aruid = 0;
// If this fails (for example because we're a sysmodule) aruid stays zero // If this fails (for example because we're a sysmodule) aruid stays zero
u64 aruid = 0;
appletGetAppletResourceUserId(&aruid); appletGetAppletResourceUserId(&aruid);
// nfp:user switch (g_nfpServiceType) {
Result rc = smGetService(&g_nfpuSrv, "nfp:user"); case NfpServiceType_NotInitialized:
case NfpServiceType_User:
g_nfpServiceType = NfpServiceType_User;
rc = smGetService(&g_nfpSrv, "nfp:user");
break;
case NfpServiceType_Debug:
rc = smGetService(&g_nfpSrv, "nfp:dbg");
break;
case NfpServiceType_System:
rc = smGetService(&g_nfpSrv, "nfp:sys");
break;
}
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = serviceConvertToDomain(&g_nfpuSrv); rc = serviceConvertToDomain(&g_nfpSrv);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = _nfpuCreateInterface(&g_nfpuSrv, &g_nfpuInterface); rc = _nfpCreateInterface(&g_nfpSrv, &g_nfpInterface);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = _nfpuInterfaceInitialize(&g_nfpuInterface, aruid, config, 0); rc = _nfpInterfaceInitialize(&g_nfpInterface, aruid, g_nfcVersionData, 2, 0);
// 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, aruid, config, hosversionBefore(4,0,0) ? 0 : 400);
return rc; return rc;
} }
void _nfpuCleanup(void) { void _nfpCleanup(void) {
_nfpuInterfaceFinalize(&g_nfpuInterface, 1); _nfpInterfaceFinalize(&g_nfpInterface, 1);
_nfpuInterfaceFinalize(&g_nfcuInterface, hosversionBefore(4,0,0) ? 1 : 401); serviceClose(&g_nfpInterface);
serviceClose(&g_nfpuInterface); serviceClose(&g_nfpSrv);
serviceClose(&g_nfcuInterface); g_nfpServiceType = NfpServiceType_NotInitialized;
serviceClose(&g_nfpuSrv);
serviceClose(&g_nfcuSrv);
} }
Service* nfpuGetServiceSession(void) { NX_GENERATE_SERVICE_GUARD(nfc);
return &g_nfpuSrv;
Result _nfcInitialize(void) {
Result rc=0;
u64 aruid = 0;
// If this fails (for example because we're a sysmodule) aruid stays zero
appletGetAppletResourceUserId(&aruid);
switch (g_nfcServiceType) {
case NfcServiceType_NotInitialized:
case NfcServiceType_User:
g_nfcServiceType = NfcServiceType_User;
rc = smGetService(&g_nfcSrv, "nfc:user");
break;
case NfcServiceType_System:
rc = smGetService(&g_nfcSrv, "nfc:sys");
break;
}
if (R_SUCCEEDED(rc))
rc = serviceConvertToDomain(&g_nfcSrv);
if (R_SUCCEEDED(rc))
rc = _nfpCreateInterface(&g_nfcSrv, &g_nfcInterface);
if (R_SUCCEEDED(rc))
rc = _nfpInterfaceInitialize(&g_nfcInterface, aruid, g_nfcVersionData, 2, hosversionBefore(4,0,0) ? 0 : 400);
return rc;
} }
Service* nfpuGetServiceSession_Interface(void) { void _nfcCleanup(void) {
return &g_nfpuInterface; _nfpInterfaceFinalize(&g_nfcInterface, hosversionBefore(4,0,0) ? 1 : 401);
serviceClose(&g_nfcInterface);
serviceClose(&g_nfcSrv);
g_nfcServiceType = NfcServiceType_NotInitialized;
} }
Service* nfcuGetServiceSession(void) { Service* nfpGetServiceSession(void) {
return &g_nfpuSrv; return &g_nfpSrv;
} }
Service* nfcuGetServiceSession_Interface(void) { Service* nfpGetServiceSession_Interface(void) {
return &g_nfpuInterface; return &g_nfpInterface;
} }
static Result _nfpuCreateInterface(Service* srv, Service* srv_out) { Service* nfcGetServiceSession(void) {
return &g_nfpSrv;
}
Service* nfcGetServiceSession_Interface(void) {
return &g_nfpInterface;
}
static Result _nfpCreateInterface(Service* srv, Service* srv_out) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatch(srv, 0, return serviceDispatch(srv, 0,
.out_num_objects = 1, .out_num_objects = 1,
@ -98,7 +145,7 @@ static Result _nfpuCreateInterface(Service* srv, Service* srv_out) {
); );
} }
static Result _nfpuCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) { static Result _nfpCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id, return serviceDispatch(srv, cmd_id,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy }, .out_handle_attrs = { SfOutHandleAttr_HipcCopy },
@ -110,46 +157,46 @@ static Result _fpuCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u3
Handle tmp_handle = INVALID_HANDLE; Handle tmp_handle = INVALID_HANDLE;
Result rc = 0; Result rc = 0;
rc = _nfpuCmdGetHandle(srv, &tmp_handle, cmd_id); rc = _nfpCmdGetHandle(srv, &tmp_handle, cmd_id);
if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear);
return rc; return rc;
} }
static Result _nfpuCmdNoIO(Service* srv, u32 cmd_id) { static Result _nfpCmdNoIO(Service* srv, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatch(srv, cmd_id); return serviceDispatch(srv, cmd_id);
} }
static Result _nfpuCmdInIdNoOut(Service* srv, HidControllerID id, u32 cmd_id) { static Result _nfpCmdInIdNoOut(Service* srv, HidControllerID id, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
return serviceDispatchIn(srv, cmd_id, tmp); return serviceDispatchIn(srv, cmd_id, tmp);
} }
static Result _nfpuCmdInIdOutU32(Service* srv, HidControllerID id, u32 *out, u32 cmd_id) { static Result _nfpCmdInIdOutU32(Service* srv, HidControllerID id, u32 *out, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
return serviceDispatchInOut(srv, cmd_id, tmp, *out); return serviceDispatchInOut(srv, cmd_id, tmp, *out);
} }
static Result _nfpuCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { static Result _nfpCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *out); return serviceDispatchOut(srv, cmd_id, *out);
} }
static Result _nfpuCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) { static Result _nfpCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatchOut(srv, cmd_id, *out); return serviceDispatchOut(srv, cmd_id, *out);
} }
static Result _nfpuCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) { static Result _nfpCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) {
u8 tmp=0; u8 tmp=0;
Result rc = _nfpuCmdNoInOutU8(srv, &tmp, cmd_id); Result rc = _nfpCmdNoInOutU8(srv, &tmp, cmd_id);
if (R_SUCCEEDED(rc) && out) *out = tmp!=0; if (R_SUCCEEDED(rc) && out) *out = tmp!=0;
return rc; return rc;
} }
static Result _nfpuCmdInIdOutEvent(Service* srv, HidControllerID id, Event *out_event, u32 cmd_id) { static Result _nfpCmdInIdOutEvent(Service* srv, HidControllerID id, Event *out_event, u32 cmd_id) {
Handle tmp_handle = INVALID_HANDLE; Handle tmp_handle = INVALID_HANDLE;
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
@ -161,7 +208,7 @@ static Result _nfpuCmdInIdOutEvent(Service* srv, HidControllerID id, Event *out_
return rc; return rc;
} }
static Result _nfpuCmdInIdOutBuffer(Service* srv, HidControllerID id, void* buf, size_t buf_size, u32 cmd_id) { static Result _nfpCmdInIdOutBuffer(Service* srv, HidControllerID id, void* buf, size_t buf_size, u32 cmd_id) {
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, tmp, return serviceDispatchIn(srv, cmd_id, tmp,
@ -170,7 +217,7 @@ static Result _nfpuCmdInIdOutBuffer(Service* srv, HidControllerID id, void* buf,
); );
} }
static Result _nfpuInterfaceInitialize(Service* srv, u64 aruid, const NfpuInitConfig *config, u32 cmd_id) { static Result _nfpInterfaceInitialize(Service* srv, u64 aruid, const NfcRequiredMcuVersionData *version, s32 count, u32 cmd_id) {
const struct { const struct {
u64 aruid; u64 aruid;
u64 zero; u64 zero;
@ -179,16 +226,16 @@ static Result _nfpuInterfaceInitialize(Service* srv, u64 aruid, const NfpuInitCo
serviceAssumeDomain(srv); serviceAssumeDomain(srv);
return serviceDispatchIn(srv, cmd_id, in, return serviceDispatchIn(srv, cmd_id, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { config, sizeof(NfpuInitConfig) } }, .buffers = { { version, count*sizeof(NfcRequiredMcuVersionData) } },
.in_send_pid = true, .in_send_pid = true,
); );
} }
static Result _nfpuInterfaceFinalize(Service* srv, u32 cmd_id) { static Result _nfpInterfaceFinalize(Service* srv, u32 cmd_id) {
return _nfpuCmdNoIO(srv, cmd_id); return _nfpCmdNoIO(srv, cmd_id);
} }
Result nfpuListDevices(s32 *count, HidControllerID *out, size_t num_elements) { Result nfpListDevices(s32 *count, HidControllerID *out, size_t num_elements) {
// This is the maximum number of controllers that can be connected to a console at a time // 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 // Incidentally, this is the biggest value official software (SSBU) was observed using
size_t max_controllers = 9; size_t max_controllers = 9;
@ -198,8 +245,8 @@ Result nfpuListDevices(s32 *count, HidControllerID *out, size_t num_elements) {
u64 buf[max_controllers]; u64 buf[max_controllers];
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
Result rc = serviceDispatchOut(&g_nfpuInterface, 2, *count, Result rc = serviceDispatchOut(&g_nfpInterface, 2, *count,
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out },
.buffers = { { buf, max_controllers*sizeof(u64) } }, .buffers = { { buf, max_controllers*sizeof(u64) } },
); );
@ -210,127 +257,139 @@ Result nfpuListDevices(s32 *count, HidControllerID *out, size_t num_elements) {
return rc; return rc;
} }
Result nfpuStartDetection(HidControllerID id) { Result nfpStartDetection(HidControllerID id) {
return _nfpuCmdInIdNoOut(&g_nfpuInterface, id, 3); return _nfpCmdInIdNoOut(&g_nfpInterface, id, 3);
} }
Result nfpuStopDetection(HidControllerID id) { Result nfpStopDetection(HidControllerID id) {
return _nfpuCmdInIdNoOut(&g_nfpuInterface, id, 4); return _nfpCmdInIdNoOut(&g_nfpInterface, id, 4);
} }
Result nfpuMount(HidControllerID id, NfpuDeviceType device_type, NfpuMountTarget mount_target) { Result nfpMount(HidControllerID id, NfpDeviceType device_type, NfpMountTarget mount_target) {
const struct { const struct {
u64 id; u64 id;
u32 device_type; u32 device_type;
u32 mount_target; u32 mount_target;
} in = { hidControllerIDToOfficial(id), device_type, mount_target }; } in = { hidControllerIDToOfficial(id), device_type, mount_target };
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
return serviceDispatchIn(&g_nfpuInterface, 5, in); return serviceDispatchIn(&g_nfpInterface, 5, in);
} }
Result nfpuUnmount(HidControllerID id) { Result nfpUnmount(HidControllerID id) {
return _nfpuCmdInIdNoOut(&g_nfpuInterface, id, 6); return _nfpCmdInIdNoOut(&g_nfpInterface, id, 6);
} }
Result nfpuOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id) { Result nfpOpenApplicationArea(HidControllerID id, u32 app_id, u32 *npad_id) {
if (g_nfpServiceType == NfpServiceType_System)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
const struct { const struct {
u64 id; u64 id;
u32 app_id; u32 app_id;
} in = { hidControllerIDToOfficial(id), app_id }; } in = { hidControllerIDToOfficial(id), app_id };
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
return serviceDispatchInOut(&g_nfpuInterface, 7, in, *npad_id); return serviceDispatchInOut(&g_nfpInterface, 7, in, *npad_id);
} }
Result nfpuGetApplicationArea(HidControllerID id, void* buf, size_t buf_size) { Result nfpGetApplicationArea(HidControllerID id, void* buf, size_t buf_size) {
if (g_nfpServiceType == NfpServiceType_System)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
return serviceDispatchIn(&g_nfpuInterface, 8, tmp, return serviceDispatchIn(&g_nfpInterface, 8, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buf, buf_size } }, .buffers = { { buf, buf_size } },
); );
} }
Result nfpuSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size) { Result nfpSetApplicationArea(HidControllerID id, const void* buf, size_t buf_size) {
if (g_nfpServiceType == NfpServiceType_System)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
u64 tmp = hidControllerIDToOfficial(id); u64 tmp = hidControllerIDToOfficial(id);
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
return serviceDispatchIn(&g_nfpuInterface, 9, tmp, return serviceDispatchIn(&g_nfpInterface, 9, tmp,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { buf, buf_size } }, .buffers = { { buf, buf_size } },
); );
} }
Result nfpuFlush(HidControllerID id) { Result nfpFlush(HidControllerID id) {
return _nfpuCmdInIdNoOut(&g_nfpuInterface, id, 10); return _nfpCmdInIdNoOut(&g_nfpInterface, id, 10);
} }
Result nfpuRestore(HidControllerID id) { Result nfpRestore(HidControllerID id) {
return _nfpuCmdInIdNoOut(&g_nfpuInterface, id, 11); return _nfpCmdInIdNoOut(&g_nfpInterface, id, 11);
} }
Result nfpuCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size) { Result nfpCreateApplicationArea(HidControllerID id, u32 app_id, const void* buf, size_t buf_size) {
if (g_nfpServiceType == NfpServiceType_System)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
const struct { const struct {
u64 id; u64 id;
u32 app_id; u32 app_id;
} PACKED in = { hidControllerIDToOfficial(id), app_id }; } PACKED in = { hidControllerIDToOfficial(id), app_id };
serviceAssumeDomain(&g_nfpuInterface); serviceAssumeDomain(&g_nfpInterface);
return serviceDispatchIn(&g_nfpuInterface, 12, in, return serviceDispatchIn(&g_nfpInterface, 12, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { buf, buf_size } }, .buffers = { { buf, buf_size } },
); );
} }
Result nfpuGetTagInfo(HidControllerID id, NfpuTagInfo *out) { Result nfpGetTagInfo(HidControllerID id, NfpTagInfo *out) {
return _nfpuCmdInIdOutBuffer(&g_nfpuInterface, id, out, sizeof(NfpuTagInfo), 13); return _nfpCmdInIdOutBuffer(&g_nfpInterface, id, out, sizeof(NfpTagInfo), 13);
} }
Result nfpuGetRegisterInfo(HidControllerID id, NfpuRegisterInfo *out) { Result nfpGetRegisterInfo(HidControllerID id, NfpRegisterInfo *out) {
return _nfpuCmdInIdOutBuffer(&g_nfpuInterface, id, out, sizeof(NfpuRegisterInfo), 14); return _nfpCmdInIdOutBuffer(&g_nfpInterface, id, out, sizeof(NfpRegisterInfo), 14);
} }
Result nfpuGetCommonInfo(HidControllerID id, NfpuCommonInfo *out) { Result nfpGetCommonInfo(HidControllerID id, NfpCommonInfo *out) {
return _nfpuCmdInIdOutBuffer(&g_nfpuInterface, id, out, sizeof(NfpuCommonInfo), 15); return _nfpCmdInIdOutBuffer(&g_nfpInterface, id, out, sizeof(NfpCommonInfo), 15);
} }
Result nfpuGetModelInfo(HidControllerID id, NfpuModelInfo *out) { Result nfpGetModelInfo(HidControllerID id, NfpModelInfo *out) {
return _nfpuCmdInIdOutBuffer(&g_nfpuInterface, id, out, sizeof(NfpuModelInfo), 16); return _nfpCmdInIdOutBuffer(&g_nfpInterface, id, out, sizeof(NfpModelInfo), 16);
} }
Result nfpuAttachActivateEvent(HidControllerID id, Event *out_event) { Result nfpAttachActivateEvent(HidControllerID id, Event *out_event) {
return _nfpuCmdInIdOutEvent(&g_nfpuInterface, id, out_event, 17); return _nfpCmdInIdOutEvent(&g_nfpInterface, id, out_event, 17);
} }
Result nfpuAttachDeactivateEvent(HidControllerID id, Event *out_event) { Result nfpAttachDeactivateEvent(HidControllerID id, Event *out_event) {
return _nfpuCmdInIdOutEvent(&g_nfpuInterface, id, out_event, 18); return _nfpCmdInIdOutEvent(&g_nfpInterface, id, out_event, 18);
} }
Result nfpuGetState(NfpuState *out) { Result nfpGetState(NfpState *out) {
u32 tmp=0; u32 tmp=0;
Result rc = _nfpuCmdNoInOutU32(&g_nfpuInterface, &tmp, 19); Result rc = _nfpCmdNoInOutU32(&g_nfpInterface, &tmp, 19);
if (R_SUCCEEDED(rc) && out) *out = tmp; if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc; return rc;
} }
Result nfpuGetDeviceState(HidControllerID id, NfpuDeviceState *out) { Result nfpGetDeviceState(HidControllerID id, NfpDeviceState *out) {
u32 tmp=0; u32 tmp=0;
Result rc = _nfpuCmdInIdOutU32(&g_nfpuInterface, id, &tmp, 20); Result rc = _nfpCmdInIdOutU32(&g_nfpInterface, id, &tmp, 20);
if (R_SUCCEEDED(rc) && out) *out = tmp; if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc; return rc;
} }
Result nfpuGetNpadId(HidControllerID id, u32 *out) { Result nfpGetNpadId(HidControllerID id, u32 *out) {
return _nfpuCmdInIdOutU32(&g_nfpuInterface, id, out, 21); return _nfpCmdInIdOutU32(&g_nfpInterface, id, out, 21);
} }
Result nfpuAttachAvailabilityChangeEvent(Event *out_event) { Result nfpAttachAvailabilityChangeEvent(Event *out_event) {
if (hosversionBefore(3,0,0)) if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _fpuCmdGetEvent(&g_nfpuInterface, out_event, true, 23); return _fpuCmdGetEvent(&g_nfpInterface, out_event, true, 23);
} }
Result nfpuIsNfcEnabled(bool *out) { Result nfcIsNfcEnabled(bool *out) {
return _nfpuCmdNoInOutBool(&g_nfcuInterface, out, hosversionBefore(4,0,0) ? 3 : 403); return _nfpCmdNoInOutBool(&g_nfcInterface, out, hosversionBefore(4,0,0) ? 3 : 403);
} }