diff --git a/examples/nfc-emulate-ndef.c b/examples/nfc-emulate-ndef.c new file mode 100644 index 0000000..a109368 --- /dev/null +++ b/examples/nfc-emulate-ndef.c @@ -0,0 +1,107 @@ +/*- + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2009, Roel Verdult + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +/** + * @file nfc-emulate.c + * @brief + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include +#include +#include +#include +#include + +#include + +#include +#include "nfc-utils.h" + +#define MAX_FRAME_LEN 264 + +static byte_t abtRx[MAX_FRAME_LEN]; +static size_t szRxLen; +static nfc_device_t *pnd; +static bool quiet_output = false; + +#define SYMBOL_PARAM_fISO14443_4_PICC 0x20 + +bool +transmit_bytes (const byte_t * pbtTx, const size_t szTxLen) +{ + // Show transmitted command + if (!quiet_output) { + printf ("Tx: "); + print_hex (pbtTx, szTxLen); + } + + // Transmit the command bytes + pn53x_set_parameters(pnd,0); + if (!nfc_target_send_bytes(pnd, pbtTx, szTxLen)) + return false; + pn53x_set_parameters(pnd,SYMBOL_PARAM_fISO14443_4_PICC); + + if (!pn53x_target_receive_bytes(pnd,abtRx,&szRxLen)) + return false; + + // Show received answer + if (!quiet_output) { + printf ("Rx: "); + print_hex (abtRx, szRxLen); + } + // Succesful transfer + return true; +} + +int +main (int argc, char *argv[]) +{ + // Try to open the NFC reader + pnd = nfc_connect (NULL); + + if (pnd == NULL) { + printf ("Error connecting NFC reader\n"); + return 1; + } + + printf ("[+] Connected to NFC reader: %s\n", pnd->acName); + printf ("[+] Emulating NDEF tag now, please touch it with a second NFC device\n"); + if (!nfc_target_init (pnd, NTM_PICC, abtRx, &szRxLen)) { + printf ("Error: Could not come out of auto-emulation, no command was received\n"); + return 1; + } + + transmit_bytes("\x0a\x00\x6a\x87",4); + transmit_bytes("\x0b\x00\x6a\x87",4); + transmit_bytes("\x0a\x00\x90\x00",4); + transmit_bytes("\x0b\x00\x90\x00",4); + transmit_bytes("\x0a\x00\x00\x0f\x10\x00\x3b\x00\x34\x04\x06\xe1\x04\x0e\xe0\x00\x00\x90\x00",19); + transmit_bytes("\x0b\x00\x90\x00",4); + transmit_bytes("\x0a\x00\x00\x21\x90\x00",6); + transmit_bytes("\x0b\x00\xd1\x02\x1c\x53\x70\x91\x01\x09\x54\x02\x65\x6e\x4c\x69\x62\x6e\x66\x63\x51\x01\x0b\x55\x03\x6c\x69\x62\x6e\x66\x63\x2e\x6f\x72\x67\x90\x00",37); + transmit_bytes("\xca\x00",2); + + nfc_disconnect(pnd); + exit (EXIT_SUCCESS); +} + diff --git a/examples/nfc-emulate.c b/examples/nfc-emulate.c index a04fd08..799614b 100644 --- a/examples/nfc-emulate.c +++ b/examples/nfc-emulate.c @@ -106,7 +106,7 @@ main (int argc, char *argv[]) printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n"); printf ("[+] To do this, please send any command after the anti-collision\n"); printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n"); - if (!nfc_target_init (pnd, abtRecv, &szRecvBits)) { + if (!nfc_target_init (pnd, NTM_PASSIVE, abtRecv, &szRecvBits)) { printf ("Error: Could not come out of auto-emulation, no command was received\n"); return 1; } diff --git a/examples/nfc-relay.c b/examples/nfc-relay.c index 28d00d5..be38d64 100644 --- a/examples/nfc-relay.c +++ b/examples/nfc-relay.c @@ -125,7 +125,7 @@ main (int argc, char *argv[]) printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n"); printf ("[+] To do this, please send any command after the anti-collision\n"); printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n"); - if (!nfc_target_init (pndTag, abtReaderRx, &szReaderRxBits)) { + if (!nfc_target_init (pndTag, NTM_PASSIVE, abtReaderRx, &szReaderRxBits)) { ERR ("%s", "Initialization of NFC emulator failed"); nfc_disconnect (pndTag); return EXIT_FAILURE; diff --git a/examples/nfc-sam.c b/examples/nfc-sam.c index 817103b..2107400 100644 --- a/examples/nfc-sam.c +++ b/examples/nfc-sam.c @@ -207,7 +207,7 @@ main (int argc, const char *argv[]) // FIXME: it does not work as expected...Probably the issue is in "nfc_target_init" // which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc. - if (!nfc_target_init (pnd, abtRx, &szRxLen)) + if (!nfc_target_init (pnd, NTM_PICC, abtRx, &szRxLen)) return EXIT_FAILURE; printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n"); diff --git a/examples/nfcip-target.c b/examples/nfcip-target.c index 4205df6..a8456f3 100644 --- a/examples/nfcip-target.c +++ b/examples/nfcip-target.c @@ -59,7 +59,7 @@ main (int argc, const char *argv[]) errx (1, "usage: %s", argv[0]); } - if (!pnd || !nfc_target_init (pnd, abtRecv, &szRecvBits)) { + if (!pnd || !nfc_target_init (pnd, NTM_DEP, abtRecv, &szRecvBits)) { printf ("unable to connect or initialize\n"); return 1; } diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 048b0ea..ae4c12b 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -262,6 +262,19 @@ typedef union { nfc_dep_info_t ndi; } nfc_target_info_t; +/** + * @enum nfc_target_mode_t + * @brief NFC target type enumeration + */ +typedef enum { + /** Configure the PN532 to accept to be initialized only in passive mode */ + NTM_PASSIVE = 0x01, + /** configure the PN532 to accept to be initialized only as DEP target */ + NTM_DEP = 0x02, + /** configure the PN532 to accept to be initialized only as ISO/IEC14443-4 PICC */ + NTM_PICC = 0x04 +} nfc_target_mode_t; + /** * @enum nfc_target_type_t * @brief NFC target type enumeration diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index b8dbb42..9f11878 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -90,7 +90,7 @@ extern "C" { byte_t * pbtRxPar); /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ - NFC_EXPORT bool nfc_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits); + NFC_EXPORT bool nfc_target_init (nfc_device_t * pnd, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen); NFC_EXPORT bool nfc_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen); NFC_EXPORT bool nfc_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen); NFC_EXPORT bool nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 20186eb..9a4fcc4 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -910,12 +910,10 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons } bool -pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits) +pn53x_target_init (nfc_device_t * pnd, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; size_t szRxLen; - uint8_t ui8rcc; - uint8_t ui8Bits; // Save the current configuration settings bool bCrc = pnd->bCrc; bool bPar = pnd->bPar; @@ -926,6 +924,9 @@ pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits) // Clear the target init struct, reset to all zeros memset (abtCmd + 2, 0x00, 37); + // Store the target mode in the initialization params + abtCmd[2] = tm; + // Set ATQA (SENS_RES) abtCmd[3] = 0x04; abtCmd[4] = 0x00; @@ -938,6 +939,29 @@ pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits) abtCmd[6] = 0xb0; abtCmd[7] = 0x0b; + // Configure the target corresponding to the requested mode + switch(tm) + { + case NTM_PASSIVE: + pn53x_set_parameters(pnd,0); + pn53x_configure(pnd,NDO_EASY_FRAMING,false); + break; + + case NTM_DEP: + pn53x_set_parameters(pnd,SYMBOL_PARAM_fAutomaticATR_RES); + pn53x_configure(pnd,NDO_EASY_FRAMING,true); + break; + + case NTM_PICC: + pn53x_set_parameters(pnd,SYMBOL_PARAM_fISO14443_4_PICC); + pn53x_configure(pnd,NDO_EASY_FRAMING,false); + break; + + default: + // Unknown mode + return false; + } + // Make sure the CRC & parity are handled by the device, this is needed for target_init to work properly if (!bCrc) pn53x_configure ((nfc_device_t *) pnd, NDO_HANDLE_CRC, true); @@ -953,15 +977,11 @@ pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits) if (!pn53x_transceive (pnd, abtCmd, 39, abtRx, &szRxLen)) return false; - // Get the last bit-count that is stored in the received byte - if (!pn53x_get_reg (pnd, REG_CIU_CONTROL, &ui8rcc)) - return false; - ui8Bits = ui8rcc & SYMBOL_RX_LAST_BITS; + // Save the received byte count + *pszRxLen = szRxLen - 1; - // We are sure the parity is handled by the PN53X chip, so we handle it this way - *pszRxBits = ((szRxLen - 1 - ((ui8Bits == 0) ? 0 : 1)) * 8) + ui8Bits; // Copy the received bytes - memcpy (pbtRx, abtRx + 1, szRxLen - 1); + memcpy (pbtRx, abtRx + 1, *pszRxLen); // Restore the CRC & parity setting to the original value (if needed) if (!bCrc) diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 3efebc4..0b1b029 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -66,6 +66,7 @@ # define SYMBOL_PARAM_fAutomaticRATS 0x10 # define SYMBOL_PARAM_fAutomaticATR_RES 0x04 +# define SYMBOL_PARAM_fISO14443_4_PICC 0x20 // Internal parameters flags # define PARAM_NONE 0x00 @@ -131,7 +132,7 @@ bool pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtT bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen); -bool pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits); +bool pn53x_target_init (nfc_device_t * pnd, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen); bool pn53x_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar); bool pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen); bool pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 457a69e..262c1f7 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -544,11 +544,11 @@ nfc_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const s * @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used. */ bool -nfc_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits) +nfc_target_init (nfc_device_t * pnd, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen) { pnd->iLastError = 0; - return pn53x_target_init (pnd, pbtRx, pszRxBits); + return pn53x_target_init (pnd, tm, pbtRx, pszRxLen); } /**