diff --git a/examples/Makefile.am b/examples/Makefile.am
index 830e456..6c920e4 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -2,6 +2,7 @@ bin_PROGRAMS = \
nfc-anticol \
nfc-emulate \
nfc-emulate-ndef \
+ nfc-emulate-tag \
nfc-list \
nfc-mfclassic \
nfc-mfultralight \
@@ -51,7 +52,15 @@ nfc_emulate_LDADD = $(top_builddir)/libnfc/libnfc.la \
nfc_emulate_ndef_SOURCES = nfc-emulate-ndef.c
nfc_emulate_ndef_LDADD = $(top_builddir)/libnfc/libnfc.la \
- libnfcutils.la
+ libnfcutils.la
+
+nfc_emulate_tag_SOURCES = nfc-emulate-tag.c
+nfc_emulate_tag_LDADD = $(top_builddir)/libnfc/libnfc.la \
+ libnfcutils.la
+
+nfc_sam_SOURCES = nfc-sam.c
+nfc_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
+ libnfcutils.la
nfcip_target_SOURCES = nfcip-target.c
nfcip_target_LDADD = $(top_builddir)/libnfc/libnfc.la
@@ -61,17 +70,13 @@ nfcip_initiator_LDADD = $(top_builddir)/libnfc/libnfc.la
pn53x_diagnose_SOURCES = pn53x-diagnose.c
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
- libnfcutils.la
+ libnfcutils.la
pn53x_tamashell_SOURCES = pn53x-tamashell.c
pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
-nfc_sam_SOURCES = nfc-sam.c
-nfc_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
- libnfcutils.la
-
dist_man_MANS = nfc-anticol.1 nfc-emulate.1 nfc-list.1 nfc-mfclassic.1 nfc-mfultralight.1 nfc-relay.1 nfc-sam.1
EXTRA_DIST = CMakeLists.txt
diff --git a/examples/nfc-emulate-ndef.c b/examples/nfc-emulate-ndef.c
index 2e9f6b2..0dd6501 100644
--- a/examples/nfc-emulate-ndef.c
+++ b/examples/nfc-emulate-ndef.c
@@ -91,7 +91,17 @@ main (int argc, char *argv[])
printf ("[+] Connected to NFC device: %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)) {
+
+ nfc_target_t nt = {
+ .ntt = NTT_MIFARE,
+ .nti.nai.abtAtqa = { 0x00, 0x04 },
+ .nti.nai.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 4,
+ .nti.nai.szAtsLen = 0,
+ };
+
+ if (!nfc_target_init (pnd, NTM_PICC, nt, abtRx, &szRxLen)) {
nfc_perror (pnd, "nfc_target_init");
ERR("Could not come out of auto-emulation, no command was received");
return EXIT_FAILURE;
diff --git a/examples/nfc-emulate-tag.c b/examples/nfc-emulate-tag.c
new file mode 100644
index 0000000..a16f198
--- /dev/null
+++ b/examples/nfc-emulate-tag.c
@@ -0,0 +1,152 @@
+/*-
+ * Public platform independent Near Field Communication (NFC) library
+ *
+ * Copyright (C) 2010, Romuald Conty
+ *
+ * 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-ndef.c
+ * @brief Emulate a tag
+ */
+
+#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;
+
+bool
+target_io( const nfc_target_t nt, const byte_t * pbtInput, const size_t szInput, byte_t * pbtOutput, size_t *pszOutput )
+{
+ bool loop = true;
+ *pszOutput = 0;
+
+ // Show transmitted command
+ if (!quiet_output) {
+ printf (" In: ");
+ print_hex (pbtInput, szInput);
+ }
+ if(szInput) {
+ switch(pbtInput[0]) {
+ case 0xe0: // RATS
+ // Send ATS
+ *pszOutput = nt.nti.nai.szAtsLen + 1;
+ pbtOutput[0] = nt.nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Lenght as first byte
+ if(nt.nti.nai.szAtsLen) {
+ memcpy(pbtOutput+1, nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
+ }
+ break;
+ default: // Unknown
+ if (!quiet_output) {
+ printf("Unknown frame, emulated target abort.\n");
+ }
+ loop = false;
+ }
+ }
+ // Show transmitted command
+ if (!quiet_output) {
+ printf (" Out: ");
+ print_hex (pbtOutput, *pszOutput);
+ }
+ return loop;
+}
+
+bool
+nfc_target_emulate_tag(nfc_device_t* pnd, const nfc_target_t nt)
+{
+ size_t szTx;
+ byte_t abtTx[MAX_FRAME_LEN];
+ bool loop = true;
+
+ if (!nfc_target_init (pnd, NTM_PASSIVE, nt, abtRx, &szRxLen)) {
+ return false;
+ }
+
+ while ( loop ) {
+ loop = target_io( nt, abtRx, szRxLen, abtTx, &szTx );
+ if (szTx) {
+ if (!nfc_target_send_bytes(pnd, abtTx, szTx)) {
+ return false;
+ }
+ }
+ if ( loop ) {
+ if (!nfc_target_receive_bytes(pnd, abtRx, &szRxLen)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+int
+main (int argc, char *argv[])
+{
+ const char *acLibnfcVersion;
+
+ // Try to open the NFC reader
+ pnd = nfc_connect (NULL);
+
+ // Display libnfc version
+ acLibnfcVersion = nfc_version ();
+ printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
+
+ if (pnd == NULL) {
+ ERR("Unable to connect to NFC device");
+ return EXIT_FAILURE;
+ }
+
+ printf ("Connected to NFC device: %s\n", pnd->acName);
+
+ nfc_target_t nt = {
+ .ntt = NTT_MIFARE,
+ .nti.nai.abtAtqa = { 0x03, 0x44 },
+ .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 4,
+ .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
+ .nti.nai.szAtsLen = 5,
+ };
+
+ printf ("%s will emulate this ISO14443-A tag:\n", argv[0]);
+ print_nfc_iso14443a_info( nt.nti.nai );
+
+ printf ("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
+ if (!nfc_target_emulate_tag (pnd, nt)) {
+ nfc_perror (pnd, "nfc_target_emulate_tag");
+ ERR("Could not come out of auto-emulation, no command was received");
+ return EXIT_FAILURE;
+ }
+
+ nfc_disconnect(pnd);
+ exit (EXIT_SUCCESS);
+}
+
diff --git a/examples/nfc-emulate.c b/examples/nfc-emulate.c
index 799614b..b9e8c32 100644
--- a/examples/nfc-emulate.c
+++ b/examples/nfc-emulate.c
@@ -19,7 +19,7 @@
/**
* @file nfc-emulate.c
- * @brief
+ * @brief This example can be used to emulate a tag which which have a "really" custom UID
*/
#ifdef HAVE_CONFIG_H
@@ -106,7 +106,17 @@ 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, NTM_PASSIVE, abtRecv, &szRecvBits)) {
+
+ // Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
+ nfc_target_t nt = {
+ .ntt = NTT_GENERIC_PASSIVE_106,
+ .nti.nai.abtAtqa = "\x04\x00",
+ .nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 5,
+ .nti.nai.szAtsLen = 0,
+ };
+ if (!nfc_target_init (pnd, NTM_PASSIVE, nt, 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 be38d64..124ba5a 100644
--- a/examples/nfc-relay.c
+++ b/examples/nfc-relay.c
@@ -125,7 +125,18 @@ 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, NTM_PASSIVE, abtReaderRx, &szReaderRxBits)) {
+
+ // Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
+ nfc_target_t nt = {
+ .ntt = NTT_GENERIC_PASSIVE_106,
+ .nti.nai.abtAtqa = "\x04\x00",
+ .nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 5,
+ .nti.nai.szAtsLen = 0,
+ };
+
+ if (!nfc_target_init (pndTag, NTM_PASSIVE, nt, 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 4662801..4bb1646 100644
--- a/examples/nfc-sam.c
+++ b/examples/nfc-sam.c
@@ -19,7 +19,7 @@
/**
* @file nfc-sam.c
- * @brief Configure the reader to comunicate with a SAM (Secure Access Module).
+ * @brief Configure the NFC device to comunicate with a SAM (Secure Access Module).
*/
#ifdef HAVE_CONFIG_H
@@ -129,7 +129,7 @@ main (int argc, const char *argv[])
return EXIT_FAILURE;
}
- printf ("Connected to NFC reader: %s\n", pnd->acName);
+ printf ("Connected to NFC device: %s\n", pnd->acName);
// Print the example's menu
printf ("\nSelect the comunication mode:\n");
@@ -152,7 +152,7 @@ main (int argc, const char *argv[])
switch (mode) {
case VIRTUAL_CARD_MODE:
{
- // FIXME: after the loop the reader doesn't respond to host commands...
+ // 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 ();
}
@@ -207,7 +207,15 @@ 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, NTM_PICC, abtRx, &szRxLen))
+ nfc_target_t nt = {
+ .ntt = NTT_GENERIC_PASSIVE_106,
+ .nti.nai.abtAtqa = "\x04\x00",
+ .nti.nai.abtUid = "\x08\xad\xbe\xaf",
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 4,
+ .nti.nai.szAtsLen = 0,
+ };
+ if (!nfc_target_init (pnd, NTM_PICC, nt, 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 d5cd718..e255ecb 100644
--- a/examples/nfcip-target.c
+++ b/examples/nfcip-target.c
@@ -59,7 +59,17 @@ main (int argc, const char *argv[])
errx (1, "usage: %s", argv[0]);
}
- if (!pnd || !nfc_target_init (pnd, NTM_DEP, abtRecv, &szRecvBits)) {
+ // Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
+ nfc_target_t nt = {
+ .ntt = NTT_GENERIC_PASSIVE_106,
+ .nti.nai.abtAtqa = "\x04\x00",
+ .nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
+ .nti.nai.btSak = 0x20,
+ .nti.nai.szUidLen = 5,
+ .nti.nai.szAtsLen = 0,
+ };
+
+ if (!pnd || !nfc_target_init (pnd, NTM_DEP, nt, abtRecv, &szRecvBits)) {
printf ("unable to connect or initialize\n");
return 1;
}
diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h
index ba1923a..4b7fe9b 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, nfc_target_mode_t ntm, byte_t * pbtRx, size_t * pszRxLen);
+ NFC_EXPORT bool nfc_target_init (nfc_device_t * pnd, const nfc_target_mode_t ntm, const nfc_target_t nt, 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 22acf7f..2070fae 100644
--- a/libnfc/chips/pn53x.c
+++ b/libnfc/chips/pn53x.c
@@ -921,7 +921,7 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons
}
bool
-pn53x_target_init (nfc_device_t * pnd, nfc_target_mode_t ntm, byte_t * pbtRx, size_t * pszRxLen)
+pn53x_target_init (nfc_device_t * pnd, const nfc_target_mode_t ntm, const nfc_target_t nt, byte_t * pbtRx, size_t * pszRxLen)
{
// Save the current configuration settings
bool bCrc = pnd->bCrc;
@@ -965,7 +965,30 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_mode_t ntm, byte_t * pbtRx, si
if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON, 0x04))
return false;
- if(!pn53x_TgInitAsTarget(pnd, ntm, pbtRx, pszRxLen)) {
+ byte_t abtMifareParams[6];
+ byte_t * pbtMifareParams = NULL;
+
+ switch(nt.ntt) {
+ case NTT_MIFARE:
+ case NTT_GENERIC_PASSIVE_106:
+ case NTT_ISO14443A_106: {
+ // Set ATQA (SENS_RES)
+ abtMifareParams[0] = nt.nti.nai.abtAtqa[1];
+ abtMifareParams[1] = nt.nti.nai.abtAtqa[0];
+ // Set UID
+ // Note: in this mode we can only emulate a single size (4 bytes) UID where the first is fixed by PN53x as 0x08
+ abtMifareParams[2] = nt.nti.nai.abtUid[1];
+ abtMifareParams[3] = nt.nti.nai.abtUid[2];
+ abtMifareParams[4] = nt.nti.nai.abtUid[3];
+ // Set SAK (SEL_RES)
+ abtMifareParams[5] = nt.nti.nai.btSak;
+
+ pbtMifareParams = abtMifareParams;
+ }
+ break;
+ }
+
+ if(!pn53x_TgInitAsTarget(pnd, ntm, pbtMifareParams, NULL, NULL, pbtRx, pszRxLen)) {
return false;
}
@@ -979,7 +1002,9 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_mode_t ntm, byte_t * pbtRx, si
}
bool
-pn53x_TgInitAsTarget (nfc_device_t * pnd, nfc_target_mode_t ntm, byte_t * pbtRx, size_t * pszRxLen)
+pn53x_TgInitAsTarget (nfc_device_t * pnd, nfc_target_mode_t ntm,
+ const byte_t * pbtMifareParams, const byte_t * pbtFeliCaParams, const byte_t * pbtNFCID3t,
+ byte_t * pbtRx, size_t * pszRxLen)
{
byte_t abtRx[MAX_FRAME_LEN];
size_t szRxLen;
@@ -993,26 +1018,27 @@ pn53x_TgInitAsTarget (nfc_device_t * pnd, nfc_target_mode_t ntm, byte_t * pbtRx,
// Store the target mode in the initialization params
abtCmd[2] = ntm;
- // Set ATQA (SENS_RES)
- abtCmd[3] = 0x04;
- abtCmd[4] = 0x00;
-
- // Set SAK (SEL_RES)
- abtCmd[8] = 0x20;
-
- // Set UID
- abtCmd[5] = 0x00;
- abtCmd[6] = 0xb0;
- abtCmd[7] = 0x0b;
+ if (pbtMifareParams) {
+ memcpy (abtCmd+3, pbtMifareParams, 6);
+ }
+ if (pbtFeliCaParams) {
+ memcpy (abtCmd+9, pbtFeliCaParams, 18);
+ }
+ if (pbtNFCID3t) {
+ memcpy(abtCmd+27, pbtNFCID3t, 10);
+ }
+ // TODO Handle General bytes and Tk (Historical bytes) lenght
// Request the initialization as a target
szRxLen = MAX_FRAME_LEN;
if (!pn53x_transceive (pnd, abtCmd, sizeof (pncmd_target_init), abtRx, &szRxLen))
return false;
+ // Note: the first byte is skip:
+ // its the "mode" byte which contains baudrate, DEP and Framing type (Mifare, active or FeliCa) datas.
+
// Save the received byte count
*pszRxLen = szRxLen - 1;
-
// Copy the received bytes
memcpy (pbtRx, abtRx + 1, *pszRxLen);
diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h
index 2183f53..95567ef 100644
--- a/libnfc/chips/pn53x.h
+++ b/libnfc/chips/pn53x.h
@@ -112,6 +112,7 @@ bool pn53x_decode_target_data (const byte_t * pbtRawData, size_t szDataLen, n
bool pn53x_get_firmware_version (nfc_device_t * pnd);
bool pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
+// NFC device as Initiator functions
bool pn53x_initiator_select_dep_target (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation,
const byte_t * pbtPidData, const size_t szPidDataLen,
const byte_t * pbtNFCID3i, const size_t szNFCID3iDataLen,
@@ -122,16 +123,15 @@ bool pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtT
byte_t * pbtRxPar);
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, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen);
+// NFC device as Target functions
+bool pn53x_target_init (nfc_device_t * pnd, const nfc_target_mode_t ntm, const nfc_target_t nt, 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,
const byte_t * pbtTxPar);
bool pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen);
-
+// Error handling functions
const char *pn53x_strerror (const nfc_device_t * pnd);
-
static const struct chip_callbacks pn53x_callbacks_list = {
pn53x_strerror
};
@@ -145,7 +145,9 @@ bool pn53x_InRelease (nfc_device_t * pnd, const uint8_t ui8Target);
bool pn53x_InAutoPoll (nfc_device_t * pnd, const nfc_target_type_t * pnttTargetTypes, const size_t szTargetTypes,
const byte_t btPollNr, const byte_t btPeriod, nfc_target_t * pntTargets,
size_t * pszTargetFound);
-bool pn53x_TgInitAsTarget (nfc_device_t * pnd, nfc_target_mode_t tm, byte_t * pbtRx, size_t * pszRxLen);
+bool pn53x_TgInitAsTarget (nfc_device_t * pnd, nfc_target_mode_t ntm,
+ const byte_t * pbtMifareParams, const byte_t * pbtFeliCaParams, const byte_t * pbtNFCID3t,
+ byte_t * pbtRx, size_t * pszRxLen);
#endif // __NFC_CHIPS_PN53X_H__
diff --git a/libnfc/nfc.c b/libnfc/nfc.c
index 1400b56..678f3b1 100644
--- a/libnfc/nfc.c
+++ b/libnfc/nfc.c
@@ -556,11 +556,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, nfc_target_mode_t ntm, byte_t * pbtRx, size_t * pszRxLen)
+nfc_target_init (nfc_device_t * pnd, const nfc_target_mode_t ntm, const nfc_target_t nt, byte_t * pbtRx, size_t * pszRxLen)
{
pnd->iLastError = 0;
- return pn53x_target_init (pnd, ntm, pbtRx, pszRxLen);
+ return pn53x_target_init (pnd, ntm, nt, pbtRx, pszRxLen);
}
/**