From 0c1152900082848276fbda7aaa8181f338d607b0 Mon Sep 17 00:00:00 2001 From: Javi Date: Thu, 4 Feb 2016 12:51:06 +0100 Subject: [PATCH 1/3] Add basic NFC service support --- libctru/include/3ds/services/nfc.h | 79 ++++++++++++++ libctru/source/services/nfc.c | 169 +++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 libctru/include/3ds/services/nfc.h create mode 100644 libctru/source/services/nfc.c diff --git a/libctru/include/3ds/services/nfc.h b/libctru/include/3ds/services/nfc.h new file mode 100644 index 0000000..7c848e1 --- /dev/null +++ b/libctru/include/3ds/services/nfc.h @@ -0,0 +1,79 @@ +/** + * @file nfc.h + * @brief NFC service. + */ +#pragma once + +/** + * @brief Initializes NFC. + */ +Result nfcInit(void); + +/** + * @brief Shuts down NFC. + */ +void nfcExit(void); + +/** + * @brief Gets the NFC service handle. + * @return The NFC service handle. + */ +Handle nfcGetSessionHandle(void); + +/** + * @brief Initialize NFC module. + * @param type Unknown, can be either value 0x1 or 0x2. + */ +Result nfc_Initialize(u8 type); + +/** + * @brief Shutdown NFC module. + * @param type Unknown. + */ +Result nfc_Shutdown(u8 type); + +/** + * @brief O3DS starts communication with the O3DS NFC hardware. N3DS just checks state for this command. + */ +Result nfc_StartCommunication(); + +/** + * @brief O3DS stops communication with the O3DS NFC hardware. N3DS just uses code used internally by NFC:StopTagScanning for this. + */ +Result nfc_StopCommunication(); + +/** + * @brief Starts scanning for NFC tags. + * @param unknown Unknown. + */ +Result nfc_StartTagScanning(u16 unknown); + +/** + * @brief Stops scanning for NFC tags. + */ +Result nfc_StopTagScanning(); + +/** + * @brief Read Amiibo NFC data and load in memory. + */ +Result nfc_LoadAmiiboData(); + +/** + * @brief If the tagstate is valid, it then sets the current tagstate to 3. + */ +Result nfc_ResetTagScanState(); + +/** + * @brief Returns the current NFC tag state. + * @param state Pointer to write NFC tag state. + * + * Tag state values: + * - 0: NFC:Initialize was not used yet. + * - 1: Not currently scanning for NFC tags. Set by NFC:StopTagScanning and NFC:Initialize, when successful. + * - 2: Currently scanning for NFC tags. Set by NFC:StartTagScanning when successful. + * - 3: NFC tag is in range. The state automatically changes to this when the state was previous value 3, without using any NFC service commands. + * - 4: NFC tag is now out of range, where the NFC tag was previously in range. This occurs automatically without using any NFC service commands. Once this state is entered, it won't automatically change to anything else when the tag is moved in range again. Hence, if you want to keep doing tag scanning after this, you must stop+start scanning. + * - 5: NFC tag data was successfully loaded. This is set by NFC:LoadAmiiboData when successful. + */ +Result nfc_GetTagState(u8 *state); + diff --git a/libctru/source/services/nfc.c b/libctru/source/services/nfc.c new file mode 100644 index 0000000..317ef5b --- /dev/null +++ b/libctru/source/services/nfc.c @@ -0,0 +1,169 @@ +#include <3ds/types.h> +#include <3ds/result.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/synchronization.h> +#include <3ds/services/nfc.h> +#include <3ds/ipc.h> + +static Handle nfcHandle; +static int nfcRefCount; + +Result nfcInit(void) +{ + Result ret=0; + + if (AtomicPostIncrement(&nfcRefCount)) return 0; + + ret = srvGetServiceHandle(&nfcHandle, "nfc:u"); + if (R_SUCCEEDED(ret)) + { + ret = nfc_Initialize(0x02); + if (R_FAILED(ret)) svcCloseHandle(nfcHandle); + } + if (R_FAILED(ret)) AtomicDecrement(&nfcRefCount); + + return ret; +} + +void nfcExit(void) +{ + if (AtomicDecrement(&nfcRefCount)) return; + svcCloseHandle(nfcHandle); +} + +Handle nfcGetSessionHandle(void) +{ + return nfcHandle; +} + +Result nfc_Initialize(u8 type) +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x1,1,0); // 0x10040 + cmdbuf[1]=type; + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_Shutdown(u8 type) +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x2,1,0); // 0x20040 + cmdbuf[1]=type; + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_StartCommunication() +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x3,0,0); // 0x30000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_StopCommunication() +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x4,0,0); // 0x40000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_StartTagScanning(u16 unknown) +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x5,1,0); // 0x50040 + cmdbuf[1]=unknown; + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_StopTagScanning() +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x6,0,0); // 0x60000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_LoadAmiiboData() +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x7,0,0); // 0x70000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_ResetTagScanState() +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x8,0,0); // 0x80000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + + return ret; +} + +Result nfc_GetTagState(u8 *state) +{ + Result ret=0; + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0xD,0,0); // 0xD0000 + + if(R_FAILED(ret = svcSendSyncRequest(nfcHandle)))return ret; + + ret = (Result)cmdbuf[1]; + *state = cmdbuf[2]; + + return ret; +} + From 14005eee528d232dc7c1cd2d5d09feae75996e14 Mon Sep 17 00:00:00 2001 From: Javi Date: Thu, 4 Feb 2016 17:18:26 +0100 Subject: [PATCH 2/3] Fixed prefix and parameters declaration --- libctru/include/3ds/services/nfc.h | 18 +++++++++--------- libctru/source/services/nfc.c | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libctru/include/3ds/services/nfc.h b/libctru/include/3ds/services/nfc.h index 7c848e1..8f78d62 100644 --- a/libctru/include/3ds/services/nfc.h +++ b/libctru/include/3ds/services/nfc.h @@ -24,44 +24,44 @@ Handle nfcGetSessionHandle(void); * @brief Initialize NFC module. * @param type Unknown, can be either value 0x1 or 0x2. */ -Result nfc_Initialize(u8 type); +Result NFC_Initialize(u8 type); /** * @brief Shutdown NFC module. * @param type Unknown. */ -Result nfc_Shutdown(u8 type); +Result NFC_Shutdown(u8 type); /** * @brief O3DS starts communication with the O3DS NFC hardware. N3DS just checks state for this command. */ -Result nfc_StartCommunication(); +Result NFC_StartCommunication(void); /** * @brief O3DS stops communication with the O3DS NFC hardware. N3DS just uses code used internally by NFC:StopTagScanning for this. */ -Result nfc_StopCommunication(); +Result NFC_StopCommunication(void); /** * @brief Starts scanning for NFC tags. * @param unknown Unknown. */ -Result nfc_StartTagScanning(u16 unknown); +Result NFC_StartTagScanning(u16 unknown); /** * @brief Stops scanning for NFC tags. */ -Result nfc_StopTagScanning(); +Result NFC_StopTagScanning(void); /** * @brief Read Amiibo NFC data and load in memory. */ -Result nfc_LoadAmiiboData(); +Result NFC_LoadAmiiboData(void); /** * @brief If the tagstate is valid, it then sets the current tagstate to 3. */ -Result nfc_ResetTagScanState(); +Result NFC_ResetTagScanState(void); /** * @brief Returns the current NFC tag state. @@ -75,5 +75,5 @@ Result nfc_ResetTagScanState(); * - 4: NFC tag is now out of range, where the NFC tag was previously in range. This occurs automatically without using any NFC service commands. Once this state is entered, it won't automatically change to anything else when the tag is moved in range again. Hence, if you want to keep doing tag scanning after this, you must stop+start scanning. * - 5: NFC tag data was successfully loaded. This is set by NFC:LoadAmiiboData when successful. */ -Result nfc_GetTagState(u8 *state); +Result NFC_GetTagState(u8 *state); diff --git a/libctru/source/services/nfc.c b/libctru/source/services/nfc.c index 317ef5b..cd3fa1d 100644 --- a/libctru/source/services/nfc.c +++ b/libctru/source/services/nfc.c @@ -37,7 +37,7 @@ Handle nfcGetSessionHandle(void) return nfcHandle; } -Result nfc_Initialize(u8 type) +Result NFC_Initialize(u8 type) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -52,7 +52,7 @@ Result nfc_Initialize(u8 type) return ret; } -Result nfc_Shutdown(u8 type) +Result NFC_Shutdown(u8 type) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -67,7 +67,7 @@ Result nfc_Shutdown(u8 type) return ret; } -Result nfc_StartCommunication() +Result NFC_StartCommunication(void) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -81,7 +81,7 @@ Result nfc_StartCommunication() return ret; } -Result nfc_StopCommunication() +Result NFC_StopCommunication(void) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -95,7 +95,7 @@ Result nfc_StopCommunication() return ret; } -Result nfc_StartTagScanning(u16 unknown) +Result NFC_StartTagScanning(u16 unknown) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -110,7 +110,7 @@ Result nfc_StartTagScanning(u16 unknown) return ret; } -Result nfc_StopTagScanning() +Result NFC_StopTagScanning(void) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -124,7 +124,7 @@ Result nfc_StopTagScanning() return ret; } -Result nfc_LoadAmiiboData() +Result NFC_LoadAmiiboData(void) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -138,7 +138,7 @@ Result nfc_LoadAmiiboData() return ret; } -Result nfc_ResetTagScanState() +Result NFC_ResetTagScanState(void) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); @@ -152,7 +152,7 @@ Result nfc_ResetTagScanState() return ret; } -Result nfc_GetTagState(u8 *state) +Result NFC_GetTagState(u8 *state) { Result ret=0; u32* cmdbuf=getThreadCommandBuffer(); From c3b22e3922848bd795503f8983ff868bfd7baba2 Mon Sep 17 00:00:00 2001 From: Javi Date: Thu, 4 Feb 2016 17:20:40 +0100 Subject: [PATCH 3/3] Fix nfcInit error --- libctru/source/services/nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/services/nfc.c b/libctru/source/services/nfc.c index cd3fa1d..ef6300c 100644 --- a/libctru/source/services/nfc.c +++ b/libctru/source/services/nfc.c @@ -18,7 +18,7 @@ Result nfcInit(void) ret = srvGetServiceHandle(&nfcHandle, "nfc:u"); if (R_SUCCEEDED(ret)) { - ret = nfc_Initialize(0x02); + ret = NFC_Initialize(0x02); if (R_FAILED(ret)) svcCloseHandle(nfcHandle); } if (R_FAILED(ret)) AtomicDecrement(&nfcRefCount);