diff --git a/nx/include/switch/services/mii.h b/nx/include/switch/services/mii.h index 9a6d63d2..0c0cb0bc 100644 --- a/nx/include/switch/services/mii.h +++ b/nx/include/switch/services/mii.h @@ -113,6 +113,18 @@ typedef struct { u8 unk_x57; } MiiCharInfo; +// Original Mii colors and types before Ver3StoreData conversion +typedef struct { + u8 faceline_color; + u8 hair_color; + u8 eye_color; + u8 eyebrow_color; + u8 mouth_color; + u8 beard_color; + u8 glass_color; + u8 glass_type; +} MiiNfpStoreDataExtension; + /// Initialize mii. Result miiInitialize(MiiServiceType service_type); diff --git a/nx/include/switch/services/nfc.h b/nx/include/switch/services/nfc.h index 9d20eb4a..7cb6b977 100644 --- a/nx/include/switch/services/nfc.h +++ b/nx/include/switch/services/nfc.h @@ -28,6 +28,11 @@ typedef enum { NfpState_Initialized = 1, } NfpState; +typedef enum { + NfcState_NonInitialized = 0, + NfcState_Initialized = 1, +} NfcState; + typedef enum { NfpDeviceState_Initialized = 0, NfpDeviceState_SearchingForTag = 1, @@ -38,6 +43,24 @@ typedef enum { NfpDeviceState_Finalized = 6, } NfpDeviceState; +typedef enum { + NfcDeviceState_Initialized = 0, + NfcDeviceState_SearchingForTag = 1, + NfcDeviceState_TagFound = 2, + NfcDeviceState_TagRemoved = 3, + NfcDeviceState_TagMounted = 4, + NfcDeviceState_Unavailable = 5, + NfcDeviceState_Finalized = 6, +} NfcDeviceState; + +typedef enum { + NfpApplicationAreaVersion_3DS = 0, + NfpApplicationAreaVersion_WiiU = 1, + NfpApplicationAreaVersion_3DSv2 = 2, + NfpApplicationAreaVersion_Switch = 3, + NfpApplicationAreaVersion_NotSet = 0xFF, +} NfpApplicationAreaVersion; + typedef enum { NfpDeviceType_Amiibo = 0, } NfpDeviceType; @@ -48,6 +71,37 @@ typedef enum { NfpMountTarget_All = 3, } NfpMountTarget; +typedef enum { + NfcProtocol_None = 0, + NfcProtocol_TypeA = BIT(0), ///< ISO14443A + NfcProtocol_TypeB = BIT(1), ///< ISO14443B + NfcProtocol_TypeF = BIT(2), ///< Sony FeliCa + NfcProtocol_All = 0xFFFFFFFF, +} NfcProtocol; + +typedef enum { + NfcTagType_None = 0, + NfcTagType_Type1 = BIT(0), ///< ISO14443A RW. Topaz + NfcTagType_Type2 = BIT(1), ///< ISO14443A RW. Ultralight, NTAGX, ST25TN + NfcTagType_Type3 = BIT(2), ///< ISO14443A RW/RO. Sony FeliCa + NfcTagType_Type4A = BIT(3), ///< ISO14443A RW/RO. DESFire + NfcTagType_Type4B = BIT(4), ///< ISO14443B RW/RO. DESFire + NfcTagType_Type5 = BIT(5), ///< ISO15693 RW/RO. SLI, SLIX, ST25TV + NfcTagType_Mifare = BIT(6), ///< Mifare clasic. Skylanders + NfcTagType_All = 0xFFFFFFFF, +} NfcTagType; + +typedef enum { + NfcMifareCommand_Read = 0x30, + NfcMifareCommand_AuthA = 0x60, + NfcMifareCommand_AuthB = 0x61, + NfcMifareCommand_Write = 0xA0, + NfcMifareCommand_Transfer = 0xB0, + NfcMifareCommand_Decrement = 0xC0, + NfcMifareCommand_Increment = 0xC1, + NfcMifareCommand_Store = 0xC2, +} NfcMifareCommand; + typedef struct { u8 uuid[10]; u8 uuid_length; @@ -57,6 +111,15 @@ typedef struct { u8 reserved2[0x30]; } PACKED NfpTagInfo; +typedef struct { + u8 uuid[10]; + u8 uuid_length; + u8 reserved1[0x15]; + u32 protocol; + u32 tag_type; + u8 reserved2[0x30]; +} PACKED NfcTagInfo; + typedef struct { u16 last_write_year; u8 last_write_month; @@ -77,10 +140,94 @@ typedef struct { u16 first_write_year; u8 first_write_month; u8 first_write_day; - char amiibo_name[10+1]; ///< utf-8, null-terminated - u8 reserved[0x99]; + char amiibo_name[(10*4)+1]; ///< utf-8, null-terminated + u8 font_region; + u8 reserved[0x7A]; } PACKED NfpRegisterInfo; +typedef struct { + u8 mii_store_data[0x44]; + u16 first_write_year; + u8 first_write_month; + u8 first_write_day; + char amiibo_name[(10*4)+1]; ///< utf-8, null-terminated + u8 font_region; + u8 reserved[0x8E]; +} PACKED NfpRegisterInfoPrivate; + +typedef struct { + u64 application_id; + u32 application_area_id; + u16 crc_change_counter; + u8 flags; + u8 tag_type; + u8 application_area_version; + u8 reserved[0x2F]; +} PACKED NfpAdminInfo; + +typedef struct { + u8 magic; + u8 reserved1[0x1]; + u8 write_counter; + u8 reserved2[0x1]; + u32 settings_crc; + u8 reserved3[0x38]; + u16 last_write_year; + u8 last_write_month; + u8 last_write_day; + u16 application_write_counter; + u16 version; + u32 application_area_size; + u8 reserved4[0x34]; + MiiCharInfo mii; + MiiNfpStoreDataExtension mii_store_data_extension; + u16 first_write_year; + u8 first_write_month; + u8 first_write_day; + u16 amiibo_name[10+1]; ///< utf-16, null-terminated + u8 settings_flag; ///< bit4 = amiibo was initialized in console settings, bit5 = has application area + u8 unknown1; ///< Normally zero + u32 register_info_crc; + u32 unknown2[0x5]; ///< Normally zero + u8 reserved5[0x64]; + u64 application_id; + u32 access_id; + u16 settings_crc_counter; + u8 font_region; + u8 tag_type; + u8 console_type; + u8 application_id_byte; ///< (Original Program ID >> 0x24) & 0xF byte (Program ID has this byte swapped with console type) + u8 reserved6[0x2E]; + u8 application_area[0xD8]; +} PACKED NfpData; + +typedef struct { + u8 mifare_command; + u8 unknown; ///< Usually 1 + u8 reserved1[0x6]; + u8 sector_key[0x6]; + u8 reserved2[0x2]; +} PACKED NfcSectorKey; + +typedef struct { + u8 sector_number; + u8 reserved[0x7]; + NfcSectorKey sector_key; +} PACKED NfcMifareReadBlockParameter; + +typedef struct { + u8 data[0x10]; + u8 sector_number; + u8 reserved[0x7]; +} PACKED NfcMifareReadBlockData; + +typedef struct { + u8 data[0x10]; + u8 sector_number; + u8 reserved[0x7]; + NfcSectorKey sector_key; +} NfcMifareWriteBlockParameter; + typedef struct { u64 version; u64 reserved[3]; @@ -103,6 +250,12 @@ Result nfcInitialize(NfcServiceType service_type); /// Exit nfc:*. void nfcExit(void); +/// Initialize nfc:mf:u. +Result nfcMfInitialize(); + +/// Exit nfc:mf:u. +void nfcMfExit(void); + /// Gets the Service object for the actual nfp:* service session. Service* nfpGetServiceSession(void); @@ -115,17 +268,34 @@ Service* nfcGetServiceSession(void); /// Gets the Service object for the interface from nfc:*. Service* nfcGetServiceSession_Interface(void); +/// Gets the Service object for the actual nfc:mf:u service session. +Service* nfcMfGetServiceSession(void); + +/// Gets the Service object for the interface from nfc:mf:u. +Service* nfcMfGetServiceSession_Interface(void); + Result nfpListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count); Result nfpStartDetection(const NfcDeviceHandle *handle); Result nfpStopDetection(const NfcDeviceHandle *handle); Result nfpMount(const NfcDeviceHandle *handle, NfpDeviceType device_type, NfpMountTarget mount_target); Result nfpUnmount(const NfcDeviceHandle *handle); +/// Only available with [4.0.0+]. +Result nfcListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count); +/// Only available with [4.0.0+]. +Result nfcStartDetection(const NfcDeviceHandle *handle, NfcProtocol protocol); +/// Only available with [4.0.0+]. +Result nfcStopDetection(const NfcDeviceHandle *handle); + +Result nfcMfListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count); +Result nfcMfStartDetection(const NfcDeviceHandle *handle); +Result nfcMfStopDetection(const NfcDeviceHandle *handle); + /// Not available with ::NfpServiceType_System. Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id); /// Not available with ::NfpServiceType_System. -Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size); +Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size, u32 *out_size); /// Not available with ::NfpServiceType_System. Result nfpSetApplicationArea(const NfcDeviceHandle *handle, const void* buf, size_t buf_size); @@ -135,27 +305,112 @@ Result nfpRestore(const NfcDeviceHandle *handle); /// Not available with ::NfpServiceType_System. Result nfpCreateApplicationArea(const NfcDeviceHandle *handle, u32 app_id, const void* buf, size_t buf_size); +/// Not available with ::NfpServiceType_System. +/// Only available with [3.0.0+]. +Result nfpRecreateApplicationArea(const NfcDeviceHandle *handle, u32 app_id, const void* buf, size_t buf_size); + +/// Not available with ::NfpServiceType_System. +Result nfpGetApplicationAreaSize(const NfcDeviceHandle *handle, u32 *out_app_area_size); + +/// Not available with ::NfpServiceType_User. +Result nfpDeleteApplicationArea(const NfcDeviceHandle *handle); + +/// Not available with ::NfpServiceType_User. +Result nfpExistsApplicationArea(const NfcDeviceHandle *handle, bool *out); + Result nfpGetTagInfo(const NfcDeviceHandle *handle, NfpTagInfo *out); Result nfpGetRegisterInfo(const NfcDeviceHandle *handle, NfpRegisterInfo *out); Result nfpGetCommonInfo(const NfcDeviceHandle *handle, NfpCommonInfo *out); Result nfpGetModelInfo(const NfcDeviceHandle *handle, NfpModelInfo *out); +/// Not available with ::NfpServiceType_User. +Result nfpGetAdminInfo(const NfcDeviceHandle *handle, NfpAdminInfo *out); + +/// Only available with [4.0.0+]. +Result nfcGetTagInfo(const NfcDeviceHandle *handle, NfcTagInfo *out); + +Result nfcMfGetTagInfo(const NfcDeviceHandle *handle, NfcTagInfo *out); /// Returned event will have autoclear off. Result nfpAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event); /// Returned event will have autoclear off. Result nfpAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event); +/// Returned event will have autoclear off. +/// Only available with [4.0.0+]. +Result nfcAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event); +/// Returned event will have autoclear off. +/// Only available with [4.0.0+]. +Result nfcAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event); + +/// Returned event will have autoclear off. +Result nfcMfAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event); +/// Returned event will have autoclear off. +Result nfcMfAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event); + Result nfpGetState(NfpState *out); Result nfpGetDeviceState(const NfcDeviceHandle *handle, NfpDeviceState *out); Result nfpGetNpadId(const NfcDeviceHandle *handle, u32 *out); +/// Only available with [4.0.0+]. +Result nfcGetState(NfcState *out); +/// Only available with [4.0.0+]. +Result nfcGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out); +/// Only available with [4.0.0+]. +Result nfcGetNpadId(const NfcDeviceHandle *handle, u32 *out); + +Result nfcMfGetState(NfcState *out); +Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out); +Result nfcMfGetNpadId(const NfcDeviceHandle *handle, u32 *out); + /// Returned event will have autoclear on. /// Only available with [3.0.0+]. Result nfpAttachAvailabilityChangeEvent(Event *out_event); +/// Returned event will have autoclear on. +/// Only available with [4.0.0+]. +Result nfcAttachAvailabilityChangeEvent(Event *out_event); +/// Returned event will have autoclear on. +Result nfcMfAttachAvailabilityChangeEvent(Event *out_event); + +/// Not available with ::NfpServiceType_User. +Result nfpFormat(const NfcDeviceHandle *handle); + +/// Not available with ::NfpServiceType_User. +Result nfpGetRegisterInfoPrivate(const NfcDeviceHandle *handle, NfpRegisterInfoPrivate *out); +/// Not available with ::NfpServiceType_User. +Result nfpSetRegisterInfoPrivate(const NfcDeviceHandle *handle, const NfpRegisterInfoPrivate *register_info_private); +/// Not available with ::NfpServiceType_User. +Result nfpDeleteRegisterInfo(const NfcDeviceHandle *handle); + +/// Only available with ::NfpServiceType_Debug. +Result nfpGetAll(const NfcDeviceHandle *handle, NfpData *out); +/// Only available with ::NfpServiceType_Debug. +Result nfpSetAll(const NfcDeviceHandle *handle, const NfpData *nfp_data); + +/// Only available with ::NfpServiceType_Debug. +Result nfpFlushDebug(const NfcDeviceHandle *handle); +/// Only available with ::NfpServiceType_Debug. +Result nfpBreakTag(const NfcDeviceHandle *handle, u32 break_type); +/// Only available with ::NfpServiceType_Debug. +Result nfpReadBackupData(const NfcDeviceHandle *handle, void* out_buf, size_t buf_size, u32 *out_size); +/// Only available with ::NfpServiceType_Debug. +Result nfpWriteBackupData(const NfcDeviceHandle *handle, const void* buf, size_t buf_size); +/// Only available with ::NfpServiceType_Debug. +Result nfpWriteNtf(const NfcDeviceHandle *handle, u32 write_type, const void* buf, size_t buf_size); /// This uses nfc:*. Result nfcIsNfcEnabled(bool *out); +/// Only available with [4.0.0+]. +Result nfcReadMifare(const NfcDeviceHandle *handle, NfcMifareReadBlockData *out_block_data, const NfcMifareReadBlockParameter *read_block_parameter, s32 count); +/// Only available with [4.0.0+]. +Result nfcWriteMifare(const NfcDeviceHandle *handle, const NfcMifareWriteBlockParameter *write_block_parameter, s32 count); + +Result nfcMfReadMifare(const NfcDeviceHandle *handle, NfcMifareReadBlockData *out_block_data, const NfcMifareReadBlockParameter *read_block_parameter, s32 count); +Result nfcMfWriteMifare(const NfcDeviceHandle *handle, const NfcMifareWriteBlockParameter *write_block_parameter, s32 count); + +/// Only available with [4.0.0+]. Result nfcSendCommandByPassThrough(const NfcDeviceHandle *handle, u64 timeout, const void* cmd_buf, size_t cmd_buf_size, void* reply_buf, size_t reply_buf_size, u64 *out_size); +/// Only available with [4.0.0+]. Result nfcKeepPassThroughSession(const NfcDeviceHandle *handle); +/// Only available with [4.0.0+]. Result nfcReleasePassThroughSession(const NfcDeviceHandle *handle); diff --git a/nx/source/services/nfc.c b/nx/source/services/nfc.c index c8989b13..387e6a36 100644 --- a/nx/source/services/nfc.c +++ b/nx/source/services/nfc.c @@ -10,6 +10,8 @@ static Service g_nfpSrv; static Service g_nfpInterface; static Service g_nfcSrv; static Service g_nfcInterface; +static Service g_nfcMfSrv; +static Service g_nfcMfInterface; static const NfcRequiredMcuVersionData g_nfcVersionData[2] = { { @@ -29,6 +31,7 @@ static Result _nfcCmdNoIO(Service* srv, u32 cmd_id); static Result _nfcCmdInDevhandleNoOut(Service* srv, const NfcDeviceHandle *handle, u32 cmd_id); static Result _nfcCmdInDevhandleOutEvent(Service* srv, const NfcDeviceHandle *handle, Event *out_event, u32 cmd_id); static Result _nfcCmdInDevhandleOutBuffer(Service* srv, const NfcDeviceHandle *handle, void* buf, size_t buf_size, u32 cmd_id); +static Result _nfcCmdInDevhandleInBufferNoOut(Service* srv, const NfcDeviceHandle *handle, const void* buf, size_t buf_size, u32 cmd_id); NX_GENERATE_SERVICE_GUARD_PARAMS(nfp, (NfpServiceType service_type), (service_type)); @@ -99,6 +102,29 @@ void _nfcCleanup(void) { serviceClose(&g_nfcSrv); } +Result _nfcMfInitialize() { + Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); + + rc = smGetService(&g_nfcMfSrv, "nfc:mf:u"); + + if (R_SUCCEEDED(rc)) + rc = serviceConvertToDomain(&g_nfcMfSrv); + + if (R_SUCCEEDED(rc)) + rc = _nfcCreateInterface(&g_nfcMfSrv, &g_nfcMfInterface); + + if (R_SUCCEEDED(rc)) + rc = _nfcInterfaceInitialize(&g_nfcMfInterface, g_nfcVersionData, 2, 0); + + return rc; +} + +void _nfcMfCleanup(void) { + _nfcCmdNoIO(&g_nfcMfInterface, 1); // Finalize + serviceClose(&g_nfcMfInterface); + serviceClose(&g_nfcMfSrv); +} + Service* nfpGetServiceSession(void) { return &g_nfpSrv; } @@ -108,11 +134,19 @@ Service* nfpGetServiceSession_Interface(void) { } Service* nfcGetServiceSession(void) { - return &g_nfpSrv; + return &g_nfcSrv; } Service* nfcGetServiceSession_Interface(void) { - return &g_nfpInterface; + return &g_nfcInterface; +} + +Service* nfcMfGetServiceSession(void) { + return &g_nfcMfSrv; +} + +Service* nfcMfGetServiceSession_Interface(void) { + return &g_nfcMfInterface; } static Result _nfcCreateInterface(Service* srv, Service* srv_out) { @@ -191,6 +225,14 @@ static Result _nfcCmdInDevhandleOutBuffer(Service* srv, const NfcDeviceHandle *h ); } +static Result _nfcCmdInDevhandleInBufferNoOut(Service* srv, const NfcDeviceHandle *handle, const void* buf, size_t buf_size, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, *handle, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { buf, buf_size } }, + ); +} + static Result _nfcInterfaceInitialize(Service* srv, const NfcRequiredMcuVersionData *version, s32 count, u32 cmd_id) { const struct { u64 aruid; @@ -213,14 +255,61 @@ Result nfpListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count) { ); } +Result nfcListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + serviceAssumeDomain(&g_nfcInterface); + return serviceDispatchOut(&g_nfcInterface, 404, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { out, count*sizeof(NfcDeviceHandle) } }, + ); +} + +Result nfcMfListDevices(s32 *total_out, NfcDeviceHandle *out, s32 count) { + serviceAssumeDomain(&g_nfcMfInterface); + return serviceDispatchOut(&g_nfcMfInterface, 2, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { out, count*sizeof(NfcDeviceHandle) } }, + ); +} + Result nfpStartDetection(const NfcDeviceHandle *handle) { return _nfcCmdInDevhandleNoOut(&g_nfpInterface, handle, 3); } +Result nfcStartDetection(const NfcDeviceHandle *handle, NfcProtocol protocol) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + NfcDeviceHandle handle; + NfcProtocol protocol; + } in = { *handle, protocol }; + + serviceAssumeDomain(&g_nfcInterface); + return serviceDispatchIn(&g_nfcInterface, 408, in); +} + +Result nfcMfStartDetection(const NfcDeviceHandle *handle) { + return _nfcCmdInDevhandleNoOut(&g_nfcMfInterface, handle, 3); +} + Result nfpStopDetection(const NfcDeviceHandle *handle) { return _nfcCmdInDevhandleNoOut(&g_nfpInterface, handle, 4); } +Result nfcStopDetection(const NfcDeviceHandle *handle) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdInDevhandleNoOut(&g_nfcInterface, handle, 409); +} + +Result nfcMfStopDetection(const NfcDeviceHandle *handle) { + return _nfcCmdInDevhandleNoOut(&g_nfcMfInterface, handle, 4); +} + Result nfpMount(const NfcDeviceHandle *handle, NfpDeviceType device_type, NfpMountTarget mount_target) { const struct { NfcDeviceHandle handle; @@ -249,12 +338,12 @@ Result nfpOpenApplicationArea(const NfcDeviceHandle *handle, u32 app_id) { return serviceDispatchIn(&g_nfpInterface, 7, in); } -Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size) { +Result nfpGetApplicationArea(const NfcDeviceHandle *handle, void* buf, size_t buf_size, u32 *out_size) { if (g_nfpServiceType == NfpServiceType_System) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); serviceAssumeDomain(&g_nfpInterface); - return serviceDispatchIn(&g_nfpInterface, 8, *handle, + return serviceDispatchInOut(&g_nfpInterface, 8, *handle, *out_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { buf, buf_size } }, ); @@ -295,10 +384,64 @@ Result nfpCreateApplicationArea(const NfcDeviceHandle *handle, u32 app_id, const ); } +Result nfpRecreateApplicationArea(const NfcDeviceHandle *handle, u32 app_id, const void* buf, size_t buf_size) { + if (g_nfpServiceType == NfpServiceType_System) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + NfcDeviceHandle handle; + u32 app_id; + } in = { *handle, app_id }; + + serviceAssumeDomain(&g_nfpInterface); + return serviceDispatchIn(&g_nfpInterface, 24, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buf, buf_size } }, + ); +} + +Result nfpGetApplicationAreaSize(const NfcDeviceHandle *handle, u32 *out_app_area_size) { + if (g_nfpServiceType == NfpServiceType_System) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleOutU32(&g_nfpInterface, handle, out_app_area_size, 22); +} + +Result nfpDeleteApplicationArea(const NfcDeviceHandle *handle) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleNoOut(&g_nfpInterface, handle, 105); +} + +Result nfpExistsApplicationArea(const NfcDeviceHandle *handle, bool *out) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + u32 tmp=0; + Result rc = _nfcCmdInDevhandleOutU32(&g_nfpInterface, handle, &tmp, 106); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + Result nfpGetTagInfo(const NfcDeviceHandle *handle, NfpTagInfo *out) { return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpTagInfo), 13); } +Result nfcGetTagInfo(const NfcDeviceHandle *handle, NfcTagInfo *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdInDevhandleOutBuffer(&g_nfcInterface, handle, out, sizeof(NfcTagInfo), 410); +} + +Result nfcMfGetTagInfo(const NfcDeviceHandle *handle, NfcTagInfo *out) { + return _nfcCmdInDevhandleOutBuffer(&g_nfcMfInterface, handle, out, sizeof(NfcTagInfo), 7); +} + Result nfpGetRegisterInfo(const NfcDeviceHandle *handle, NfpRegisterInfo *out) { return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpRegisterInfo), 14); } @@ -311,14 +454,43 @@ Result nfpGetModelInfo(const NfcDeviceHandle *handle, NfpModelInfo *out) { return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpModelInfo), 16); } +Result nfpGetAdminInfo(const NfcDeviceHandle *handle, NfpAdminInfo *out) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpAdminInfo), 101); +} + Result nfpAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event) { return _nfcCmdInDevhandleOutEvent(&g_nfpInterface, handle, out_event, 17); } +Result nfcAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdInDevhandleOutEvent(&g_nfcInterface, handle, out_event, 411); +} + +Result nfcMfAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event) { + return _nfcCmdInDevhandleOutEvent(&g_nfcMfInterface, handle, out_event, 8); +} + Result nfpAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event) { return _nfcCmdInDevhandleOutEvent(&g_nfpInterface, handle, out_event, 18); } +Result nfcAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdInDevhandleOutEvent(&g_nfcInterface, handle, out_event, 412); +} + +Result nfcMfAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event) { + return _nfcCmdInDevhandleOutEvent(&g_nfcMfInterface, handle, out_event, 9); +} + Result nfpGetState(NfpState *out) { u32 tmp=0; Result rc = _nfcCmdNoInOutU32(&g_nfpInterface, &tmp, 19); @@ -326,6 +498,20 @@ Result nfpGetState(NfpState *out) { return rc; } +Result nfcGetState(NfcState *out) { + u32 tmp=0; + Result rc = _nfcCmdNoInOutU32(&g_nfcInterface, &tmp, hosversionBefore(4,0,0) ? 2 : 402); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + +Result nfcMfGetState(NfcState *out) { + u32 tmp=0; + Result rc = _nfcCmdNoInOutU32(&g_nfcMfInterface, &tmp, 10); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + Result nfpGetDeviceState(const NfcDeviceHandle *handle, NfpDeviceState *out) { u32 tmp=0; Result rc = _nfcCmdInDevhandleOutU32(&g_nfpInterface, handle, &tmp, 20); @@ -333,10 +519,38 @@ Result nfpGetDeviceState(const NfcDeviceHandle *handle, NfpDeviceState *out) { return rc; } +Result nfcGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u32 tmp=0; + Result rc = _nfcCmdInDevhandleOutU32(&g_nfcInterface, handle, &tmp, 405); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + +Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out) { + u32 tmp=0; + Result rc = _nfcCmdInDevhandleOutU32(&g_nfcMfInterface, handle, &tmp, 11); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + Result nfpGetNpadId(const NfcDeviceHandle *handle, u32 *out) { return _nfcCmdInDevhandleOutU32(&g_nfpInterface, handle, out, 21); } +Result nfcGetNpadId(const NfcDeviceHandle *handle, u32 *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdInDevhandleOutU32(&g_nfcInterface, handle, out, 406); +} + +Result nfcMfGetNpadId(const NfcDeviceHandle *handle, u32 *out) { + return _nfcCmdInDevhandleOutU32(&g_nfcMfInterface, handle, out, 12); +} + Result nfpAttachAvailabilityChangeEvent(Event *out_event) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -344,10 +558,185 @@ Result nfpAttachAvailabilityChangeEvent(Event *out_event) { return _nfcCmdGetEvent(&g_nfpInterface, out_event, true, 23); } +Result nfcAttachAvailabilityChangeEvent(Event *out_event) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nfcCmdGetEvent(&g_nfcInterface, out_event, true, 407); +} + +Result nfcMfAttachAvailabilityChangeEvent(Event *out_event) { + return _nfcCmdGetEvent(&g_nfcMfInterface, out_event, true, 13); +} + +Result nfcFormat(const NfcDeviceHandle *handle) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleNoOut(&g_nfcInterface, handle, 100); +} + +Result nfpGetRegisterInfoPrivate(const NfcDeviceHandle *handle, NfpRegisterInfoPrivate *out) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpRegisterInfoPrivate), 102); +} + +Result nfpSetRegisterInfoPrivate(const NfcDeviceHandle *handle, const NfpRegisterInfoPrivate *register_info_private) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleInBufferNoOut(&g_nfcInterface, handle, register_info_private, sizeof(NfpRegisterInfoPrivate) , 103); +} + +Result nfpDeleteRegisterInfo(const NfcDeviceHandle *handle) { + if (g_nfpServiceType == NfpServiceType_User) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleNoOut(&g_nfcInterface, handle, 104); +} + +Result nfpGetAll(const NfcDeviceHandle *handle, NfpData *out) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleOutBuffer(&g_nfpInterface, handle, out, sizeof(NfpData), 200); +} + +Result nfpSetAll(const NfcDeviceHandle *handle, const NfpData *nfp_data) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleInBufferNoOut(&g_nfcInterface, handle, nfp_data, sizeof(NfpData) , 201); +} + +Result nfpFlushDebug(const NfcDeviceHandle *handle) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nfcCmdInDevhandleNoOut(&g_nfcInterface, handle, 202); +} + +Result nfpBreakTag(const NfcDeviceHandle *handle, u32 break_type) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + const struct { + NfcDeviceHandle handle; + u32 break_type; + } in = { *handle, break_type }; + + serviceAssumeDomain(&g_nfpInterface); + return serviceDispatchIn(&g_nfpInterface, 203, in); +} + +Result nfpReadBackupData(const NfcDeviceHandle *handle, void* out_buf, size_t buf_size, u32 *out_size) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + serviceAssumeDomain(&g_nfpInterface); + return serviceDispatchInOut(&g_nfpInterface, 204, *handle, *out_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_buf, buf_size } }, + ); +} + +Result nfpWriteBackupData(const NfcDeviceHandle *handle, const void* buf, size_t buf_size) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + serviceAssumeDomain(&g_nfpInterface); + return serviceDispatchIn(&g_nfpInterface, 205, *handle, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buf, buf_size } }, + ); +} + +/// Only available with ::NfpServiceType_Debug. +Result nfpWriteNtf(const NfcDeviceHandle *handle, u32 write_type, const void* buf, size_t buf_size) { + if (g_nfpServiceType != NfpServiceType_Debug) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + const struct { + NfcDeviceHandle handle; + u32 write_type; + } in = { *handle, write_type }; + + + serviceAssumeDomain(&g_nfpInterface); + return serviceDispatchIn(&g_nfpInterface, 206, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buf, buf_size } }, + ); +} + Result nfcIsNfcEnabled(bool *out) { return _nfcCmdNoInOutBool(&g_nfcInterface, out, hosversionBefore(4,0,0) ? 3 : 403); } +Result nfcReadMifare(const NfcDeviceHandle *handle, NfcMifareReadBlockData *out_block_data, const NfcMifareReadBlockParameter *read_block_parameter, s32 count) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + serviceAssumeDomain(&g_nfcInterface); + Result rc = serviceDispatchIn(&g_nfcInterface, 1000, *handle, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { out_block_data, count*sizeof(NfcMifareReadBlockData) }, + { read_block_parameter, count*sizeof(NfcMifareReadBlockParameter) }, + }, + ); + return rc; +} + +Result nfcMfReadMifare(const NfcDeviceHandle *handle, NfcMifareReadBlockData *out_block_data, const NfcMifareReadBlockParameter *read_block_parameter, s32 count) { + serviceAssumeDomain(&g_nfcMfInterface); + Result rc = serviceDispatchIn(&g_nfcMfInterface, 5, *handle, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { out_block_data, count*sizeof(NfcMifareReadBlockData) }, + { read_block_parameter, count*sizeof(NfcMifareReadBlockParameter) }, + }, + ); + return rc; +} + +Result nfcWriteMifare(const NfcDeviceHandle *handle, const NfcMifareWriteBlockParameter *write_block_parameter, s32 count) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + serviceAssumeDomain(&g_nfcInterface); + Result rc = serviceDispatchIn(&g_nfcInterface, 1001, *handle, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { write_block_parameter, count*sizeof(NfcMifareWriteBlockParameter) }, + }, + ); + return rc; +} + +Result nfcMfWriteMifare(const NfcDeviceHandle *handle, const NfcMifareWriteBlockParameter *write_block_parameter, s32 count) { + serviceAssumeDomain(&g_nfcMfInterface); + Result rc = serviceDispatchIn(&g_nfcMfInterface, 6, *handle, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { write_block_parameter, count*sizeof(NfcMifareWriteBlockParameter) }, + }, + ); + return rc; +} + Result nfcSendCommandByPassThrough(const NfcDeviceHandle *handle, u64 timeout, const void* cmd_buf, size_t cmd_buf_size, void* reply_buf, size_t reply_buf_size, u64 *out_size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -386,4 +775,3 @@ Result nfcReleasePassThroughSession(const NfcDeviceHandle *handle) { return _nfcCmdInDevhandleNoOut(&g_nfcInterface, handle, 1302); } -