int main(int argc, const char *argv[]) { (void) argc; (void) argv; nfc_context *context; nfc_init(&context); if (context == NULL) { ERR("Unable to init libnfc (malloc)"); exit(EXIT_FAILURE); } // Display libnfc version const char *acLibnfcVersion = nfc_version(); printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion); // Open using the first available NFC device nfc_device *pnd; pnd = nfc_open(context, NULL); if (pnd == NULL) { ERR("%s", "Unable to open NFC device."); nfc_exit(context); exit(EXIT_FAILURE); } printf("NFC device: %s opened\n", nfc_device_get_name(pnd)); // Print the example's menu printf("\nSelect the communication mode:\n"); printf("[1] Virtual card mode.\n"); printf("[2] Wired card mode.\n"); printf("[3] Dual card mode.\n"); printf(">> "); // Take user's choice int input = getchar(); printf("\n"); if ((input < '1') || (input > '3')) { ERR("%s", "Invalid selection."); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } /* * '1' -> "Virtual mode" (0x02) * '2' -> "Wired card" (0x03) * '3' -> "Dual card" (0x04) */ int iMode = input - '0' + 0x01; pn532_sam_mode mode = iMode; // Connect with the SAM switch (mode) { case PSM_VIRTUAL_CARD: { // FIXME Its a private pn53x function if (pn532_SAMConfiguration(pnd, mode, 0) < 0) { nfc_perror(pnd, "pn53x_SAMConfiguration"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } printf("Now the SAM is readable for 1 minute from an external reader.\n"); wait_one_minute(); } break; case PSM_WIRED_CARD: { // Set opened NFC device to initiator mode if (nfc_initiator_init_secure_element(pnd) < 0) { nfc_perror(pnd, "nfc_initiator_init_secure_element"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } // Let the reader only try once to find a tag if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) { nfc_perror(pnd, "nfc_device_set_property_bool"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } // Read the SAM's info const nfc_modulation nmSAM = { .nmt = NMT_ISO14443A, .nbr = NBR_106, }; nfc_target nt; int res; if ((res = nfc_initiator_select_passive_target(pnd, nmSAM, NULL, 0, &nt)) < 0) { nfc_perror(pnd, "nfc_initiator_select_passive_target"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } else if (res == 0) { ERR("No SAM found."); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } else if (res == 1) { printf("The following ISO14443A tag (SAM) was found:\n"); print_nfc_target(&nt, true); } else { ERR("%s", "More than one ISO14442 tag found as SAM."); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } } break; case PSM_DUAL_CARD: { // FIXME Its a private pn53x function if (pn532_SAMConfiguration(pnd, mode, 0) < 0) { nfc_perror(pnd, "pn53x_SAMConfiguration"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } uint8_t abtRx[MAX_FRAME_LEN]; nfc_target nt = { .nm = { .nmt = NMT_ISO14443A, .nbr = NBR_UNDEFINED, }, .nti = { .nai = { .abtAtqa = { 0x04, 0x00 }, .abtUid = { 0x08, 0xad, 0xbe, 0xef }, .btSak = 0x20, .szUidLen = 4, .szAtsLen = 0, }, }, };
int main (int argc, const char *argv[]) { nfc_device_t *pnd; (void) argc; (void) argv; // Display libnfc version const char *acLibnfcVersion = nfc_version (); printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion); // Connect using the first available NFC device pnd = nfc_connect (NULL); if (pnd == NULL) { ERR ("%s", "Unable to connect to NFC device."); return EXIT_FAILURE; } printf ("Connected to NFC device: %s\n", pnd->acName); // Print the example's menu printf ("\nSelect the communication mode:\n"); printf ("[1] Virtual card mode.\n"); printf ("[2] Wired card mode.\n"); printf ("[3] Dual card mode.\n"); printf (">> "); // Take user's choice char input = getchar (); int mode = input - '0' + 1; printf ("\n"); if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) { ERR ("%s", "Invalid selection."); return EXIT_FAILURE; } // Connect with the SAM sam_connection (pnd, mode); switch (mode) { case VIRTUAL_CARD_MODE: { // FIXME after the loop the device doesn't respond to host commands... printf ("Now the SAM is readable for 1 minute from an external reader.\n"); wait_one_minute (); } break; case WIRED_CARD_MODE: { nfc_target_t nt; // Set connected NFC device to initiator mode nfc_initiator_init (pnd); // Drop the field for a while if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { nfc_perror (pnd, "nfc_configure"); exit (EXIT_FAILURE); } // Let the reader only try once to find a tag if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { nfc_perror (pnd, "nfc_configure"); exit (EXIT_FAILURE); } // Enable field so more power consuming cards can power themselves up if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { nfc_perror (pnd, "nfc_configure"); exit (EXIT_FAILURE); } // Read the SAM's info const nfc_modulation_t nmSAM = { .nmt = NMT_ISO14443A, .nbr = NBR_106, }; if (!nfc_initiator_select_passive_target (pnd, nmSAM, NULL, 0, &nt)) { nfc_perror (pnd, "nfc_initiator_select_passive_target"); ERR ("%s", "Reading of SAM info failed."); return EXIT_FAILURE; } printf ("The following ISO14443A tag (SAM) was found:\n\n"); print_nfc_iso14443a_info (nt.nti.nai, true); } break; case DUAL_CARD_MODE: { byte_t abtRx[MAX_FRAME_LEN]; size_t szRx; nfc_target_t nt = { .nm.nmt = NMT_ISO14443A, .nm.nbr = NBR_UNDEFINED, .nti.nai.abtAtqa = { 0x04, 0x00 }, .nti.nai.abtUid = { 0x08, 0xad, 0xbe, 0xef }, .nti.nai.btSak = 0x20, .nti.nai.szUidLen = 4, .nti.nai.szAtsLen = 0, }; printf ("Now both, NFC device (configured as target) and SAM are readables from an external NFC initiator.\n"); printf ("Please note that NFC device (configured as target) stay in target mode until it receive RATS, ATR_REQ or proprietary command.\n"); if (!nfc_target_init (pnd, &nt, abtRx, &szRx)) { nfc_perror(pnd, "nfc_target_init"); return EXIT_FAILURE; } // wait_one_minute (); } break; } // Disconnect from the SAM sam_connection (pnd, NORMAL_MODE); // Disconnect from NFC device nfc_disconnect (pnd); return EXIT_SUCCESS; }