Merge r520-546 from trunk.
This commit is contained in:
commit
769eef20f7
16 changed files with 291 additions and 278 deletions
|
@ -69,7 +69,13 @@ bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint
|
||||||
if (!nfc_initiator_transceive_dep_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) return false;
|
if (!nfc_initiator_transceive_dep_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) return false;
|
||||||
|
|
||||||
// When we have executed a read command, copy the received bytes into the param
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
if (mc == MC_READ && szRxLen == 17) memcpy(pmp->mpd.abtData,abtRx+1,16);
|
if (mc == MC_READ) {
|
||||||
|
if(szRxLen == 16) {
|
||||||
|
memcpy(pmp->mpd.abtData,abtRx,16);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Command succesfully executed
|
// Command succesfully executed
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#define MAX_TARGET_COUNT 16
|
#define MAX_TARGET_COUNT 16
|
||||||
|
|
||||||
static nfc_device_t* pnd;
|
static nfc_device_t* pnd;
|
||||||
static byte_t abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
|
@ -55,7 +54,6 @@ int main(int argc, const char* argv[])
|
||||||
size_t szDeviceFound;
|
size_t szDeviceFound;
|
||||||
size_t szTargetFound;
|
size_t szTargetFound;
|
||||||
size_t i;
|
size_t i;
|
||||||
nfc_target_info_t nti;
|
|
||||||
nfc_device_desc_t *pnddDevices;
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
|
@ -133,45 +131,54 @@ int main(int argc, const char* argv[])
|
||||||
|
|
||||||
printf("Connected to NFC reader: %s\n",pnd->acName);
|
printf("Connected to NFC reader: %s\n",pnd->acName);
|
||||||
|
|
||||||
|
// List ISO14443A targets
|
||||||
if (nfc_initiator_list_passive_targets(pnd, NM_ISO14443A_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
if (nfc_initiator_list_passive_targets(pnd, NM_ISO14443A_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
size_t n;
|
size_t n;
|
||||||
printf("%zu ISO14443A passive targets was found:\n", szTargetFound);
|
printf("%zu ISO14443A passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
|
||||||
for(n=0; n<szTargetFound; n++) {
|
for(n=0; n<szTargetFound; n++) {
|
||||||
print_nfc_iso14443a_info (anti[n].nai);
|
print_nfc_iso14443a_info (anti[n].nai);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("-------------------\n");
|
|
||||||
|
|
||||||
// Poll for a Felica tag
|
// List Felica tags
|
||||||
if (nfc_initiator_select_passive_target(pnd,NM_FELICA_212,abtFelica,5,&nti) || nfc_initiator_select_passive_target(pnd,NM_FELICA_424,abtFelica,5,&nti))
|
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_212, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
{
|
size_t n;
|
||||||
printf("The following (NFC) Felica tag was found:\n\n");
|
printf("%zu Felica (212 kbps) passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
|
||||||
printf("%18s","ID (NFCID2): "); print_hex(nti.nfi.abtId,8);
|
for(n=0; n<szTargetFound; n++) {
|
||||||
printf("%18s","Parameter (PAD): "); print_hex(nti.nfi.abtPad,8);
|
print_nfc_felica_info (anti[n].nfi);
|
||||||
}
|
printf("\n");
|
||||||
|
}
|
||||||
// Poll for a ISO14443B tag
|
}
|
||||||
if (nfc_initiator_select_passive_target(pnd,NM_ISO14443B_106,(byte_t*)"\x00",1,&nti))
|
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_424, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
{
|
size_t n;
|
||||||
printf("The following (NFC) ISO14443-B tag was found:\n\n");
|
printf("%zu Felica (424 kbps) passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
|
||||||
printf(" ATQB: "); print_hex(nti.nbi.abtAtqb,12);
|
for(n=0; n<szTargetFound; n++) {
|
||||||
printf(" ID: "); print_hex(nti.nbi.abtId,4);
|
print_nfc_felica_info (anti[n].nfi);
|
||||||
printf(" CID: %02x\n",nti.nbi.btCid);
|
printf("\n");
|
||||||
if (nti.nbi.szInfLen>0)
|
}
|
||||||
{
|
}
|
||||||
printf(" INF: "); print_hex(nti.nbi.abtInf,nti.nbi.szInfLen);
|
|
||||||
|
// List ISO14443B targets
|
||||||
|
if (nfc_initiator_list_passive_targets(pnd, NM_ISO14443B_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
|
size_t n;
|
||||||
|
printf("%zu ISO14443B passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
|
||||||
|
for(n=0; n<szTargetFound; n++) {
|
||||||
|
print_nfc_iso14443b_info (anti[n].nbi);
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf("PARAMS: %02x %02x %02x %02x\n",nti.nbi.btParam1,nti.nbi.btParam2,nti.nbi.btParam3,nti.nbi.btParam4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for a Jewel tag
|
/*
|
||||||
if (nfc_initiator_select_passive_target(pnd,NM_JEWEL_106,NULL,0,&nti))
|
// List Jewel targets
|
||||||
{
|
if (nfc_initiator_list_passive_targets(pnd, NM_JEWEL_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
||||||
// No test results yet
|
size_t n;
|
||||||
printf("jewel\n");
|
printf("%zu Jewel passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":"); for(n=0; n<szTargetFound; n++) {
|
||||||
|
printf("Jewel support is missing in libnfc, feel free to contribute.\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect(pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,9 +141,6 @@ authenticate (uint32_t uiBlock)
|
||||||
for (key_index = 0; key_index < num_keys; key_index++) {
|
for (key_index = 0; key_index < num_keys; key_index++) {
|
||||||
memcpy (mp.mpa.abtKey, keys + (key_index * 6), 6);
|
memcpy (mp.mpa.abtKey, keys + (key_index * 6), 6);
|
||||||
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp)) {
|
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp)) {
|
||||||
/**
|
|
||||||
* @note: what about the other key?
|
|
||||||
*/
|
|
||||||
if (bUseKeyA)
|
if (bUseKeyA)
|
||||||
memcpy (mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
|
memcpy (mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
|
||||||
else
|
else
|
||||||
|
@ -190,7 +187,7 @@ read_card (void)
|
||||||
|
|
||||||
// Try to authenticate for the current sector
|
// Try to authenticate for the current sector
|
||||||
if (!authenticate (iBlock)) {
|
if (!authenticate (iBlock)) {
|
||||||
printf ("!\nError: authentication failed for block %02x\n", iBlock);
|
printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Try to read out the trailer
|
// Try to read out the trailer
|
||||||
|
@ -199,6 +196,8 @@ read_card (void)
|
||||||
memcpy (mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6);
|
memcpy (mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6);
|
||||||
memcpy (mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
|
memcpy (mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
|
||||||
memcpy (mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
|
memcpy (mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
|
||||||
|
} else {
|
||||||
|
printf("!\nError: unable to read trailer block 0x%02x\n", iBlock);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Make sure a earlier readout did not fail
|
// Make sure a earlier readout did not fail
|
||||||
|
@ -208,6 +207,8 @@ read_card (void)
|
||||||
memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
|
memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
|
||||||
} else {
|
} else {
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
|
printf("!\nError: unable to read block 0x%02x\n", iBlock);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,15 +102,9 @@ main (int argc, const char *argv[])
|
||||||
|
|
||||||
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
// NOTE we can't use pn53x_transceive() because rx[0] is not status byte (0x00 != status OK)
|
|
||||||
// XXX: as of r491, this is no longer the case. Unfortunately I can't be sure that these comments can be removed.
|
|
||||||
// bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
|
||||||
// bool res = pn53x_transceive(pnd, abtTx, szTxLen, abtRx, &szRxLen);
|
|
||||||
|
|
||||||
// bool (*transceive)(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
|
||||||
|
|
||||||
if (pnd->nc == NC_PN531) {
|
if (pnd->nc == NC_PN531) {
|
||||||
// PN531 doesn't support hardware polling (InAutoPoll)
|
// PN531 doesn't support hardware polling (InAutoPoll)
|
||||||
|
// TODO find a way to handle this in higher level (i.e. libnfc)
|
||||||
WARN ("%s", "PN531 doesn't support hardware polling.");
|
WARN ("%s", "PN531 doesn't support hardware polling.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,9 @@ void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbt
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SAK_ISO14443_4_COMPLIANT 0x20
|
||||||
|
#define SAK_ISO18092_COMPLIANT 0x40
|
||||||
|
|
||||||
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai)
|
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai)
|
||||||
{
|
{
|
||||||
printf(" ATQA (SENS_RES): "); print_hex(nai.abtAtqa,2);
|
printf(" ATQA (SENS_RES): "); print_hex(nai.abtAtqa,2);
|
||||||
|
@ -93,6 +96,28 @@ void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai)
|
||||||
printf(" ATS (ATR): ");
|
printf(" ATS (ATR): ");
|
||||||
print_hex(nai.abtAts, nai.szAtsLen);
|
print_hex(nai.abtAts, nai.szAtsLen);
|
||||||
}
|
}
|
||||||
|
if ( (nai.btSak & SAK_ISO14443_4_COMPLIANT) || (nai.btSak & SAK_ISO18092_COMPLIANT) ) {
|
||||||
|
printf(" Compliant with: ");
|
||||||
|
if (nai.btSak & SAK_ISO14443_4_COMPLIANT) printf("ISO/IEC 14443-4 ");
|
||||||
|
if (nai.btSak & SAK_ISO18092_COMPLIANT) printf("ISO/IEC 18092");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void print_nfc_felica_info(const nfc_felica_info_t nfi)
|
||||||
|
{
|
||||||
|
printf(" ID (NFCID2): "); print_hex(nfi.abtId,8);
|
||||||
|
printf(" Parameter (PAD): "); print_hex(nfi.abtPad,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_nfc_iso14443b_info(const nfc_iso14443b_info_t nbi)
|
||||||
|
{
|
||||||
|
printf(" ATQB: "); print_hex(nbi.abtAtqb,12);
|
||||||
|
printf(" ID: "); print_hex(nbi.abtId,4);
|
||||||
|
printf(" CID: %02x\n",nbi.btCid);
|
||||||
|
if (nbi.szInfLen>0) {
|
||||||
|
printf(" INF: "); print_hex(nbi.abtInf,nbi.szInfLen);
|
||||||
|
}
|
||||||
|
printf(" PARAMS: %02x %02x %02x %02x\n",nbi.btParam1,nbi.btParam2,nbi.btParam3,nbi.btParam4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,7 +31,11 @@
|
||||||
void print_hex(const byte_t* pbtData, const size_t szLen);
|
void print_hex(const byte_t* pbtData, const size_t szLen);
|
||||||
void print_hex_bits(const byte_t* pbtData, const size_t szBits);
|
void print_hex_bits(const byte_t* pbtData, const size_t szBits);
|
||||||
void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbtDataPar);
|
void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbtDataPar);
|
||||||
|
|
||||||
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai);
|
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai);
|
||||||
|
void print_nfc_iso14443b_info(const nfc_iso14443b_info_t nbi);
|
||||||
|
void print_nfc_felica_info(const nfc_felica_info_t nfi);
|
||||||
|
|
||||||
nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFound);
|
nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFound);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,10 +51,10 @@ typedef struct {
|
||||||
term_info tiNew; // Terminal info during the transaction
|
term_info tiNew; // Terminal info during the transaction
|
||||||
} serial_port_unix;
|
} serial_port_unix;
|
||||||
|
|
||||||
// Set time-out on 30 miliseconds
|
// timeval struct that define timeout delay for serial port
|
||||||
const struct timeval timeout = {
|
const struct timeval timeout = {
|
||||||
.tv_sec = 0, // 0 second
|
.tv_sec = 0, // 0 second
|
||||||
.tv_usec = 50000 // 50 ms
|
.tv_usec = 60000 // 60 ms
|
||||||
};
|
};
|
||||||
|
|
||||||
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
|
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
|
||||||
|
|
|
@ -59,16 +59,16 @@
|
||||||
// Try to guess what we should use.
|
// Try to guess what we should use.
|
||||||
//
|
//
|
||||||
// XXX: Some review from users cross-compiling is welcome!
|
// XXX: Some review from users cross-compiling is welcome!
|
||||||
#if defined(_WIN32)
|
#if defined (_WIN32)
|
||||||
#define SERIAL_STRING "COM"
|
#define DEFAULT_SERIAL_PORTS { "COM1", "COM2", "COM3", "COM4", NULL }
|
||||||
//#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// TODO: find UART connection string for PN53X device on Mac OS X
|
// XXX: find UART connection string for PN53X device on Mac OS X when multiples devices are used
|
||||||
// #define SERIAL_STRING ""
|
#define DEFAULT_SERIAL_PORTS { "/dev/tty.SLAB_USBtoUART", NULL }
|
||||||
#elif defined (__FreeBSD__) || defined (__OpenBSD__)
|
#elif defined (__FreeBSD__) || defined (__OpenBSD__)
|
||||||
// XXX: Not tested
|
// XXX: Not tested
|
||||||
#define SERIAL_STRING "/dev/cuau"
|
#define DEFAULT_SERIAL_PORTS { "/dev/cuau0", "/dev/cuau1", "/dev/cuau2", "/dev/cuau3", NULL }
|
||||||
#elif defined (__linux__)
|
#elif defined (__linux__)
|
||||||
#define SERIAL_STRING "/dev/ttyUSB"
|
#define DEFAULT_SERIAL_PORTS { "/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3", "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3", NULL }
|
||||||
#else
|
#else
|
||||||
#error "Can't determine serial string for your system"
|
#error "Can't determine serial string for your system"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
// FIXME: WTF are doing debug macros in this file?
|
// FIXME: WTF are doing debug macros in this file?
|
||||||
|
@ -289,8 +290,8 @@ pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t
|
||||||
case NTT_MIFARE:
|
case NTT_MIFARE:
|
||||||
case NTT_GENERIC_PASSIVE_106:
|
case NTT_GENERIC_PASSIVE_106:
|
||||||
// We skip the first byte: its the target number (Tg)
|
// We skip the first byte: its the target number (Tg)
|
||||||
|
|
||||||
pbtRawData++;
|
pbtRawData++;
|
||||||
|
|
||||||
// Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset
|
// Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset
|
||||||
if (nc == NC_PN531) {
|
if (nc == NC_PN531) {
|
||||||
pnti->nai.abtAtqa[1] = *(pbtRawData++);
|
pnti->nai.abtAtqa[1] = *(pbtRawData++);
|
||||||
|
@ -312,6 +313,76 @@ pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t
|
||||||
} else {
|
} else {
|
||||||
pnti->nai.szAtsLen = 0;
|
pnti->nai.szAtsLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strip CT (Cascade Tag) to retrieve and store the _real_ UID
|
||||||
|
// (e.g. 0x8801020304050607 is in fact 0x01020304050607)
|
||||||
|
if ((pnti->nai.szUidLen == 8) && (pnti->nai.abtUid[0] == 0x88)) {
|
||||||
|
pnti->nai.szUidLen = 7;
|
||||||
|
memmove (pnti->nai.abtUid, pnti->nai.abtUid + 1, 7);
|
||||||
|
} else if ((pnti->nai.szUidLen == 12) && (pnti->nai.abtUid[0] == 0x88) && (pnti->nai.abtUid[4] == 0x88)) {
|
||||||
|
pnti->nai.szUidLen = 10;
|
||||||
|
memmove (pnti->nai.abtUid, pnti->nai.abtUid + 1, 3);
|
||||||
|
memmove (pnti->nai.abtUid + 3, pnti->nai.abtUid + 5, 7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NTT_ISO14443B_106:
|
||||||
|
// We skip the first byte: its the target number (Tg)
|
||||||
|
pbtRawData++;
|
||||||
|
|
||||||
|
// Store the mandatory info
|
||||||
|
memcpy(pnti->nbi.abtAtqb, pbtRawData, 12);
|
||||||
|
pbtRawData += 12;
|
||||||
|
|
||||||
|
// Store temporarily the ATTRIB_RES length
|
||||||
|
uint8_t ui8AttribResLen = *(pbtRawData++);
|
||||||
|
|
||||||
|
// Store the 4 bytes ID
|
||||||
|
memcpy(pnti->nbi.abtId, pbtRawData,4);
|
||||||
|
pbtRawData += 4;
|
||||||
|
|
||||||
|
pnti->nbi.btParam1 = *(pbtRawData++);
|
||||||
|
pnti->nbi.btParam2 = *(pbtRawData++);
|
||||||
|
pnti->nbi.btParam3 = *(pbtRawData++);
|
||||||
|
pnti->nbi.btParam4 = *(pbtRawData++);
|
||||||
|
|
||||||
|
// Test if the Higher layer (INF) is available
|
||||||
|
if (ui8AttribResLen > 8) {
|
||||||
|
pnti->nbi.szInfLen = *(pbtRawData++);
|
||||||
|
memcpy(pnti->nbi.abtInf, pbtRawData, pnti->nbi.szInfLen);
|
||||||
|
} else {
|
||||||
|
pnti->nbi.szInfLen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NTT_FELICA_212:
|
||||||
|
case NTT_FELICA_424:
|
||||||
|
// We skip the first byte: its the target number (Tg)
|
||||||
|
pbtRawData++;
|
||||||
|
|
||||||
|
// Store the mandatory info
|
||||||
|
pnti->nfi.szLen = *(pbtRawData++);
|
||||||
|
pnti->nfi.btResCode = *(pbtRawData++);
|
||||||
|
// Copy the NFCID2t
|
||||||
|
memcpy(pnti->nfi.abtId, pbtRawData, 8);
|
||||||
|
pbtRawData += 8;
|
||||||
|
// Copy the felica padding
|
||||||
|
memcpy(pnti->nfi.abtPad, pbtRawData, 8);
|
||||||
|
pbtRawData += 8;
|
||||||
|
// Test if the System code (SYST_CODE) is available
|
||||||
|
if (pnti->nfi.szLen > 18)
|
||||||
|
{
|
||||||
|
memcpy(pnti->nfi.abtSysCode, pbtRawData, 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NTT_JEWEL_106:
|
||||||
|
// We skip the first byte: its the target number (Tg)
|
||||||
|
pbtRawData++;
|
||||||
|
|
||||||
|
// Store the mandatory info
|
||||||
|
memcpy(pnti->nji.btSensRes, pbtRawData, 2);
|
||||||
|
pbtRawData += 2;
|
||||||
|
memcpy(pnti->nji.btId, pbtRawData, 4);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -381,6 +452,66 @@ pn53x_InRelease(nfc_device_t* pnd, const uint8_t ui8Target)
|
||||||
return(pn53x_transceive(pnd,abtCmd,sizeof(abtCmd),NULL,NULL));
|
return(pn53x_transceive(pnd,abtCmd,sizeof(abtCmd),NULL,NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
size_t szTxInAutoPoll, n, szRxLen;
|
||||||
|
byte_t abtRx[256];
|
||||||
|
bool res;
|
||||||
|
byte_t *pbtTxInAutoPoll;
|
||||||
|
|
||||||
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
|
if(pnd->nc == NC_PN531) {
|
||||||
|
// TODO This function is not supported by pn531 (set errno = ENOSUPP or similar)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// InAutoPoll frame looks like this { 0xd4, 0x60, 0x0f, 0x01, 0x00 } => { direction, command, pollnr, period, types... }
|
||||||
|
szTxInAutoPoll = 4 + szTargetTypes;
|
||||||
|
pbtTxInAutoPoll = malloc( szTxInAutoPoll );
|
||||||
|
pbtTxInAutoPoll[0] = 0xd4;
|
||||||
|
pbtTxInAutoPoll[1] = 0x60;
|
||||||
|
pbtTxInAutoPoll[2] = btPollNr;
|
||||||
|
pbtTxInAutoPoll[3] = btPeriod;
|
||||||
|
for(n=0; n<szTargetTypes; n++) {
|
||||||
|
pbtTxInAutoPoll[4+n] = pnttTargetTypes[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
szRxLen = 256;
|
||||||
|
res = pnd->pdc->transceive(pnd->nds, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen);
|
||||||
|
|
||||||
|
if((szRxLen == 0)||(res == false)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
*pszTargetFound = abtRx[0];
|
||||||
|
if( *pszTargetFound ) {
|
||||||
|
uint8_t ln;
|
||||||
|
byte_t* pbt = abtRx + 1;
|
||||||
|
/* 1st target */
|
||||||
|
// Target type
|
||||||
|
pntTargets[0].ntt = *(pbt++);
|
||||||
|
// AutoPollTargetData length
|
||||||
|
ln = *(pbt++);
|
||||||
|
pn53x_decode_target_data(pbt, ln, pnd->nc, pntTargets[0].ntt, &(pntTargets[0].nti));
|
||||||
|
pbt += ln;
|
||||||
|
|
||||||
|
if(abtRx[0] > 1) {
|
||||||
|
/* 2nd target */
|
||||||
|
// Target type
|
||||||
|
pntTargets[1].ntt = *(pbt++);
|
||||||
|
// AutoPollTargetData length
|
||||||
|
ln = *(pbt++);
|
||||||
|
pn53x_decode_target_data(pbt, ln, pnd->nc, pntTargets[1].ntt, &(pntTargets[1].nti));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static struct sErrorMessage {
|
static struct sErrorMessage {
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
const char *pcErrorMsg;
|
const char *pcErrorMsg;
|
||||||
|
|
|
@ -87,6 +87,7 @@ bool pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_ch
|
||||||
bool pn53x_InListPassiveTarget(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData);
|
bool pn53x_InListPassiveTarget(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t szMaxTargets, const byte_t* pbtInitiatorData, const size_t szInitiatorDataLen, byte_t* pbtTargetsData, size_t* pszTargetsData);
|
||||||
bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target);
|
bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target);
|
||||||
bool pn53x_InRelease(nfc_device_t* pnd, const uint8_t ui8Target);
|
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);
|
||||||
|
|
||||||
const char *pn53x_strerror (const nfc_device_t *pnd);
|
const char *pn53x_strerror (const nfc_device_t *pnd);
|
||||||
|
|
||||||
|
|
|
@ -205,8 +205,6 @@ nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd)
|
||||||
SCARDCONTEXT *pscc;
|
SCARDCONTEXT *pscc;
|
||||||
|
|
||||||
DBG("Attempt to connect to %s",pndd->acDevice);
|
DBG("Attempt to connect to %s",pndd->acDevice);
|
||||||
// We no longer support connecting with a NULL
|
|
||||||
if(pndd == NULL) return NULL;
|
|
||||||
// Test if context succeeded
|
// Test if context succeeded
|
||||||
if (!(pscc = acr122_get_scardcontext ())) return NULL;
|
if (!(pscc = acr122_get_scardcontext ())) return NULL;
|
||||||
// Test if we were able to connect to the "emulator" card
|
// Test if we were able to connect to the "emulator" card
|
||||||
|
|
|
@ -109,21 +109,13 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
char acPort[BUFFER_LENGTH];
|
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
|
||||||
int iDevice;
|
const char* pcPort;
|
||||||
|
int iDevice = 0;
|
||||||
|
|
||||||
// I have no idea how MAC OS X deals with multiple devices, so a quick workaround
|
while( pcPort = pcPorts[iDevice++] ) {
|
||||||
for (iDevice=0; iDevice<DRIVERS_MAX_DEVICES; iDevice++)
|
sp = uart_open(pcPort);
|
||||||
{
|
DBG("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
|
||||||
#ifdef __APPLE__
|
|
||||||
strncpy(acPort, SERIAL_STRING, BUFFER_LENGTH - 1);
|
|
||||||
acPort[BUFFER_LENGTH - 1] = '\0';
|
|
||||||
#else /* __APPLE__ */
|
|
||||||
snprintf(acPort, BUFFER_LENGTH - 1, "%s%d", SERIAL_STRING, iDevice);
|
|
||||||
acPort[BUFFER_LENGTH - 1] = '\0';
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
sp = uart_open(acPort);
|
|
||||||
DBG("Trying to find ARYGON device on serial port: %s at %d bauds.",acPort, SERIAL_DEFAULT_PORT_SPEED);
|
|
||||||
|
|
||||||
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT))
|
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT))
|
||||||
{
|
{
|
||||||
|
@ -132,10 +124,10 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
|
||||||
uart_close(sp);
|
uart_close(sp);
|
||||||
|
|
||||||
// ARYGON reader is found
|
// ARYGON reader is found
|
||||||
snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "ARYGON", acPort);
|
snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "ARYGON", pcPort);
|
||||||
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
|
pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
|
||||||
pnddDevices[*pszDeviceFound].pcPort = strdup(acPort);
|
pnddDevices[*pszDeviceFound].pcPort = strdup(pcPort);
|
||||||
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
||||||
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
|
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
|
@ -144,8 +136,8 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
|
||||||
if((*pszDeviceFound) >= szDevices) break;
|
if((*pszDeviceFound) >= szDevices) break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acPort);
|
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
|
||||||
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acPort);
|
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
}
|
}
|
||||||
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
|
@ -157,19 +149,14 @@ nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t* pnd = NULL;
|
||||||
|
|
||||||
if( pndd == NULL ) {
|
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
||||||
DBG("%s", "arygon_connect() need an nfc_device_desc_t struct.");
|
sp = uart_open(pndd->pcPort);
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
|
||||||
sp = uart_open(pndd->pcPort);
|
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
||||||
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
||||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
||||||
|
|
||||||
uart_set_speed(sp, pndd->uiSpeed);
|
uart_set_speed(sp, pndd->uiSpeed);
|
||||||
}
|
|
||||||
|
|
||||||
DBG("Successfully connected to: %s",pndd->pcPort);
|
DBG("Successfully connected to: %s",pndd->pcPort);
|
||||||
|
|
||||||
|
|
|
@ -84,21 +84,13 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
char acPort[BUFFER_LENGTH];
|
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
|
||||||
int iDevice;
|
const char* pcPort;
|
||||||
|
int iDevice = 0;
|
||||||
// I have no idea how MAC OS X deals with multiple devices, so a quick workaround
|
|
||||||
for (iDevice=0; iDevice<DRIVERS_MAX_DEVICES; iDevice++)
|
while( pcPort = pcPorts[iDevice++] ) {
|
||||||
{
|
sp = uart_open(pcPort);
|
||||||
#ifdef __APPLE__
|
DBG("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
|
||||||
strncpy(acPort,SERIAL_STRING, BUFFER_LENGTH - 1);
|
|
||||||
acPort[BUFFER_LENGTH - 1] = '\0';
|
|
||||||
#else /* __APPLE__ */
|
|
||||||
snprintf(acPort,BUFFER_LENGTH - 1,"%s%d",SERIAL_STRING,iDevice);
|
|
||||||
acPort[BUFFER_LENGTH - 1] = '\0';
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
sp = uart_open(acPort);
|
|
||||||
DBG("Trying to find PN532 device on serial port: %s at %d bauds.",acPort, SERIAL_DEFAULT_PORT_SPEED);
|
|
||||||
|
|
||||||
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT))
|
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT))
|
||||||
{
|
{
|
||||||
|
@ -114,11 +106,10 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_
|
||||||
continue;
|
continue;
|
||||||
uart_close(sp);
|
uart_close(sp);
|
||||||
|
|
||||||
snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", acPort);
|
snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
|
||||||
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
|
pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
|
||||||
pnddDevices[*pszDeviceFound].pcPort = strdup(acPort);
|
pnddDevices[*pszDeviceFound].pcPort = strdup(pcPort);
|
||||||
pnddDevices[*pszDeviceFound].pcPort[BUFFER_LENGTH] = '\0';
|
|
||||||
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
||||||
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
|
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
|
@ -127,8 +118,8 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_
|
||||||
if((*pszDeviceFound) >= szDevices) break;
|
if((*pszDeviceFound) >= szDevices) break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acPort);
|
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
|
||||||
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acPort);
|
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
}
|
}
|
||||||
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
|
@ -141,19 +132,15 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd)
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t* pnd = NULL;
|
||||||
bool bComOk;
|
bool bComOk;
|
||||||
|
|
||||||
if( pndd == NULL ) {
|
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
||||||
DBG("%s", "pn532_uart_connect() need an nfc_device_desc_t struct.");
|
sp = uart_open(pndd->pcPort);
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
|
||||||
sp = uart_open(pndd->pcPort);
|
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
||||||
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
||||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
||||||
|
|
||||||
uart_set_speed(sp, pndd->uiSpeed);
|
uart_set_speed(sp, pndd->uiSpeed);
|
||||||
}
|
|
||||||
// PN532 could be powered down, we need to wake it up before line testing.
|
// PN532 could be powered down, we need to wake it up before line testing.
|
||||||
pn532_uart_wakeup((nfc_device_spec_t)sp);
|
pn532_uart_wakeup((nfc_device_spec_t)sp);
|
||||||
// Check communication using "Diagnose" command, with "Comunication test" (0x00)
|
// Check communication using "Diagnose" command, with "Comunication test" (0x00)
|
||||||
|
@ -240,7 +227,7 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// When the answer should be ignored, just return a successful result
|
// When the answer should be ignored, just return a successful result
|
||||||
|
|
|
@ -162,9 +162,6 @@ nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * targe
|
||||||
us.uiEndPointOut = 0;
|
us.uiEndPointOut = 0;
|
||||||
us.pudh = NULL;
|
us.pudh = NULL;
|
||||||
|
|
||||||
// must specify device to connect to
|
|
||||||
if(pndd == NULL) return NULL;
|
|
||||||
|
|
||||||
DBG("Attempt to connect to %s device", target_name);
|
DBG("Attempt to connect to %s device", target_name);
|
||||||
usb_init();
|
usb_init();
|
||||||
|
|
||||||
|
|
195
libnfc/nfc.c
195
libnfc/nfc.c
|
@ -447,7 +447,7 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
|
||||||
|
|
||||||
// Make sure we are dealing with a active device
|
// Make sure we are dealing with a active device
|
||||||
if (!pnd->bActive) return false;
|
if (!pnd->bActive) return false;
|
||||||
|
// TODO Put this in a function
|
||||||
switch(nmInitModulation)
|
switch(nmInitModulation)
|
||||||
{
|
{
|
||||||
case NM_ISO14443A_106:
|
case NM_ISO14443A_106:
|
||||||
|
@ -493,60 +493,33 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
|
||||||
switch(nmInitModulation)
|
switch(nmInitModulation)
|
||||||
{
|
{
|
||||||
case NM_ISO14443A_106:
|
case NM_ISO14443A_106:
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_GENERIC_PASSIVE_106, pnti)) return false;
|
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_GENERIC_PASSIVE_106, pnti)) {
|
||||||
|
return false;
|
||||||
// Strip CT (Cascade Tag) to retrieve and store the _real_ UID
|
}
|
||||||
// (e.g. 0x8801020304050607 is in fact 0x01020304050607)
|
|
||||||
if ((pnti->nai.szUidLen == 8) && (pnti->nai.abtUid[0] == 0x88)) {
|
|
||||||
pnti->nai.szUidLen = 7;
|
|
||||||
memmove (pnti->nai.abtUid, pnti->nai.abtUid + 1, 7);
|
|
||||||
} else if ((pnti->nai.szUidLen == 12) && (pnti->nai.abtUid[0] == 0x88) && (pnti->nai.abtUid[4] == 0x88)) {
|
|
||||||
pnti->nai.szUidLen = 10;
|
|
||||||
memmove (pnti->nai.abtUid, pnti->nai.abtUid + 1, 3);
|
|
||||||
memmove (pnti->nai.abtUid + 3, pnti->nai.abtUid + 5, 7);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_FELICA_212:
|
case NM_FELICA_212:
|
||||||
case NM_FELICA_424:
|
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_212, pnti)) {
|
||||||
// Store the mandatory info
|
return false;
|
||||||
pnti->nfi.szLen = abtTargetsData[2];
|
|
||||||
pnti->nfi.btResCode = abtTargetsData[3];
|
|
||||||
// Copy the NFCID2t
|
|
||||||
memcpy(pnti->nfi.abtId,abtTargetsData+4,8);
|
|
||||||
// Copy the felica padding
|
|
||||||
memcpy(pnti->nfi.abtPad,abtTargetsData+12,8);
|
|
||||||
// Test if the System code (SYST_CODE) is available
|
|
||||||
if (szTargetsData > 20)
|
|
||||||
{
|
|
||||||
memcpy(pnti->nfi.abtSysCode,abtTargetsData+20,2);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NM_FELICA_424:
|
||||||
|
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_424, pnti)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case NM_ISO14443B_106:
|
case NM_ISO14443B_106:
|
||||||
// Store the mandatory info
|
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_ISO14443B_106, pnti)) {
|
||||||
memcpy(pnti->nbi.abtAtqb,abtTargetsData+2,12);
|
return false;
|
||||||
// Ignore the 0x1D byte, and just store the 4 byte id
|
|
||||||
memcpy(pnti->nbi.abtId,abtTargetsData+15,4);
|
|
||||||
pnti->nbi.btParam1 = abtTargetsData[19];
|
|
||||||
pnti->nbi.btParam2 = abtTargetsData[20];
|
|
||||||
pnti->nbi.btParam3 = abtTargetsData[21];
|
|
||||||
pnti->nbi.btParam4 = abtTargetsData[22];
|
|
||||||
// Test if the Higher layer (INF) is available
|
|
||||||
if (szTargetsData > 22)
|
|
||||||
{
|
|
||||||
pnti->nbi.szInfLen = abtTargetsData[23];
|
|
||||||
memcpy(pnti->nbi.abtInf,abtTargetsData+24,pnti->nbi.szInfLen);
|
|
||||||
} else {
|
|
||||||
pnti->nbi.szInfLen = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_JEWEL_106:
|
case NM_JEWEL_106:
|
||||||
// Store the mandatory info
|
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_JEWEL_106, pnti)) {
|
||||||
memcpy(pnti->nji.btSensRes,abtTargetsData+2,2);
|
return false;
|
||||||
memcpy(pnti->nji.btId,abtTargetsData+4,4);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Should not be possible, so whatever...
|
// Should not be possible, so whatever...
|
||||||
|
@ -556,11 +529,10 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, nfc_target_info_t anti[], const size_t szTargets, size_t *pszTargetFound )
|
bool
|
||||||
|
nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, nfc_target_info_t anti[], const size_t szTargets, size_t *pszTargetFound)
|
||||||
{
|
{
|
||||||
nfc_target_info_t nti;
|
nfc_target_info_t nti;
|
||||||
|
|
||||||
bool bCollisionDetected = false;
|
|
||||||
size_t szTargetFound = 0;
|
size_t szTargetFound = 0;
|
||||||
|
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
@ -568,16 +540,17 @@ bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_
|
||||||
|
|
||||||
// Let the reader only try once to find a target
|
// Let the reader only try once to find a target
|
||||||
nfc_configure (pnd, NDO_INFINITE_SELECT, false);
|
nfc_configure (pnd, NDO_INFINITE_SELECT, false);
|
||||||
|
byte_t* pbtInitData = NULL;
|
||||||
while (nfc_initiator_select_passive_target (pnd, nmInitModulation, NULL, 0, &nti)) {
|
size_t szInitDataLen = 0;
|
||||||
|
|
||||||
|
if(nmInitModulation == NM_ISO14443B_106) {
|
||||||
|
// Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
|
||||||
|
pbtInitData = (byte_t*)"\x00";
|
||||||
|
szInitDataLen = 1;
|
||||||
|
}
|
||||||
|
while (nfc_initiator_select_passive_target (pnd, nmInitModulation, pbtInitData, szInitDataLen, &nti)) {
|
||||||
nfc_initiator_deselect_target(pnd);
|
nfc_initiator_deselect_target(pnd);
|
||||||
|
|
||||||
if(nmInitModulation == NM_ISO14443A_106) {
|
|
||||||
if((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x00)) {
|
|
||||||
bCollisionDetected = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(szTargets > szTargetFound) {
|
if(szTargets > szTargetFound) {
|
||||||
memcpy( &(anti[szTargetFound]), &nti, sizeof(nfc_target_info_t) );
|
memcpy( &(anti[szTargetFound]), &nti, sizeof(nfc_target_info_t) );
|
||||||
}
|
}
|
||||||
|
@ -585,56 +558,10 @@ bool nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_
|
||||||
}
|
}
|
||||||
*pszTargetFound = szTargetFound;
|
*pszTargetFound = szTargetFound;
|
||||||
|
|
||||||
DBG("%zu targets was found%s.", *pszTargetFound, bCollisionDetected?" (with SENS_RES collision)":"");
|
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO This chunk of code attempt to retrieve SENS_RES (ATQA) for ISO14443A which collide previously.
|
|
||||||
// XXX Unfortunately at this stage, I'm not able to REQA each tag correctly to retrieve this SENS_REQ.
|
|
||||||
|
|
||||||
|
|
||||||
// Drop the field for a while
|
|
||||||
nfc_configure(pnd,NDO_ACTIVATE_FIELD,false);
|
|
||||||
// Let the reader only try once to find a tag
|
|
||||||
nfc_configure(pnd,NDO_INFINITE_SELECT,false);
|
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
|
||||||
nfc_configure(pnd,NDO_HANDLE_CRC,true);
|
|
||||||
nfc_configure(pnd,NDO_HANDLE_PARITY,true);
|
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
|
||||||
nfc_configure(pnd,NDO_ACTIVATE_FIELD,true);
|
|
||||||
|
|
||||||
if(bCollisionDetected && (nmInitModulation == NM_ISO14443A_106)) {
|
|
||||||
// nfc_initiator_select_passive_target(pnd, NM_ISO14443A_106, anti[0].nai.abtUid, anti[0].nai.szUidLen, NULL);
|
|
||||||
|
|
||||||
for( size_t n = 0; n < szTargetFound; n++ ) {
|
|
||||||
size_t szTargetsData;
|
|
||||||
byte_t abtTargetsData[MAX_FRAME_LEN];
|
|
||||||
if(!pn53x_InListPassiveTarget(pnd, NM_ISO14443A_106, 2, NULL, 0, abtTargetsData, &szTargetsData)) return false;
|
|
||||||
DBG("pn53x_InListPassiveTarget(): %d selected target(s)", abtTargetsData[0]);
|
|
||||||
if(szTargetsData && (abtTargetsData[0] > 0)) {
|
|
||||||
byte_t* pbtTargetData = abtTargetsData+1;
|
|
||||||
size_t szTargetData = 5 + *(pbtTargetData + 4); // Tg, SENS_RES (2), SEL_RES, NFCIDLength, NFCID1 (NFCIDLength)
|
|
||||||
|
|
||||||
if( (*(pbtTargetData + 3) & 0x40) && ((~(*(pbtTargetData + 3))) & 0x04) ) { // Check if SAK looks like 0bxx1xx0xx, which means compliant with ISO/IEC 14443-4 (= ATS available) (See ISO14443-3 document)
|
|
||||||
szTargetData += 1 + *(pbtTargetData + szTargetData); // Add ATS length
|
|
||||||
}
|
|
||||||
if(!pn53x_decode_target_data(pbtTargetData, szTargetData, pnd->nc, NTT_GENERIC_PASSIVE_106, &nti)) return false;
|
|
||||||
#ifdef DEBUG
|
|
||||||
for(size_t n=0;n<sizeof(nti.nai);n++) printf("%02x ", *(((byte_t*)(&nti.nai)) + n));
|
|
||||||
printf("\n");
|
|
||||||
#endif // DEBUG
|
|
||||||
pn53x_InDeselect(pnd, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn nfc_initiator_deselect_target(const nfc_device_t* pnd);
|
|
||||||
* @brief Deselect a selected passive or emulated tag
|
* @brief Deselect a selected passive or emulated tag
|
||||||
* @return Returns true if action was successfully performed; otherwise returns false.
|
* @return Returns true if action was successfully performed; otherwise returns false.
|
||||||
* @param pnd nfc_device_t struct pointer that represent currently used device
|
* @param pnd nfc_device_t struct pointer that represent currently used device
|
||||||
|
@ -666,62 +593,10 @@ nfc_initiator_poll_targets(nfc_device_t* pnd,
|
||||||
const byte_t btPollNr, const byte_t btPeriod,
|
const byte_t btPollNr, const byte_t btPeriod,
|
||||||
nfc_target_t* pntTargets, size_t* pszTargetFound)
|
nfc_target_t* pntTargets, size_t* pszTargetFound)
|
||||||
{
|
{
|
||||||
size_t szTxInAutoPoll, n, szRxLen;
|
return pn53x_InAutoPoll(pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
|
||||||
byte_t abtRx[256];
|
|
||||||
bool res;
|
|
||||||
byte_t *pbtTxInAutoPoll;
|
|
||||||
|
|
||||||
pnd->iLastError = 0;
|
|
||||||
|
|
||||||
if(pnd->nc == NC_PN531) {
|
|
||||||
// errno = ENOSUPP
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// byte_t abtInAutoPoll[] = { 0xd4, 0x60, 0x0f, 0x01, 0x00 };
|
|
||||||
szTxInAutoPoll = 4 + szTargetTypes;
|
|
||||||
pbtTxInAutoPoll = malloc( szTxInAutoPoll );
|
|
||||||
pbtTxInAutoPoll[0] = 0xd4;
|
|
||||||
pbtTxInAutoPoll[1] = 0x60;
|
|
||||||
pbtTxInAutoPoll[2] = btPollNr;
|
|
||||||
pbtTxInAutoPoll[3] = btPeriod;
|
|
||||||
for(n=0; n<szTargetTypes; n++) {
|
|
||||||
pbtTxInAutoPoll[4+n] = pnttTargetTypes[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
szRxLen = 256;
|
|
||||||
res = pn53x_transceive(pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRxLen);
|
|
||||||
|
|
||||||
if((szRxLen == 0)||(res == false)) {
|
|
||||||
DBG("pn53x_transceive() failed: szRxLen=%ld, res=%d", (unsigned long) szRxLen, res);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
*pszTargetFound = abtRx[0];
|
|
||||||
if( *pszTargetFound ) {
|
|
||||||
uint8_t ln;
|
|
||||||
byte_t* pbt = abtRx + 1;
|
|
||||||
/* 1st target */
|
|
||||||
// Target type
|
|
||||||
pntTargets[0].ntt = *(pbt++);
|
|
||||||
// AutoPollTargetData length
|
|
||||||
ln = *(pbt++);
|
|
||||||
pn53x_decode_target_data(pbt, ln, pnd->nc, pntTargets[0].ntt, &(pntTargets[0].nti));
|
|
||||||
pbt += ln;
|
|
||||||
|
|
||||||
if(abtRx[0] > 1) {
|
|
||||||
/* 2nd target */
|
|
||||||
// Target type
|
|
||||||
pntTargets[1].ntt = *(pbt++);
|
|
||||||
// AutoPollTargetData length
|
|
||||||
ln = *(pbt++);
|
|
||||||
pn53x_decode_target_data(pbt, ln, pnd->nc, pntTargets[1].ntt, &(pntTargets[1].nti));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar)
|
|
||||||
* @brief Transceive raw bit-frames
|
* @brief Transceive raw bit-frames
|
||||||
* @return Returns true if action was successfully performed; otherwise returns false.
|
* @return Returns true if action was successfully performed; otherwise returns false.
|
||||||
* @param pbtTx contains a byte array of the frame that needs to be transmitted.
|
* @param pbtTx contains a byte array of the frame that needs to be transmitted.
|
||||||
|
@ -821,7 +696,7 @@ bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx,
|
||||||
if (!pn53x_set_tx_bits(pnd,0)) return false;
|
if (!pn53x_set_tx_bits(pnd,0)) return false;
|
||||||
|
|
||||||
// Send the frame to the PN53X chip and get the answer
|
// Send the frame to the PN53X chip and get the answer
|
||||||
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
|
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x40)
|
||||||
if (!pn53x_transceive(pnd,abtCmd,szTxLen+3,abtRx,&szRxLen)) return false;
|
if (!pn53x_transceive(pnd,abtCmd,szTxLen+3,abtRx,&szRxLen)) return false;
|
||||||
|
|
||||||
// Save the received byte count
|
// Save the received byte count
|
||||||
|
@ -835,10 +710,10 @@ bool nfc_initiator_transceive_dep_bytes(nfc_device_t* pnd, const byte_t* pbtTx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Transceive byte and APDU frames
|
* @brief Send raw data to target then retrieve raw data from target
|
||||||
* @return Returns true if action was successfully performed; otherwise returns false.
|
* @return Returns true if action was successfully performed; otherwise returns false.
|
||||||
*
|
*
|
||||||
* The reader will transmit the supplied bytes in pbtTx to the target (tag).
|
* The reader will transmit the supplied bytes (\a pbtTx) to the target in raw mode: PN53x will not handle input neither output data.
|
||||||
* It waits for the response and stores the received bytes in the pbtRx byte array.
|
* It waits for the response and stores the received bytes in the pbtRx byte array.
|
||||||
* The parity bits are handled by the PN53X chip. The CRC can be generated automatically or handled manually.
|
* The parity bits are handled by the PN53X chip. The CRC can be generated automatically or handled manually.
|
||||||
* Using this function, frames can be communicated very fast via the NFC reader to the tag.
|
* Using this function, frames can be communicated very fast via the NFC reader to the tag.
|
||||||
|
@ -1168,7 +1043,7 @@ void nfc_perror (const nfc_device_t *pnd, const char *pcString)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the device name
|
* @brief Returns the device name
|
||||||
* @return Returns a string with the device name ( MUST be freed with free() )
|
* @return Returns a string with the device name
|
||||||
*/
|
*/
|
||||||
const char* nfc_device_name(nfc_device_t* pnd)
|
const char* nfc_device_name(nfc_device_t* pnd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
[
|
[
|
||||||
AC_MSG_CHECKING(which drivers to build)
|
AC_MSG_CHECKING(which drivers to build)
|
||||||
AC_ARG_WITH(drivers,
|
AC_ARG_WITH(drivers,
|
||||||
AC_HELP_STRING([--with-drivers=driver@<:@[[[,]]]driver...@:>@], [Only use specific drivers (default set)]),
|
AC_HELP_STRING([--with-drivers=driver@<:@[[[,]]]driver...@:>@], [Only use specific drivers (available drivers: acr122,arygon,pn531_usb,pn533_usb,pn532_uart)]),
|
||||||
[ case "${withval}" in
|
[ case "${withval}" in
|
||||||
yes | no)
|
yes | no)
|
||||||
dnl ignore calls without any arguments
|
dnl ignore calls without any arguments
|
||||||
|
|
Loading…
Reference in a new issue