Added new example, PN53x chips will now emulate NDEF tag! not in build-script yet

This commit is contained in:
Roel Verdult 2010-09-28 16:15:59 +00:00
parent 5efa9e2cdb
commit 6dfe88113e
10 changed files with 159 additions and 18 deletions

107
examples/nfc-emulate-ndef.c Normal file
View file

@ -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 <http://www.gnu.org/licenses/>
*/
/**
* @file nfc-emulate.c
* @brief
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <nfc/nfc.h>
#include <nfc/nfc-messages.h>
#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);
}

View file

@ -106,7 +106,7 @@ main (int argc, char *argv[])
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n"); 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 ("[+] 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"); 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"); printf ("Error: Could not come out of auto-emulation, no command was received\n");
return 1; return 1;
} }

View file

@ -125,7 +125,7 @@ main (int argc, char *argv[])
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n"); 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 ("[+] 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"); 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"); ERR ("%s", "Initialization of NFC emulator failed");
nfc_disconnect (pndTag); nfc_disconnect (pndTag);
return EXIT_FAILURE; return EXIT_FAILURE;

View file

@ -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" // 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. // 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; return EXIT_FAILURE;
printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n"); printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");

View file

@ -59,7 +59,7 @@ main (int argc, const char *argv[])
errx (1, "usage: %s", argv[0]); 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"); printf ("unable to connect or initialize\n");
return 1; return 1;
} }

View file

@ -262,6 +262,19 @@ typedef union {
nfc_dep_info_t ndi; nfc_dep_info_t ndi;
} nfc_target_info_t; } 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 * @enum nfc_target_type_t
* @brief NFC target type enumeration * @brief NFC target type enumeration

View file

@ -90,7 +90,7 @@ extern "C" {
byte_t * pbtRxPar); byte_t * pbtRxPar);
/* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ /* 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_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_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, NFC_EXPORT bool nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,

View file

@ -910,12 +910,10 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons
} }
bool 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]; byte_t abtRx[MAX_FRAME_LEN];
size_t szRxLen; size_t szRxLen;
uint8_t ui8rcc;
uint8_t ui8Bits;
// Save the current configuration settings // Save the current configuration settings
bool bCrc = pnd->bCrc; bool bCrc = pnd->bCrc;
bool bPar = pnd->bPar; 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 // Clear the target init struct, reset to all zeros
memset (abtCmd + 2, 0x00, 37); memset (abtCmd + 2, 0x00, 37);
// Store the target mode in the initialization params
abtCmd[2] = tm;
// Set ATQA (SENS_RES) // Set ATQA (SENS_RES)
abtCmd[3] = 0x04; abtCmd[3] = 0x04;
abtCmd[4] = 0x00; abtCmd[4] = 0x00;
@ -938,6 +939,29 @@ pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits)
abtCmd[6] = 0xb0; abtCmd[6] = 0xb0;
abtCmd[7] = 0x0b; 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 // Make sure the CRC & parity are handled by the device, this is needed for target_init to work properly
if (!bCrc) if (!bCrc)
pn53x_configure ((nfc_device_t *) pnd, NDO_HANDLE_CRC, true); 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)) if (!pn53x_transceive (pnd, abtCmd, 39, abtRx, &szRxLen))
return false; return false;
// Get the last bit-count that is stored in the received byte // Save the received byte count
if (!pn53x_get_reg (pnd, REG_CIU_CONTROL, &ui8rcc)) *pszRxLen = szRxLen - 1;
return false;
ui8Bits = ui8rcc & SYMBOL_RX_LAST_BITS;
// 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 // 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) // Restore the CRC & parity setting to the original value (if needed)
if (!bCrc) if (!bCrc)

View file

@ -66,6 +66,7 @@
# define SYMBOL_PARAM_fAutomaticRATS 0x10 # define SYMBOL_PARAM_fAutomaticRATS 0x10
# define SYMBOL_PARAM_fAutomaticATR_RES 0x04 # define SYMBOL_PARAM_fAutomaticATR_RES 0x04
# define SYMBOL_PARAM_fISO14443_4_PICC 0x20
// Internal parameters flags // Internal parameters flags
# define PARAM_NONE 0x00 # 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, bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen,
byte_t * pbtRx, size_t * pszRxLen); 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_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_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, bool pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,

View file

@ -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. * @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 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; pnd->iLastError = 0;
return pn53x_target_init (pnd, pbtRx, pszRxBits); return pn53x_target_init (pnd, tm, pbtRx, pszRxLen);
} }
/** /**