Merge r520-546 from trunk.

This commit is contained in:
Romain Tartiere 2010-08-18 14:32:01 +00:00
commit 769eef20f7
16 changed files with 291 additions and 278 deletions

View file

@ -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;
// 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
return true;

View file

@ -47,7 +47,6 @@
#define MAX_TARGET_COUNT 16
static nfc_device_t* pnd;
static byte_t abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
int main(int argc, const char* argv[])
{
@ -55,7 +54,6 @@ int main(int argc, const char* argv[])
size_t szDeviceFound;
size_t szTargetFound;
size_t i;
nfc_target_info_t nti;
nfc_device_desc_t *pnddDevices;
// Display libnfc version
@ -133,45 +131,54 @@ int main(int argc, const char* argv[])
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 )) {
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++) {
print_nfc_iso14443a_info (anti[n].nai);
printf("\n");
}
}
printf("-------------------\n");
// Poll for a Felica tag
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))
{
printf("The following (NFC) Felica tag was found:\n\n");
printf("%18s","ID (NFCID2): "); print_hex(nti.nfi.abtId,8);
printf("%18s","Parameter (PAD): "); print_hex(nti.nfi.abtPad,8);
// List Felica tags
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_212, anti, MAX_TARGET_COUNT, &szTargetFound )) {
size_t n;
printf("%zu Felica (212 kbps) passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
for(n=0; n<szTargetFound; n++) {
print_nfc_felica_info (anti[n].nfi);
printf("\n");
}
}
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_424, anti, MAX_TARGET_COUNT, &szTargetFound )) {
size_t n;
printf("%zu Felica (424 kbps) passive target(s) was found%s\n", szTargetFound, (szTargetFound==0)?".\n":":");
for(n=0; n<szTargetFound; n++) {
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))
{
printf("The following (NFC) ISO14443-B tag was found:\n\n");
printf(" ATQB: "); print_hex(nti.nbi.abtAtqb,12);
printf(" ID: "); print_hex(nti.nbi.abtId,4);
printf(" CID: %02x\n",nti.nbi.btCid);
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))
{
// No test results yet
printf("jewel\n");
/*
// List Jewel targets
if (nfc_initiator_list_passive_targets(pnd, NM_JEWEL_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
size_t 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);
}

View file

@ -141,9 +141,6 @@ authenticate (uint32_t uiBlock)
for (key_index = 0; key_index < num_keys; key_index++) {
memcpy (mp.mpa.abtKey, keys + (key_index * 6), 6);
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp)) {
/**
* @note: what about the other key?
*/
if (bUseKeyA)
memcpy (mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
else
@ -190,7 +187,7 @@ read_card (void)
// Try to authenticate for the current sector
if (!authenticate (iBlock)) {
printf ("!\nError: authentication failed for block %02x\n", iBlock);
printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);
return false;
}
// 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.abtAccessBits, mp.mpd.abtData + 6, 4);
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 {
// 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);
} else {
bFailure = true;
printf("!\nError: unable to read block 0x%02x\n", iBlock);
return false;
}
}
}

View file

@ -102,15 +102,9 @@ main (int argc, const char *argv[])
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) {
// 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.");
continue;
}

View file

@ -84,6 +84,9 @@ void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbt
printf("\n");
}
#define SAK_ISO14443_4_COMPLIANT 0x20
#define SAK_ISO18092_COMPLIANT 0x40
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai)
{
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): ");
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);
}
/**

View file

@ -31,7 +31,11 @@
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_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_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);
#endif

View file

@ -51,10 +51,10 @@ typedef struct {
term_info tiNew; // Terminal info during the transaction
} serial_port_unix;
// Set time-out on 30 miliseconds
// timeval struct that define timeout delay for serial port
const struct timeval timeout = {
.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

View file

@ -60,15 +60,15 @@
//
// XXX: Some review from users cross-compiling is welcome!
#if defined (_WIN32)
#define SERIAL_STRING "COM"
//#elif defined(__APPLE__)
// TODO: find UART connection string for PN53X device on Mac OS X
// #define SERIAL_STRING ""
#define DEFAULT_SERIAL_PORTS { "COM1", "COM2", "COM3", "COM4", NULL }
#elif defined(__APPLE__)
// XXX: find UART connection string for PN53X device on Mac OS X when multiples devices are used
#define DEFAULT_SERIAL_PORTS { "/dev/tty.SLAB_USBtoUART", NULL }
#elif defined (__FreeBSD__) || defined (__OpenBSD__)
// XXX: Not tested
#define SERIAL_STRING "/dev/cuau"
#define DEFAULT_SERIAL_PORTS { "/dev/cuau0", "/dev/cuau1", "/dev/cuau2", "/dev/cuau3", NULL }
#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
#error "Can't determine serial string for your system"
#endif

View file

@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <nfc/nfc.h>
// 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_GENERIC_PASSIVE_106:
// We skip the first byte: its the target number (Tg)
pbtRawData++;
// Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset
if (nc == NC_PN531) {
pnti->nai.abtAtqa[1] = *(pbtRawData++);
@ -312,6 +313,76 @@ pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t
} else {
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;
default:
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));
}
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 {
int iErrorCode;
const char *pcErrorMsg;

View file

@ -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_InDeselect(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);

View file

@ -205,8 +205,6 @@ nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd)
SCARDCONTEXT *pscc;
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
if (!(pscc = acr122_get_scardcontext ())) return NULL;
// Test if we were able to connect to the "emulator" card

View file

@ -109,21 +109,13 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
*pszDeviceFound = 0;
serial_port sp;
char acPort[BUFFER_LENGTH];
int iDevice;
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
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++)
{
#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);
while( pcPort = pcPorts[iDevice++] ) {
sp = uart_open(pcPort);
DBG("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
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);
// 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].pcDriver = ARYGON_DRIVER_NAME;
pnddDevices[*pszDeviceFound].pcPort = strdup(acPort);
pnddDevices[*pszDeviceFound].pcPort = strdup(pcPort);
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
(*pszDeviceFound)++;
@ -144,8 +136,8 @@ arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
if((*pszDeviceFound) >= szDevices) break;
}
#ifdef DEBUG
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acPort);
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acPort);
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
#endif /* DEBUG */
}
#endif /* SERIAL_AUTOPROBE_ENABLED */
@ -157,10 +149,6 @@ nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
serial_port sp;
nfc_device_t* pnd = NULL;
if( pndd == NULL ) {
DBG("%s", "arygon_connect() need an nfc_device_desc_t struct.");
return NULL;
} else {
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
sp = uart_open(pndd->pcPort);
@ -169,7 +157,6 @@ nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
uart_set_speed(sp, pndd->uiSpeed);
}
DBG("Successfully connected to: %s",pndd->pcPort);

View file

@ -84,21 +84,13 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_
*pszDeviceFound = 0;
serial_port sp;
char acPort[BUFFER_LENGTH];
int iDevice;
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
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++)
{
#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 PN532 device on serial port: %s at %d bauds.",acPort, SERIAL_DEFAULT_PORT_SPEED);
while( pcPort = pcPorts[iDevice++] ) {
sp = uart_open(pcPort);
DBG("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
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;
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].pcDriver = PN532_UART_DRIVER_NAME;
pnddDevices[*pszDeviceFound].pcPort = strdup(acPort);
pnddDevices[*pszDeviceFound].pcPort[BUFFER_LENGTH] = '\0';
pnddDevices[*pszDeviceFound].pcPort = strdup(pcPort);
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
DBG("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
(*pszDeviceFound)++;
@ -127,8 +118,8 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_
if((*pszDeviceFound) >= szDevices) break;
}
#ifdef DEBUG
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acPort);
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acPort);
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
#endif /* DEBUG */
}
#endif /* SERIAL_AUTOPROBE_ENABLED */
@ -141,10 +132,6 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd)
nfc_device_t* pnd = NULL;
bool bComOk;
if( pndd == NULL ) {
DBG("%s", "pn532_uart_connect() need an nfc_device_desc_t struct.");
return NULL;
} else {
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
sp = uart_open(pndd->pcPort);
@ -153,7 +140,7 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd)
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
uart_set_speed(sp, pndd->uiSpeed);
}
// PN532 could be powered down, we need to wake it up before line testing.
pn532_uart_wakeup((nfc_device_spec_t)sp);
// Check communication using "Diagnose" command, with "Comunication test" (0x00)

View file

@ -162,9 +162,6 @@ nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * targe
us.uiEndPointOut = 0;
us.pudh = NULL;
// must specify device to connect to
if(pndd == NULL) return NULL;
DBG("Attempt to connect to %s device", target_name);
usb_init();

View file

@ -447,7 +447,7 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
// Make sure we are dealing with a active device
if (!pnd->bActive) return false;
// TODO Put this in a function
switch(nmInitModulation)
{
case NM_ISO14443A_106:
@ -493,59 +493,32 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
switch(nmInitModulation)
{
case NM_ISO14443A_106:
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);
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_GENERIC_PASSIVE_106, pnti)) {
return false;
}
break;
case NM_FELICA_212:
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_212, pnti)) {
return false;
}
break;
case NM_FELICA_424:
// Store the mandatory info
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);
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_424, pnti)) {
return false;
}
break;
case NM_ISO14443B_106:
// Store the mandatory info
memcpy(pnti->nbi.abtAtqb,abtTargetsData+2,12);
// 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;
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_ISO14443B_106, pnti)) {
return false;
}
break;
case NM_JEWEL_106:
// Store the mandatory info
memcpy(pnti->nji.btSensRes,abtTargetsData+2,2);
memcpy(pnti->nji.btId,abtTargetsData+4,4);
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_JEWEL_106, pnti)) {
return false;
}
break;
default:
@ -556,11 +529,10 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
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;
bool bCollisionDetected = false;
size_t szTargetFound = 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
nfc_configure (pnd, NDO_INFINITE_SELECT, false);
byte_t* pbtInitData = NULL;
size_t szInitDataLen = 0;
while (nfc_initiator_select_passive_target (pnd, nmInitModulation, NULL, 0, &nti)) {
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);
if(nmInitModulation == NM_ISO14443A_106) {
if((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x00)) {
bCollisionDetected = true;
}
}
if(szTargets > szTargetFound) {
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;
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;
}
/**
* @fn nfc_initiator_deselect_target(const nfc_device_t* pnd);
* @brief Deselect a selected passive or emulated tag
* @return Returns true if action was successfully performed; otherwise returns false.
* @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,
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) {
// 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;
return pn53x_InAutoPoll(pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
}
/**
* @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
* @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.
@ -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;
// 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;
// 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.
*
* 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.
* 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.
@ -1168,7 +1043,7 @@ void nfc_perror (const nfc_device_t *pnd, const char *pcString)
/**
* @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)
{

View file

@ -4,7 +4,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
[
AC_MSG_CHECKING(which drivers to build)
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
yes | no)
dnl ignore calls without any arguments