Note the following cautions when implementing an application that uses the NFP library.
- The NFP library does not support multithreaded processes. Do not call NFP library functions simultaneously from multiple threads.
- A successful function call generally returns
nn::ResultSuccess
, but uses theIsSuccess
function or theIsFailure
function to determine whether execution succeeded. - Return values belonging to
nn::nfp::ResultInvalidUsage
are implementation errors (nn::nfp::ResultInvalidArgument
,nn::nfp::ResultInvalidPointer
, andnn::nfp::ResultBufferIsSmall
). Fix your implementation during development so that these errors are not returned. - Many of the API functions provided by the NFP library have processing times in the range from a few dozen milliseconds to several hundred milliseconds. In particular, initializing the library can take upwards of five seconds and writing to an NFP tag can take around one second. For this reason, we recommend calling the functions in the NFP library from a separate thread rather than from the main loop.
- After a tag is detected, if communication is lost because, for example, the tag is moved too far away from the reader, a loss-of-tag notification is sent to the application. At this point, the NFP library transitions to the
RW_DEACTIVE
state, and the mounted tag is unmounted.
If you call an NFP library function in this state, most functions will returnnn::nfp::ResultInvalidOperation
. Be sure to have your application handle the tag loss notification and verify that the detected tag is still accessible before calling any NFP library functions. - If the system enters Sleep Mode or wireless-disabled mode during the execution of an NFP library function, most functions will return
nn::nfp::ResultSleep
ornn::nfp::ResultWifiOff
. When these values are returned, the NFP library reverts to theINIT
state, tag detection stops, and the mounted tag is unmounted. This state is the same as the one that is entered when thenn::nfp::Unmount
andnn::nfp::StopDetection
functions are called.
Even if the system wakes from Sleep Mode or transitions back to wireless-enabled mode, the NFP library does not automatically return to its previous state. The application must resume tag detection by callingnn::nfp::StartDetection
again. - Before transitioning to the HOME Menu or Sleep Mode, if the
nn::nfp::Flush
function has not yet been called when writing to the application-specific region, you can delay the transition to the HOME Menu or Sleep Mode until the write operation has been completed by callingnn::nfp::Flush
. An alternative approach is to display the HOME Menu Disabled icon and prevent transitioning to the HOME Menu while writing to the NFP tag. - Before transitioning to the HOME Menu or an applet, call
nn::nfp::Finalize
to put the NFP library into theNONE
state. If this operation is omitted, the touch panel and NFC-related features will be unavailable to the HOME Menu or applet.
The NFP library includes functions that access backup data and NFP tags. Calling these functions excessively can shorten the life of the hardware and NFP tag.
Implement your application so that it does not call the following functions too often, unless the user intentionally repeats an operation that requires them.
Function | Read From Backup Data | Write to Backup Data | Write to NFP Tag |
---|---|---|---|
nn::nfp::Initialize |
Always | When there is no save data for backups | None |
nn::nfp::Mount |
Always | When mounting a tag for the first time, or when mounting a tag that was overwritten by another device | None |
nn::nfp::Restore |
Always | None | Always |
nn::nfp::Flush |
None | Always | Always |
nn::nfp::CreateApplicationArea |
None | Always | Always |
6.1. Initialization
Call the nn::nfp::Initialize
function to initialize the NFP library. Nintendo strongly recommends calling this function outside of the main thread because it usually takes around one second to execute, and as much as five seconds when run for the first time. Nintendo also recommends calling this function after the application is ready to update the screen instead of during startup.
Almost all of the functions in the NFP library return nn::nfp::ResultInvalidOperation
if called before the library is initialized. If you call nn::nfp::Initialize
when the library is already initialized, it returns nn::nfp::ResultInvalidOperation
, but you can handle this result as a success in this case.
If initialization of the NFP library fails, sometimes nn::nfp::ResultNeedRetry
is returned. When this occurs, call nn::nfp::Initialize
again. You can increase the chance of success if you wait around one second before calling.
Return Value | Description |
---|---|
nn::ResultSuccess |
Initialization successful. |
nn::nfp::ResultInvalidOperation |
Already initialized. |
nn::nfp::ResultNeedRetry |
Try again. |
6.1.1. Setting Events to Receive Tag Detection Notifications
Before starting tag detection, you must set events so the application can receive tag detection notifications from the NFP library.
The NFP library sends tag detection notifications to the application at the following times.
- A tag was detected within the range of communication of the NFC module (tag detection notification).
- The detected tag left the range of communication (tag loss notification).
- The
nn::nfp::StopDetection
,nn::nfp::Disconnect
ornn::nfp::Finalize
function was called when a tag had been detected (tag loss notification).
Use the nn::nfp::SetActivateEvent
function to set the event for tag detection notifications and the nn::nfp::SetDeactivateEvent
function for tag loss notifications.
Each of these functions takes a pointer to an instance of the nn::os::Event
class as an argument. The NFP library manages the events, so the application does not need to initialize or finalize the instances that are passed.
These functions must be called before starting tag detection (while the state is INIT
).
Return Value | Description |
---|---|
nn::ResultSuccess |
The event was successfully set. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
6.1.1.1. Handling Tag Detection Notifications
When the NFP library detects a tag, the application is notified by putting the event object set with nn::nfp::SetActivateEvent
into a signaled state.
When a tag is detected, the following processes become available.
6.1.1.2. Handling Tag Loss Notifications
When the NFP library loses a tag because the tag leaves the range of communication, the application is notified by putting the event object set with nn::nfp::SetDeactivateEvent
into a signaled state. The NFP library transitions to the RW_DEACTIVE
state as soon as the notification is received. To continue tag detection, you must call the nn::nfp::StartDetection
function again.
You can determine the cause of the tag loss based on the tag connection status that can be retrieved using nn::nfp::GetConnectionStatus
. The tag connection status is defined with the nn::nfp::ConnectionStatus
structure. A pointer to the structure must be passed to nn::nfp::GetConnectionStatus
.
If nn::nfp::GetConnectionStatus
succeeds, the connection status of the current tag will be stored in the structure that was passed as an argument. The detailed connection status (reason for disconnect) is defined by the nn::nfp::DeactivateReason
enumerator and stored in the deactivateReason
member of the structure.
Definition | Connection Status | Description |
---|---|---|
BEFORE_ACTIVATION |
Not found | A tag has not been detected yet. |
TAG_IS_ACTIVE |
Connected | The tag can be accessed. |
DETECT_ERROR |
Connection failure | Not recognized as a valid tag. The tag data may be corrupted. |
CONNECTION_LOST |
Disconnected | Could not maintain the connection because the tag left the range of communication or the signal is too weak. |
UNKNOWN_DEACTIVATE_REASON |
Disconnected | The connection was lost for a reason not recognized by the library. |
Return Value | Description |
---|---|
nn::ResultSuccess |
The connection status was successfully retrieved. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
6.2. Starting Tag Detection
Call the nn::nfp::StartDetection
function to start tag detection.
While tag detection is running, the NFP library periodically checks whether any tags have been detected and whether it can communicate with any detected tags. There is a time lag of several hundred milliseconds between the occurrence of the event that causes the tag detection state to change, and when the application is notified of the tag detection or tag loss. Do not implement your application in a way that requires careful timing when applying and removing tags. This assumes that the tag is placed in the center of the lower screen on the New Nintendo 3DS system. Specifically, the tag can be accurately recognized within ±10 mm in the horizontal and vertical directions from the center of the LCD screen, and within 5 mm of the surface. This range also applies to the New Nintendo 3DS XL. Avoid gameplay and user interface designs that encourage the user to place a tag away from the center of the LCD screen.
Also note that the electromagnetic waves used for tag detection on the New Nintendo 3DS system cause the input from the touch panel to become unstable. Use of the touch panel for input during detection is restricted on the New Nintendo 3DS due to the potential for unintended operations in an application. Specifically, the status
member of nn::hid::CTR::TouchPanelStatus
is always 0
(pen up) from the time the nn::nfp::StartDetection
function is called until the nn::nfp::StopDetection
or nn::nfp::Finalize
function is called to stop tag detection.
There is no such restriction on the original Nintendo 3DS systems because a peripheral device is used for tag detection. However, if your application uses the touch panel on the Nintendo 3DS during tag detection, make sure that the application can also be controlled on the New Nintendo 3DS by providing a different UI or other method.
Return Value | Description |
---|---|
nn::ResultSuccess |
Tag detection has started. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
6.3. Getting Tag Information
Call the nn::nfp::GetTagInfo
function to get tag information. Tag information is defined with the nn::nfp::TagInfo
structure. A pointer to the structure must be passed to nn::nfp::GetTagInfo
.
After a tag is detected, if it leaves the range of communication or is swapped with a different tag before nn::nfp::GetTagInfo
is called, the nn::nfp::GetTagInfo
function will return nn::nfp::ResultTagNotFound
. When this value is returned, the NFP library transitions to the RW_DEACTIVE
state as soon as the notification is received. To continue tag detection, you must call the nn::nfp::StartDetection
function again.
Return Value | Description |
---|---|
nn::ResultSuccess |
The tag information was successfully retrieved. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
The NFP library can only get the tag UID from the tag information. We recommend using nn::nfp::GetTagInfo
to get the tag information in advance for applications that access the application-specific region of the NFP tag.
Because the tag information only contains information that can be retrieved from any tag type that is accessible to the NFP library, there is no way to determine whether the detected tag is an NFP tag.
6.4. Mounting a Tag
To access the information in an NFP tag, you must first call nn::nfp::Mount
or nn::nfp::MountRom
to mount the detected tag.
Neither function will mount a tag that is not an NFP tag, but the nn::nfp::MountRom
function can mount a tag even if it has corrupted data, although there are limitations on the information that can be accessed.
You can use the return value to determine whether a tag is an NFP tag, as described below.
Tag Status | nn::nfp::Mount |
nn::nfp::MountRom |
---|---|---|
Not an NFP tag | nn::nfp::ResultNotSupported |
|
NFP tag with unknown format version | nn::nfp::ResultInvalidFormatVersion |
|
NFP tag with normal data | nn::nfp::ResultSuccess |
|
NFP tag with corrupted data (No backup data for the tag) |
nn::nfp::ResultNeedFormat |
nn::nfp::ResultSuccess |
NFP tag with corrupted data (Backup data for the tag is available) |
nn::nfp::ResultNeedRestore |
nn::nfp::ResultSuccess |
If the detected tag is not an NFP tag, a value of nn::nfp::ResultNotSupported
is returned.
If the detected tag is an NFP tag but cannot be mounted because the format version is unknown, a value of nn::nfp::ReultInvalidFormatVersion
is returned.
If the detected tag is an NFP tag and is successfully mounted, a value of nn::nfp::ResultSuccess
is returned.
If the detected tag is an NFP tag and the data is corrupted, a value of nn::nfp::ResultNeedRestore
or nn::nfp::ResultNeedFormat
is returned. If the first value is returned, you can restore the tag data in the application by calling nn::nfp::Restore
. If the second value is returned, you cannot restore the tag data within the application, so the NFP tag must be reset in amiibo Settings.
When nn::nfp::ResultTagNotFound
is returned, the NFP library transitions to the RW_DEACTIVE
state as soon as the notification is received. To continue tag detection, you must call the nn::nfp::StartDetection
function again.
When nn::nfp::ResultNeedRetry
is returned, the mounting process might succeed if nn::nfp::Mount
is called again.
Mounting a tag can take longer than a second.
If you want to try again, we recommend a retry interval of around 100 milliseconds.
Return Value | Description |
---|---|
nn::ResultSuccess |
The tag was successfully mounted. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNotSupported |
The tag is not an NFP tag. |
nn::nfp::ResultNeedRestore |
The tag data is corrupted. Call nn::nfp::Restore to restore the tag data. |
nn::nfp::ResultNeedFormat |
The tag data is corrupted and must be reset in amiibo Settings. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultNeedRetry |
An error occurred during mounting. The process might succeed if tried again. |
nn::nfp::ResultInvalidFormatVersion |
The tag version is not supported. Inform the user that the tag is not supported. |
Return Value | Description |
---|---|
nn::ResultSuccess |
The tag was successfully mounted. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNotSupported |
The tag is not an NFP tag. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultInvalidFormatVersion |
The tag version is not supported. Inform the user that the tag is not supported. |
6.4.1. Restoring Tags
When the nn::nfp::Mount
function returns nn::nfp::ResultNeedRestore
, you can restore the NFP tag from the application by calling the nn::nfp::Restore
function.
If a value of nn::nfp::ResultNeedRetry
is returned, the tag restoration process might succeed if nn::nfp::Restore
is called again.
Restoring a tag can take longer than a second.
If you want to try again, we recommend a retry interval of around 100 milliseconds.
The tag is restored using the data that was backed up by the NFP library when mounting the tag or immediately before writing to the tag. Consequently, the restored data is the data that the application is attempting to write, and not the data that was in the tag before the write process failed.
Return Value | Description |
---|---|
nn::ResultSuccess |
The tag was successfully restored. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNotSupported |
The tag is not an NFP tag. |
nn::nfp::ResultNeedRetry |
An error occurred during the write process. The function must be called again. |
nn::nfp::ResultNotBroken |
Restoration is unnecessary because the tag is not corrupted. |
nn::nfp::ResultOperationFailed |
An error occurred during writing. The tag data might not have been restored correctly. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultBackupError |
Failed to access the backup data. This NFP tag cannot be restored. |
6.5. Starting amiibo Settings
The following steps are required when starting amiibo Settings.
- Configure the information required to start amiibo Settings.
- Finalize the NFP library.
- Start amiibo Settings.
Start by configuring the nn::nfp::Parameter
structure with the information required to start amiibo Settings.
Call nn::nfp::InitializeParameter
to initialize the structure and then configure the input
member (nn::nfp::Input
structure) with the information required when starting amiibo Settings from an application.
When amiibo Settings detects the tag, it must determine whether it is the same tag specified by the application. Be sure to specify the tag information previously retrieved using nn::nfp::GetTagInfo
in the tagInfo
member.
Configure the other members (mode
, isRegistered
, registerInfo
, and commonInfo
) with the following values based on the use case.
Use Case | mode | isRegistered | registerInfo | commonInfo |
---|---|---|---|---|
The nn::nfp::Mount function returned nn::nfp::ResultNeedRestore . |
AMIIBO_SETTINGS_RESTORE |
false |
NULL |
NULL |
The nn::nfp::GetNfpRegisterInfo function returned nn::nfp::ResultNeedRegister . |
AMIIBO_SETTINGS_NICKNAME_OWNER |
false |
NULL |
Information retrieved using nn::nfp::GetNfpCommonInfo |
The nn::nfp::GetNfpRegisterInfo function returned nn::nfp::ResultSuccess , but the nickname was an empty string. |
AMIIBO_SETTINGS_NICKNAME_OWNER |
true |
Information retrieved using nn::nfp::GetNfpRegisterInfo |
Information retrieved using nn::nfp::GetNfpCommonInfo |
The nn::nfp::OpenApplicationArea function returned nn::nfp::ResultAccessIdMisMatch , so you want to delete the application-specific region. |
AMIIBO_SETTINGS_ERASE_GAMEDATA |
true |
Information retrieved using nn::nfp::GetNfpRegisterInfo |
Information retrieved using nn::nfp::GetNfpCommonInfo |
The mode
member takes an enumerator of the nn::nfp::AmiiboSettingsMode
enumeration and specifies the mode to use when starting amiibo Settings.
Definition | Description |
---|---|
AMIIBO_SETTINGS_RESTORE |
Restores a tag. |
AMIIBO_SETTINGS_NICKNAME_OWNER |
Registers the owner and sets a nickname. |
AMIIBO_SETTINGS_ERASE_GAMEDATA |
Erases the application-specific region. |
Call the nn::nfp::StartAmiiboSettings
function to start amiibo Settings. Before calling this function, you must finalize the NFP library by calling nn::nfp::Finalize
. Consequently, the NFP library must be reinitialized before use after returning from amiibo Settings.
If the nn::nfp::StartAmiiboSettings
returns false
, the startup of amiibo Settings failed. This result could be caused by the following factors.
- The NFP library was not finalized (by calling
nn::nfp::Finalize
). - The amiibo Settings applet is not installed (
nn::nfp::IsAmiiboSettingsAvailable
returnsfalse
). - The parameter settings are incorrect.
- The applet failed to start.
The Parameter.output.result
object stores whether any changes were made to the NFP tag in amiibo Settings. A value of nn::nfp::AMIIBO_SETTINGS_RESULT_SUCCESS
in this member indicates that changes were made to the NFP tag in amiibo Settings, while any other value indicates that no changes were made because the operation was canceled by the user or other reason.
Similar to other library applets, when control returns from nn::nfp::StartAmiiboSettings
, use the nn::applet::IsExpectedToProcessPowerButton
and nn::applet::IsExpectedToCloseApplication
functions to check whether the application has been requested to close because the POWER Button was pressed while the applet was running.
6.6. Accessing the NFP Tag
When a tag is successfully mounted, you can access the following information in the NFP tag.
- Shared region
- Application-specific region
The application cannot access the application-specific region unless it has the same access ID as the application that created the region.
If the tag was mounted with nn::nfp::MountRom
, the application can only access part of the shared region.
6.6.1. Accessing the Shared Region
Before using the information in the mounted NFP tag, use nn::nfp::GetNfpCommonInfo
or nn::nfp::GetNfpRomInfo
to get the information in the shared region to determine whether the NFP tag is compatible with the application.
If the tag was mounted with nn::nfp::MountRom
, the nn::nfp::GetNfpCommonInfo
function returns nn::nfp::ResultInvalidOperation
.
The shared region information retrieved by nn::nfp::GetNfpCommonInfo
is defined with the nn::nfp::CommonInfo
structure. A pointer to this structure must be passed to the function.
The shared region information retrieved by nn::nfp::GetNfpRomInfo
is defined with the nn::nfp::RomInfo
structure. A pointer to this structure must be passed to the function.
Only use the character ID (characterId
) to determine compatibility of the NFP tag. You must prepare a list of compatible character IDs in your application.
Using any information other than the character ID in an application is currently prohibited.
Return Value | Description |
---|---|
nn::ResultSuccess |
The information was successfully retrieved. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
Return Value | Description |
---|---|
nn::ResultSuccess |
The information was successfully retrieved. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
The shared region includes registration information that is retrieved using the nn::nfp::GetNfpRegisterInfo
function in addition to the information that is retrieved using nn::nfp:GetNfpCommonInfo
and nn::nfp::GetNfpRomInfo
.
If the tag was mounted with nn::nfp::MountRom
, the nn::nfp::GetNfpRegisterInfo
function returns nn::nfp::ResultInvalidOperation
.
Registration information is defined with the nn::nfp::RegisterInfo
structure. A pointer to the structure must be passed to nn::nfp::GetNfpRegisterInfo
.
If a value of nn::nfp::ResultNeedRegister
is returned, an owner has not yet been registered for the NFP tag in amiibo Settings. Start amiibo Settings if your application requires registration information.
For more information, see 6.5. Starting amiibo Settings.
The registration information includes data about the Mii that is registered as the owner (miiData
), the nickname of the amiibo (nickName
), and the font region required to display the nickname (fontRegion
).
To use the Mii data inside your application, you must include the Face Library. For more information about how to display Mii characters in your application, see the Face Library documentation.
Nicknames are stored using UTF-16 BE, so convert the endianness and encoding as required. The terminating character is NULL (0x0000
). When displaying a nickname in your application, handle the display of unsupported characters in a way that does not corrupt the display or prevent the application from proceeding. For example, you can use the system font specified in the font region or display substitute characters for characters that are not included in the application font.
If an owner is registered, Mii data is definitely available, but in some cases a nickname might not be set (it might be an empty string). If your application requires a nickname, start amiibo Settings using the same procedure described for nn::nfp::ResultNeedRegister
.
Applications that display the nickname must take care in the handling of amiibo nicknames and Mii nicknames. In particular, avoid displaying the nickname in a manner that implies it is the name of the owner Mii. Also be sure to display a substitute string such as "(owner name)'s amiibo," "(amiibo character name)," or just "amiiibo" if the nickname is not set.
Using country information (country
) in an application is currently prohibited.
Return Value | Description |
---|---|
nn::ResultSuccess |
The information was successfully retrieved. |
nn::nfp::ResultInvalidPointer |
The pointer passed as an argument is invalid. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNeedRegister |
The owner has not been registered in amiibo Settings. |
6.6.2. Accessing the Application-Specific Region
Access privileges for the application-specific region are controlled by the access ID. Before opening access to the application-specific region, you must first call nn::nfp::OpenApplicationArea
and check whether the application has access privileges.
If a value of nn::nfp::ResultAccessIdMisMatch
is returned, the application does not have access privileges because the application-specific area was created by a different access ID. In this case, both reading and writing are restricted. There is no way to delete the application-specific region from an application. If you want to use this region for your application, you must use amiibo Settings to delete it.
A return value of nn::nfp::ResultNeedCreate
means the mounted NFP tag does not have an application-specific region. Your application must create one.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. The application-specific region can be accessed. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultAccessIdMisMatch |
The application-specific area cannot be accessed because it was created by a different access ID. |
nn::nfp::ResultNeedCreate |
The application-specific region has not been created. |
6.6.2.1. Creating the Application-Specific Region
The application-specific region is created by calling the nn::nfp::CreateApplicationArea
function.
Use the nn::nfp::InitializeCreateInfo
function to initialize the nn::nfp::ApplicationAreaCreateInfo
structure that is passed to this function before setting the member variables.
If the data written to the application-specific region will also be read by Cafe, we recommend standardizing the byte order because the Cafe and CTR/SNAKE architectures have different endianness.
Creating the application-specific region can take longer than a second.
If you want to try the operation again, we recommend a retry interval of around 100 milliseconds.
Because the function performs the same operations as nn::nfp::Flush
, you do not need to call nn::nfp::Flush
after calling nn::nfp::CreateApplication
.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. The application-specific region has been created. |
nn::nfp::ResultInvalidArgument |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
nn::nfp::ResultInvalidPointer |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNotSupported |
The tag is not supported. The tag may have been switched with a different tag. |
nn::nfp::ResultAlreadyCreated |
The application-specific region has already been created. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultNeedRetry |
An error occurred during writing. The process might succeed if tried again. |
nn::nfp::ResultOperationFailed |
An error occurred during writing. The tag content may be corrupted. |
The following sample code retries the operation up to three times.
#define MY_ACCESS_ID 0x12345678 #define MY_APPLICATION_AREA_SIZE 128 nn::Result result; bit8 writeData[MY_APPLICATION_AREA_SIZE]; // First, initialize the settings information. nn::nfp::ApplicationAreaCreateInfo createInfo; result = nn::nfp::InitializeCreateInfo(&createInfo); if (result.IsFailure()) { // Error. return; } // Prepare the initialization data. { memset(writeData, NULL, sizeof(writeData)); // Write the data with big-endian byte order. writeData[0] = 'I'; writeData[1] = 'N'; writeData[2] = 'I'; writeData[3] = 'T'; writeData[4] = 0x00; writeData[5] = 0x00; writeData[6] = 0x00; writeData[7] = 0x01; } // Set the data required for initialization. createInfo.accessId = MY_ACCESS_ID; createInfo.pInitialData = writeData; createInfo.initialDataSize = sizeof(writeData); // Create the application-specific region. int retryCount = 0; while (true) { result = nn::nfp::CreateApplicationArea(createInfo); if (result.IsSuccess()) break; if (result.IsFailure()) { if (nn::nfp::ResultNeedRetry::Includes(result)) { // Retry up to 3 times. retryCount++; if (retryCount < 3) { // Wait 0.1 seconds before retrying. nn::os::Thread::Sleep(100); continue; } // Process failed. Handle by starting over from tag detection or a similar measure. } else if (nn::nfp::ResultAlreadyCreated::Includes(result)) { // The application-specific region has already been created. // Make sure the data is valid. The process succeeded if no problems are found. } else if (nn::nfp::ResultNotSupported::Includes(result)) { // The tag might have been switched. } else if (nn::nfp::ResultOperationFailed::Includes(result)) { // The tag might be corrupted. } else if (nn::nfp::ResultTagNotFound::Includes(result)) { // The tag might have been removed from the reader. } else if (nn::nfp::ResultInvalidOperation::Includes(result)) { // Entered a state where the function cannot be called. } else if (nn::nfp::ResultWifiOff::Includes(result)) { // Failed because the system is in wireless-disabled mode. } else if (nn::nfp::ResultSleep::Includes(result)) { // Failed because the system is in Sleep Mode. } else { // Other error. } return; } } // nn::nfp::Flush does not need to be called.
6.6.2.2. Reading the Application-Specific Region
To read the data that is written to the application-specific region, call the nn::nfp::ReadApplicationArea
function.
This lets you read the specified number of bytes from the beginning of the application-specific region. The maximum size of the data that can be read from the application-specific region can be retrieved from the applicationAreaSize
member of the CommonInfo
structure that can be retrieved using the nn::nfp::GetCommonInfo
function.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultInvalidPointer |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
nn::nfp::ResultInvalidArgument |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
6.6.2.3. Writing to the Application-Specific Region
The application-specific region is written to by calling the nn::nfp::WriteApplicationArea
function, followed by the nn::nfp::Flush
function.
The UID of the target NFP tag is required when calling nn::nfp::WriteApplicationArea
. Take the value of the tagId
member of the TagInfo
structure that was retrieved using nn::nfp::GetTagInfo
beforehand and pass it as an argument. We recommend encoding the data to be written to the application-specific region using the same big-endian encoding as the information written to the tag by the NFP library.
The data is not actually written to the application-specific region when nn::nfp::WriteApplicationArea
finishes executing. It is stored in a cache in the NFP library. The data is actually written to the application-specific region of the NFP tag when the nn::nfp::Flush
function is called.
Writing to the application-specific region of the NFP tag can take longer than a second.
If you want to try the operation again, we recommend a retry interval of around 100 milliseconds.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidArgument |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
nn::nfp::ResultInvalidPointer |
The process failed due to a problem in the argument that was specified. This result is an implementation error that must be fixed in the development phase. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultUidMisMatch |
The tag UID does not match the specified UID. |
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
nn::nfp::ResultNotSupported |
The tag is not supported. The tag may have been switched with a different tag. |
nn::nfp::ResultTagNotFound |
The tag could not be found. This result is caused by the tag leaving the range of communication or being swapped with a different tag. |
nn::nfp::ResultNeedRetry |
An error occurred during writing. The process might succeed if tried again. |
nn::nfp::ResultOperationFailed |
An error occurred during writing. The tag content may be corrupted. |
6.7. Unmounting a Tag
Tags are unmounted by calling the nn::nfp::Unmount
function.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
6.8. Stopping Tag Detection
Call the nn::nfp::StopDetection
function to stop tag detection.
If this function is called while a tag is mounted, the NFP library unmounts the tag.
If the tag is in a detected state when nn::nfp::StopDetection
is called, the application receives a tag loss notification.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidOperation |
The library is not in an appropriate state for calling this function. |
nn::nfp::ResultSleep |
The process failed because the system is entering Sleep Mode. |
nn::nfp::ResultWifiOff |
The process failed because the system is in wireless-disabled mode. |
6.9. Finalization
Call the nn::nfp::Finalize
function to finalize the NFP library. This function unmounts the tag, stops tag detection, and, if a tag had been detected, issues a tag loss notification.
Return Value | Description |
---|---|
nn::ResultSuccess |
The process was successful. |
nn::nfp::ResultInvalidOperation |
The library has already been finalized. |
6.10. Using in 3DS Applications
To use the NFP library in a 3DS application, you must implement code to support various 3DS features such as the HOME Button, Sleep Mode, and the POWER Button.
In addition, the NFC reader that is being prepared for CTR uses the infrared port on the CTR system. This necessitates the handling of notifications from the reader and when the reader is connected and disconnected.
6.10.1. Handling the HOME Button
When a HOME Button press is detected, call nn::nfp::Finalize
to put the NFP library into the NONE
state before transitioning to the HOME Menu. If this operation is omitted, the touch panel and NFC-related features will be unavailable to the HOME Menu or any applets started from the HOME Menu.
You can display the HOME Menu Disabled icon and not transition to the HOME Menu if it is necessary to protect the integrity of the tag data because, for example, the application is in the middle of writing data to the application-specific region.
Note: Data writing usually finishes in around one to two seconds.
// Check if transitioning to the HOME Menu. if (nn::applet::IsExpectedToProcessHomeButton()) { // Do not transition to the HOME Menu if writing to the NFP tag. if (_isNfpTagWritingInProgress()) { // Display the Home Menu Disabled icon. _displyHomeNixSign(); nn::applet::ClearHomeButtonState(); } else { // Stop access to the NFP tag. // Call nn::nfp::StopDetection to enter the INIT state before transitioning to the HOME Menu. _stopNfpTagAccess(); // Processes to run before transitioning to the HOME Menu. _prepareHomeMenu(); // Transition to the HOME Menu. nn::applet::ProcessHomeButtonAndWait(); if (nn::applet::IsExpectedToCloseApplication()) { // Close the application. _finalizeNfpTagAccess(); _closeApplication(); } // Processes after returning from the HOME Menu. _returnFromHomeMenu(); // Start tag detection here if resuming immediately. (Call nn::nfp::StartDetection.) if (_needRestartNfpTagAccess()) _startNfpTagAccess(); } }
6.10.2. Handling Sleep Mode Requests
The NFP library automatically changes the state to INIT
when the system transitions to Sleep Mode. However, we recommend having the application handle the transition if it is necessary to protect the integrity of the NFP tag data because, for example, the application is in the middle of writing to the application-specific region.
// Handling Sleep Mode Requests // Assumes the sleep query callback function will wait for the reply. if (nn::applet::IsExpectedToReplySleepQuery()) { // Check whether the NFP tag is being written to. if (_isNfpTagWritingInProgress()) { // Do not enter Sleep Mode if the NFP tag is being written to. } else { // Processes to run before Sleep Mode. _prepareSleep(); // Allow transition to Sleep Mode. nn::applet::ReplySleepQuery(nn::applet::REPLY_ACCEPT); // Wait for the event to be signaled by the wakeup callback, etc. _waitAwakeEvent(); // Processes for returning from Sleep Mode. _returnFromSleep(); // Start tag detection here if resuming immediately. (Call nn::nfp::StartDetection.) if (_needRestartNfpTagAccess()) _startNfpTagAccess(); } }
6.10.3. Handling the POWER Button
When the POWER Button is pressed, the application must quickly display the POWER Menu. However, the application can wait for the writing process to complete before displaying the POWER Menu if it is necessary to protect the integrity of the NFP tag data because, for example, the application is in the middle of writing data to the application-specific region. Data writing usually finishes in around one to two seconds.
Because the touch panel cannot be used on SNAKE during tag detection, the application must call nn::nfp::StopDetection
, nn::nfp::Disconnect
, or nn::nfp::Finalize
before displaying the POWER Menu.
// Handling the POWER Button if (nn::applet::IsExpectedToProcessPowerButton()) { // Check whether the NFP tag is being written to. if (_isNfpTagWritingInProgress()) { // Do not handle the POWER Button until finished writing to the NFP tag. } else { // Stop access to the NFP tag. _stopNfpTagAccess(); // Processes to run before transitioning to the POWER Menu. _preparePowerButtonMenu(); // Display the POWER Menu. nn::applet::ProcessPowerButtonAndWait(); if (nn::applet::IsExpectedCloseApplication()) { // Application finalization process. _finalizeNfpTagAccess(); _closeApplication(); } else { // Return from the POWER Menu. _returnFromPowerButtonMenu(); } } }
6.10.4. Implementation Requirements for CTR
If your application uses the NFC reader/writer for CTR, you must explicitly connect to the device from the application. Your application also must handle the connected and disconnected states of the device, in addition to the tag detection and loss notifications.
The following four functions are related to using the NFC reader/writer
nn::nfp::Connect
nn::nfp::GetTargetConnectionStatus
nn::nfp::GetConnectResult
nn::nfp::Disconnect
The nn::nfp::Connect
function requests that the NFP library establish a connection to the reader. This function is asynchronous. The nn::nfp::GetTargetConnectionStatus
function returns a value of nn::nfp::TARGET_CONNECTED
if the connection succeeded, or nn::nfp::TARGET_DISCONNECTED
if the connection failed.
If the nn::nfp::GetTargetConnectionStatus
function is called on SNAKE hardware, it always returns nn::nfp::TARGET_CONNECTED
.
If the NFC reader/write and CTR are correctly oriented, the connection process takes several hundred milliseconds to complete.
However, the connection can take a full second to complete if the system attempts to connect immediately after the NFC reader/writer is turned on due to an internal initialization process.
If the NFC reader/writer and CTR system are not correctly oriented, the system attempts to connect for one second until it times out, after which the state becomes nn::nfp::TARGET_DISCONNECTED
.
On SNAKE hardware, this function does nothing and returns nn::ResultSuccess
immediately.
If the connection fails, the nn::nfp::GetConnectResult
function is called to get the cause of the failure. Call this function after the nn::nfp::GetTargetConnectionStatus
function returns nn::nfp::TARGET_DISCONNECTED
.
On SNAKE hardware, the function ends immediately and returns nn::ResultSuccess
in both the parameter and the return value.
The nn::nfp::Disconnect
function is called by the application when you explicitly want to disconnect from the reader. This process takes between 10 and 100 milliseconds to complete.
If tag detection is currently in progress (nn::nfp::StartDetection
was called), the nn::nfp::StopDetection
function is called internally to stop tag detection. The entire process takes around 100 milliseconds to complete.
This function returns nn::nfp::ResultInvalidOperation
if called when the NFC reader/writer is already disconnected. We recommend handling notifications from the library to keep track of the connection status.
When called on SNAKE hardware, this function only stops tag detection (nn::nfp::StopDetection
) and returns success (nn::ResultSuccess
).
There is a one second timeout when the nn::nfp::Connect
function is called while the system cannot communicate with the NFC reader/writer. The time required for the system to determine that a connection has been lost is also one second.
Consequently, if the CTR is pointed away from the NFC reader/writer while the user is playing, the disconnect is detected in a relatively short amount of time.
If you do not want the user to be aware of the disconnection, you can implement the application to keep track of the connection state and automatically call nn::nfp::Connect
if the state is nn::nfp::TARGET_DISCONNECTED
.
The remaining battery life of the NFC reader/writer is only checked once, immediately after it is connected to the CTR using the nn::nfp::Connect
function. It is not checked again until the device is disconnected.
Consequently, if the NFC reader/writer continuously detects and writes tags for several minutes without updating the connection state, it might suddenly turn off without the red remaining battery life warning LED turning on.
If your application continuously detects and writes tags, we recommend calling the nn::nfp::Disconnect
and nn::nfp::Connect
functions on a regular basis (for example, once per minute).
For certain battery types, the LED might light up blue when the power is turned back on after the device loses power as described above. This is by design.
If you continue to use FANGATE without changing the batteries, the LED will turn red before the device loses power again.
The following sample code shows how to start and stop tag detection.
bool _willTerminate = false; bool _connected = false; nn::Result _lastResult = nn::ResultSuccess(); nn::os::Event _eventActivate; nn::os::Event _eventDeactivate; nn::nfp::TargetConnectionStatus _targetConnectionStatus; // Start tag detection. nn::Result _startDetection() { // CTR-specific code. if (!nn::os::IsRunOnSnake()) { // Connect to external NFC device. if (!_connected) { _lastResult = nn::nfp::Connect(&_eventConnect, &_eventDisconnect); if (_lastResult.IsSuccess()) { // Wait for connection process to complete. while (1) { nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(500)); nn::nfp::GetTargetConnectionStatus(&_targetConnectionStatus); if (_targetConnectionStatus == nn::nfp::TARGET_CONNECTED) { // Connection successful. _connected = true; break; } else if (_targetConnectionStatus == nn::nfp::TARGET_DISCONNECTED) { // Connection failed or timed out. _connected = false; nn::nfp::GetConnectResult(&_lastResult); return _lastResult; } } } else { if (nn::nfp::ResultInvalidOperation::Includes(_lastResult)) { // Abnormal state. } else { // Stop on a panic for any other error. NN_PANIC_WITH_RESULT(_lastResult); } return _lastResult; } } } // Start detection. _lastResult = nn::nfp::StartDetection(); if (_lastResult.IsSuccess()) { // Process succeeded. // Prompt the user to touch the tag to the touchpoint. } else if (nn::nfp::ResultWifiOff::Includes(_lastResult)) { // Wireless-disabled mode. } else if (nn::nfp::ResultSleep::Includes(_lastResult)) { // Sleep Mode. } else if (nn::nfp::ResultInvalidOperation::Includes(_lastResult)) { // Abnormal state. } else { // Stop on a panic for any other error. NN_PANIC_WITH_RESULT(_lastResult); } return _lastResult; } // Stop tag detection. nn::Result _stopDetection(bool forceDisconnect = false) { // Stop detection. _lastResult = nn::nfp::StopDetection(); if (_lastResult.IsSuccess()) { // Success. } else if (nn::nfp::ResultWifiOff::Includes(_lastResult)) { // Wireless-disabled mode. } else if (nn::nfp::ResultSleep::Includes(_lastResult)) { // Sleep Mode. } else if (nn::nfp::ResultInvalidOperation::Includes(_lastResult)) { // Abnormal state. } else { // Stop on a panic for any other error. NN_PANIC_WITH_RESULT(_lastResult); } // CTR-specific code. if (!nn::os::IsRunOnSnake()) { // Disconnect external NFC device. if (forceDisconnect && _connected) { _connected = false; _lastResult = nn::nfp::Disconnect(); if (_lastResult.IsSuccess()) { // Success. } else if (nn::nfp::ResultInvalidOperation::Includes(_lastResult)) { // Abnormal state. } else { // Stop on a panic for any other error. NN_PANIC_WITH_RESULT(_lastResult); } } } return _lastResult; } // Thread function that waits for notifications from the NFP library. void _procTagDetection() { const int waitMilliSeconds = 500; nn::os::WaitObject* events[2] = { &_eventActivate, &_eventDeactivate }; while (!_willTerminate) { const int eventIndex = nn::os::WaitObject::WaitAny( events, 2, nn::fnd::TimeSpan::FromMilliSeconds(waitMilliSeconds)); if (eventIndex == 0) { _activate(); } else if (eventIndex == 1) { _deactivate(); } else { nn::nfp::TargetConnectionStatus currentTargetConnectionStatus; nn::nfp::GetTargetConnectionStatus(¤tTargetConnectionStatus); if( _targetConnectionStatus != currentTargetConnectionStatus ) { if (currentTargetConnectionStatus == nn::nfp::TARGET_CONNECTED) { _connected = true; } else if (currentTargetConnectionStatus == nn::nfp::TARGET_DISCONNECTED) { _connected = false; } _targetConnectionStatus = currentTargetConnectionStatus; } } } }