switch-examples/nfc/source/main.c
2019-02-05 23:11:03 +01:00

153 lines
4.9 KiB
C

// Include the most common headers from the C standard library
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
// Include the main libnx system header, for Switch development
#include <switch.h>
#include "amiibo_char.h"
// See also libnx nfc.h.
#define PRINT_UPD(fmt, ...) ({ \
printf(fmt, ## __VA_ARGS__); \
consoleUpdate(NULL); \
})
// Indefinitely wait for an event to be signaled
// Break when + is pressed, or if the application should quit (in this case, return value will be non-zero)
Result eventWaitLoop(Event *event) {
Result rc = 0;
while (appletMainLoop()) {
rc = eventWait(event, 0);
hidScanInput();
if (R_SUCCEEDED(rc) || (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_PLUS))
break;
}
return rc;
}
// Main program entrypoint
int main(int argc, char* argv[])
{
Result rc = 0;
// This example uses a text console, as a simple way to output text to the screen.
// If you want to write a software-rendered graphics application,
// take a look at the graphics/simplegfx example, which uses the libnx Framebuffer API instead.
// If on the other hand you want to write an OpenGL based application,
// take a look at the graphics/opengl set of examples, which uses EGL instead.
consoleInit(NULL);
PRINT_UPD("NFC example program.\n");
PRINT_UPD("Scan an amiibo tag to display its character.\n");
PRINT_UPD("Press + to exit.\n\n");
// Initialize the nfp:user and nfc:user services.
rc = nfpuInitialize();
// Check if NFC is enabled. If not, wait until it is.
if (R_SUCCEEDED(rc)) {
bool nfc_enabled = false;
rc = nfpuIsNfcEnabled(&nfc_enabled);
if (R_SUCCEEDED(rc) && !nfc_enabled) {
// Get the availability change event. This is signaled when a change in NFC availability happens.
Event availability_change_event = {0};
rc = nfpuAttachAvailabilityChangeEvent(&availability_change_event);
// Wait for a change in availability.
if (R_SUCCEEDED(rc)) {
PRINT_UPD("NFC is disabled. Please turn off plane mode via the quick settings to continue.\n");
rc = eventWaitLoop(&availability_change_event);
}
eventClose(&availability_change_event);
}
}
if (R_FAILED(rc))
goto fail_0;
// Get the handle of the first controller with NFC capabilities.
HidControllerID controller = 0;
if (R_SUCCEEDED(rc)) {
u32 device_count;
rc = nfpuListDevices(&device_count, &controller, 1);
}
if (R_FAILED(rc))
goto fail_0;
// Get the activation event. This is signaled when a tag is detected.
Event activate_event = {0};
if (R_FAILED(nfpuAttachActivateEvent(controller, &activate_event)))
goto fail_1;
// Get the deactivation event. This is signaled when a tag is removed.
Event deactivate_event = {0};
if (R_FAILED(nfpuAttachDeactivateEvent(controller, &deactivate_event)))
goto fail_2;
// Start the detection of tags.
rc = nfpuStartDetection(controller);
if (R_SUCCEEDED(rc))
PRINT_UPD("Scanning for a tag...\n");
// Wait until a tag is detected.
if (R_SUCCEEDED(rc)) {
rc = eventWaitLoop(&activate_event);
if (R_SUCCEEDED(rc))
PRINT_UPD("A tag was detected, please do not remove it from the NFC spot.\n");
}
// If a tag was successfully detected, load it into memory.
if (R_SUCCEEDED(rc))
rc = nfpuMount(controller, NfpuDeviceType_Amiibo, NfpuMountTarget_All);
// Retrieve the model info data, which contains the amiibo id.
if (R_SUCCEEDED(rc)) {
NfpuModelInfo model_info = {0};
rc = nfpuGetModelInfo(controller, &model_info);
if (R_SUCCEEDED(rc))
PRINT_UPD("Amiibo character: %s.\n", get_amiibo_char(model_info));
}
if (R_SUCCEEDED(rc)) {
PRINT_UPD("You can now remove the tag.\n");
eventWaitLoop(&deactivate_event);
}
// If an error happened during detection/reading, print it.
if (R_FAILED(rc))
PRINT_UPD("Error: 0x%x (%04d-%04d).\n", rc, (R_MODULE(rc) | 2000), (R_VALUE(rc) >> 9));
// Unmount the tag.
nfpuUnmount(controller);
// Stop the detection of tags.
nfpuStopDetection(controller);
// Wait for the user to explicitely exit.
PRINT_UPD("Press + to exit.\n");
while (appletMainLoop()) {
hidScanInput();
if (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_PLUS)
break;
}
// Cleanup.
fail_2:
eventClose(&deactivate_event);
fail_1:
eventClose(&activate_event);
fail_0:
nfpuExit();
// Deinitialize and clean up resources used by the console (important!)
consoleExit(NULL);
return 0;
}