Indent whole code using make indent. (Fixes issue 84).
This commit is contained in:
parent
f93b4939f4
commit
18cc86a613
42 changed files with 2613 additions and 2479 deletions
|
@ -1,59 +1,61 @@
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
nfc_device_t* pnd;
|
nfc_device_t *pnd;
|
||||||
nfc_target_info_t nti;
|
nfc_target_info_t nti;
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
const char* acLibnfcVersion = nfc_version();
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
// Connect using the first available NFC device
|
// Connect using the first available NFC device
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("%s", "Unable to connect to NFC device.");
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set connected NFC device to initiator mode
|
// Set connected NFC device to initiator mode
|
||||||
nfc_initiator_init(pnd);
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
nfc_configure(pnd,NDO_ACTIVATE_FIELD,false);
|
nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
nfc_configure(pnd,NDO_INFINITE_SELECT,false);
|
nfc_configure (pnd, NDO_INFINITE_SELECT, false);
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
// Configure the CRC and Parity settings
|
||||||
nfc_configure(pnd,NDO_HANDLE_CRC,true);
|
nfc_configure (pnd, NDO_HANDLE_CRC, true);
|
||||||
nfc_configure(pnd,NDO_HANDLE_PARITY,true);
|
nfc_configure (pnd, NDO_HANDLE_PARITY, true);
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
nfc_configure(pnd,NDO_ACTIVATE_FIELD,true);
|
nfc_configure (pnd, NDO_ACTIVATE_FIELD, true);
|
||||||
|
|
||||||
printf("Connected to NFC reader: %s\n",pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
// Poll for a ISO14443A (MIFARE) tag
|
// Poll for a ISO14443A (MIFARE) tag
|
||||||
if (nfc_initiator_select_passive_target(pnd,NM_ISO14443A_106,NULL,0,&nti)) {
|
if (nfc_initiator_select_passive_target (pnd, NM_ISO14443A_106, NULL, 0, &nti)) {
|
||||||
printf("The following (NFC) ISO14443A tag was found:\n");
|
printf ("The following (NFC) ISO14443A tag was found:\n");
|
||||||
printf(" ATQA (SENS_RES): "); print_hex(nti.nai.abtAtqa,2);
|
printf (" ATQA (SENS_RES): ");
|
||||||
printf(" UID (NFCID%c): ",(nti.nai.abtUid[0]==0x08?'3':'1')); print_hex(nti.nai.abtUid,nti.nai.szUidLen);
|
print_hex (nti.nai.abtAtqa, 2);
|
||||||
printf(" SAK (SEL_RES): "); print_hex(&nti.nai.btSak,1);
|
printf (" UID (NFCID%c): ", (nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
||||||
if (nti.nai.szAtsLen) {
|
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
||||||
printf(" ATS (ATR): ");
|
printf (" SAK (SEL_RES): ");
|
||||||
print_hex(nti.nai.abtAts,nti.nai.szAtsLen);
|
print_hex (&nti.nai.btSak, 1);
|
||||||
}
|
if (nti.nai.szAtsLen) {
|
||||||
|
printf (" ATS (ATR): ");
|
||||||
|
print_hex (nti.nai.abtAts, nti.nai.szAtsLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from NFC device
|
// Disconnect from NFC device
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,70 +17,70 @@
|
||||||
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
||||||
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
||||||
*/
|
*/
|
||||||
bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp)
|
bool
|
||||||
|
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
|
||||||
{
|
{
|
||||||
byte_t abtRx[265];
|
byte_t abtRx[265];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
size_t szParamLen;
|
size_t szParamLen;
|
||||||
byte_t abtCmd[265];
|
byte_t abtCmd[265];
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
abtCmd[0] = mc; // The MIFARE Classic command
|
abtCmd[0] = mc; // The MIFARE Classic command
|
||||||
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
|
|
||||||
switch (mc)
|
switch (mc) {
|
||||||
{
|
|
||||||
// Read and store command have no parameter
|
// Read and store command have no parameter
|
||||||
case MC_READ:
|
case MC_READ:
|
||||||
case MC_STORE:
|
case MC_STORE:
|
||||||
szParamLen = 0;
|
szParamLen = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Authenticate command
|
// Authenticate command
|
||||||
case MC_AUTH_A:
|
case MC_AUTH_A:
|
||||||
case MC_AUTH_B:
|
case MC_AUTH_B:
|
||||||
szParamLen = sizeof(mifare_param_auth);
|
szParamLen = sizeof (mifare_param_auth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data command
|
// Data command
|
||||||
case MC_WRITE:
|
case MC_WRITE:
|
||||||
szParamLen = sizeof(mifare_param_data);
|
szParamLen = sizeof (mifare_param_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Value command
|
// Value command
|
||||||
case MC_DECREMENT:
|
case MC_DECREMENT:
|
||||||
case MC_INCREMENT:
|
case MC_INCREMENT:
|
||||||
case MC_TRANSFER:
|
case MC_TRANSFER:
|
||||||
szParamLen = sizeof(mifare_param_value);
|
szParamLen = sizeof (mifare_param_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Please fix your code, you never should reach this statement
|
// Please fix your code, you never should reach this statement
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, copy the parameter bytes
|
// When available, copy the parameter bytes
|
||||||
if (szParamLen) memcpy(abtCmd+2,(byte_t*)pmp,szParamLen);
|
if (szParamLen)
|
||||||
|
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
|
||||||
|
|
||||||
// Fire the mifare command
|
// Fire the mifare command
|
||||||
if (!nfc_initiator_transceive_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) {
|
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRxLen)) {
|
||||||
if (pnd->iLastError != 0x14)
|
if (pnd->iLastError != 0x14)
|
||||||
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
||||||
return false;
|
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) {
|
if (mc == MC_READ) {
|
||||||
if(szRxLen == 16) {
|
if (szRxLen == 16) {
|
||||||
memcpy(pmp->mpd.abtData,abtRx,16);
|
memcpy (pmp->mpd.abtData, abtRx, 16);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command succesfully executed
|
// Command succesfully executed
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,36 +22,36 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBNFC_MIFARE_H_
|
#ifndef _LIBNFC_MIFARE_H_
|
||||||
#define _LIBNFC_MIFARE_H_
|
# define _LIBNFC_MIFARE_H_
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
#pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MC_AUTH_A = 0x60,
|
MC_AUTH_A = 0x60,
|
||||||
MC_AUTH_B = 0x61,
|
MC_AUTH_B = 0x61,
|
||||||
MC_READ = 0x30,
|
MC_READ = 0x30,
|
||||||
MC_WRITE = 0xA0,
|
MC_WRITE = 0xA0,
|
||||||
MC_TRANSFER = 0xB0,
|
MC_TRANSFER = 0xB0,
|
||||||
MC_DECREMENT = 0xC0,
|
MC_DECREMENT = 0xC0,
|
||||||
MC_INCREMENT = 0xC1,
|
MC_INCREMENT = 0xC1,
|
||||||
MC_STORE = 0xC2
|
MC_STORE = 0xC2
|
||||||
} mifare_cmd;
|
} mifare_cmd;
|
||||||
|
|
||||||
// MIFARE command params
|
// MIFARE command params
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtKey[6];
|
byte_t abtKey[6];
|
||||||
byte_t abtUid[4];
|
byte_t abtUid[4];
|
||||||
} mifare_param_auth;
|
} mifare_param_auth;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
byte_t abtData[16];
|
||||||
} mifare_param_data;
|
} mifare_param_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtValue[4];
|
byte_t abtValue[4];
|
||||||
} mifare_param_value;
|
} mifare_param_value;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -61,30 +61,30 @@ typedef union {
|
||||||
} mifare_param;
|
} mifare_param;
|
||||||
|
|
||||||
// Reset struct alignment to default
|
// Reset struct alignment to default
|
||||||
#pragma pack()
|
# pragma pack()
|
||||||
|
|
||||||
bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp);
|
bool nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp);
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
#pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
// MIFARE Classic
|
// MIFARE Classic
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtUID[4];
|
byte_t abtUID[4];
|
||||||
byte_t btBCC;
|
byte_t btBCC;
|
||||||
byte_t btUnknown;
|
byte_t btUnknown;
|
||||||
byte_t abtATQA[2];
|
byte_t abtATQA[2];
|
||||||
byte_t abtUnknown[8];
|
byte_t abtUnknown[8];
|
||||||
} mifare_classic_block_manufacturer;
|
} mifare_classic_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
byte_t abtData[16];
|
||||||
} mifare_classic_block_data;
|
} mifare_classic_block_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtKeyA[6];
|
byte_t abtKeyA[6];
|
||||||
byte_t abtAccessBits[4];
|
byte_t abtAccessBits[4];
|
||||||
byte_t abtKeyB[6];
|
byte_t abtKeyB[6];
|
||||||
} mifare_classic_block_trailer;
|
} mifare_classic_block_trailer;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -99,17 +99,17 @@ typedef struct {
|
||||||
|
|
||||||
// MIFARE Ultralight
|
// MIFARE Ultralight
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t sn0[3];
|
byte_t sn0[3];
|
||||||
byte_t btBCC0;
|
byte_t btBCC0;
|
||||||
byte_t sn1[4];
|
byte_t sn1[4];
|
||||||
byte_t btBCC1;
|
byte_t btBCC1;
|
||||||
byte_t internal;
|
byte_t internal;
|
||||||
byte_t lock[2];
|
byte_t lock[2];
|
||||||
byte_t otp[4];
|
byte_t otp[4];
|
||||||
} mifareul_block_manufacturer;
|
} mifareul_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
byte_t abtData[16];
|
||||||
} mifareul_block_data;
|
} mifareul_block_data;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -122,6 +122,6 @@ typedef struct {
|
||||||
} mifareul_tag;
|
} mifareul_tag;
|
||||||
|
|
||||||
// Reset struct alignment to default
|
// Reset struct alignment to default
|
||||||
#pragma pack()
|
# pragma pack()
|
||||||
|
|
||||||
#endif // _LIBNFC_MIFARE_H_
|
#endif // _LIBNFC_MIFARE_H_
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -47,152 +47,143 @@ static size_t szRxBits;
|
||||||
static size_t szRxLen;
|
static size_t szRxLen;
|
||||||
static byte_t abtUid[10];
|
static byte_t abtUid[10];
|
||||||
static size_t szUidLen = 4;
|
static size_t szUidLen = 4;
|
||||||
static nfc_device_t* pnd;
|
static nfc_device_t *pnd;
|
||||||
|
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
|
|
||||||
// ISO14443A Anti-Collision Commands
|
// ISO14443A Anti-Collision Commands
|
||||||
byte_t abtReqa [1] = { 0x26 };
|
byte_t abtReqa[1] = { 0x26 };
|
||||||
byte_t abtSelectAll [2] = { 0x93,0x20 };
|
byte_t abtSelectAll[2] = { 0x93, 0x20 };
|
||||||
byte_t abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
byte_t abtRats [4] = { 0xe0,0x50,0xbc,0xa5 };
|
byte_t abtRats[4] = { 0xe0, 0x50, 0xbc, 0xa5 };
|
||||||
byte_t abtHalt [4] = { 0x50,0x00,0x57,0xcd };
|
byte_t abtHalt[4] = { 0x50, 0x00, 0x57, 0xcd };
|
||||||
|
|
||||||
static bool transmit_bits(const byte_t* pbtTx, const size_t szTxBits)
|
static bool
|
||||||
|
transmit_bits (const byte_t * pbtTx, const size_t szTxBits)
|
||||||
{
|
{
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("R: ");
|
||||||
printf("R: ");
|
print_hex_bits (pbtTx, szTxBits);
|
||||||
print_hex_bits(pbtTx,szTxBits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
||||||
if (!nfc_initiator_transceive_bits(pnd,pbtTx,szTxBits,NULL,abtRx,&szRxBits,NULL)) return false;
|
if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Show received answer
|
// Show received answer
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("T: ");
|
||||||
printf("T: ");
|
print_hex_bits (abtRx, szRxBits);
|
||||||
print_hex_bits(abtRx,szRxBits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Succesful transfer
|
// Succesful transfer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool transmit_bytes(const byte_t* pbtTx, const size_t szTxLen)
|
static bool
|
||||||
|
transmit_bytes (const byte_t * pbtTx, const size_t szTxLen)
|
||||||
{
|
{
|
||||||
// Show transmitted command
|
// Show transmitted command
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("R: ");
|
||||||
printf("R: ");
|
print_hex (pbtTx, szTxLen);
|
||||||
print_hex(pbtTx,szTxLen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit the command bytes
|
// Transmit the command bytes
|
||||||
if (!nfc_initiator_transceive_bytes(pnd,pbtTx,szTxLen,abtRx,&szRxLen)) return false;
|
if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTxLen, abtRx, &szRxLen))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Show received answer
|
// Show received answer
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("T: ");
|
||||||
printf("T: ");
|
print_hex (abtRx, szRxLen);
|
||||||
print_hex(abtRx,szRxLen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Succesful transfer
|
// Succesful transfer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_usage(char* argv[])
|
static void
|
||||||
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc,char* argv[])
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int arg;
|
int arg;
|
||||||
|
|
||||||
// Get commandline options
|
// Get commandline options
|
||||||
for (arg=1;arg<argc;arg++) {
|
for (arg = 1; arg < argc; arg++) {
|
||||||
if (0 == strcmp(argv[arg], "-h")) {
|
if (0 == strcmp (argv[arg], "-h")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
INFO("%s", "Quiet mode.");
|
INFO ("%s", "Quiet mode.");
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (!pnd)
|
if (!pnd) {
|
||||||
{
|
printf ("Error connecting NFC reader\n");
|
||||||
printf("Error connecting NFC reader\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
nfc_initiator_init(pnd);
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror (pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_CRC,false)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
|
||||||
nfc_perror (pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure parity settings
|
// Configure parity settings
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror (pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror (pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nfc_configure(pnd, NDO_EASY_FRAMING, false)) {
|
if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
|
||||||
nfc_perror (pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\nConnected to NFC reader: %s\n\n",pnd->acName);
|
printf ("\nConnected to NFC reader: %s\n\n", pnd->acName);
|
||||||
|
|
||||||
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
||||||
if (!transmit_bits(abtReqa,7))
|
if (!transmit_bits (abtReqa, 7)) {
|
||||||
{
|
printf ("Error: No tag available\n");
|
||||||
printf("Error: No tag available\n");
|
nfc_disconnect (pnd);
|
||||||
nfc_disconnect(pnd);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anti-collision
|
// Anti-collision
|
||||||
transmit_bytes(abtSelectAll,2);
|
transmit_bytes (abtSelectAll, 2);
|
||||||
|
|
||||||
// Save the UID
|
// Save the UID
|
||||||
memcpy(abtUid,abtRx,4);
|
memcpy (abtUid, abtRx, 4);
|
||||||
memcpy(abtSelectTag+2,abtRx,5);
|
memcpy (abtSelectTag + 2, abtRx, 5);
|
||||||
append_iso14443a_crc(abtSelectTag,7);
|
append_iso14443a_crc (abtSelectTag, 7);
|
||||||
transmit_bytes(abtSelectTag,9);
|
transmit_bytes (abtSelectTag, 9);
|
||||||
|
|
||||||
// Test if we are dealing with a 4 bytes uid
|
// Test if we are dealing with a 4 bytes uid
|
||||||
if (abtUid[0]!= 0x88)
|
if (abtUid[0] != 0x88) {
|
||||||
{
|
|
||||||
szUidLen = 4;
|
szUidLen = 4;
|
||||||
} else {
|
} else {
|
||||||
// We have to do the anti-collision for cascade level 2
|
// We have to do the anti-collision for cascade level 2
|
||||||
|
@ -200,28 +191,29 @@ int main(int argc,char* argv[])
|
||||||
abtSelectTag[0] = 0x95;
|
abtSelectTag[0] = 0x95;
|
||||||
|
|
||||||
// Anti-collision
|
// Anti-collision
|
||||||
transmit_bytes(abtSelectAll,2);
|
transmit_bytes (abtSelectAll, 2);
|
||||||
|
|
||||||
// Save the UID
|
// Save the UID
|
||||||
memcpy(abtUid+4,abtRx,4);
|
memcpy (abtUid + 4, abtRx, 4);
|
||||||
memcpy(abtSelectTag+2,abtRx,5);
|
memcpy (abtSelectTag + 2, abtRx, 5);
|
||||||
append_iso14443a_crc(abtSelectTag,7);
|
append_iso14443a_crc (abtSelectTag, 7);
|
||||||
transmit_bytes(abtSelectTag,9);
|
transmit_bytes (abtSelectTag, 9);
|
||||||
szUidLen = 7;
|
szUidLen = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request ATS, this only applies to tags that support ISO 14443A-4
|
// Request ATS, this only applies to tags that support ISO 14443A-4
|
||||||
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) transmit_bytes(abtRats,4);
|
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED)
|
||||||
|
transmit_bytes (abtRats, 4);
|
||||||
|
|
||||||
// Done, halt the tag now
|
// Done, halt the tag now
|
||||||
transmit_bytes(abtHalt,4);
|
transmit_bytes (abtHalt, 4);
|
||||||
|
|
||||||
printf("\nFound tag with UID: ");
|
printf ("\nFound tag with UID: ");
|
||||||
if (szUidLen == 7) {
|
if (szUidLen == 7) {
|
||||||
printf("%02x%02x%02x", abtUid[6], abtUid[5], abtUid[4]);
|
printf ("%02x%02x%02x", abtUid[6], abtUid[5], abtUid[4]);
|
||||||
}
|
}
|
||||||
printf("%02x%02x%02x%02x\n", abtUid[3], abtUid[2], abtUid[1], abtUid[0]);
|
printf ("%02x%02x%02x%02x\n", abtUid[3], abtUid[2], abtUid[1], abtUid[0]);
|
||||||
|
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -41,138 +41,132 @@
|
||||||
|
|
||||||
static byte_t abtRecv[MAX_FRAME_LEN];
|
static byte_t abtRecv[MAX_FRAME_LEN];
|
||||||
static size_t szRecvBits;
|
static size_t szRecvBits;
|
||||||
static nfc_device_t* pnd;
|
static nfc_device_t *pnd;
|
||||||
|
|
||||||
// ISO14443A Anti-Collision response
|
// ISO14443A Anti-Collision response
|
||||||
byte_t abtAtqa [2] = { 0x04,0x00 };
|
byte_t abtAtqa[2] = { 0x04, 0x00 };
|
||||||
byte_t abtUidBcc [5] = { 0xDE,0xAD,0xBE,0xAF,0x62 };
|
byte_t abtUidBcc[5] = { 0xDE, 0xAD, 0xBE, 0xAF, 0x62 };
|
||||||
byte_t abtSak [9] = { 0x08,0xb6,0xdd };
|
byte_t abtSak[9] = { 0x08, 0xb6, 0xdd };
|
||||||
|
|
||||||
void print_usage(char* argv[])
|
void
|
||||||
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS] [UID]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS] [UID]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
printf("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEAF).\n");
|
printf ("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEAF).\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
byte_t* pbtTx = NULL;
|
byte_t *pbtTx = NULL;
|
||||||
size_t szTxBits;
|
size_t szTxBits;
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
|
|
||||||
int arg, i;
|
int arg,
|
||||||
|
i;
|
||||||
|
|
||||||
// Get commandline options
|
// Get commandline options
|
||||||
for (arg=1;arg<argc;arg++) {
|
for (arg = 1; arg < argc; arg++) {
|
||||||
if (0 == strcmp(argv[arg], "-h")) {
|
if (0 == strcmp (argv[arg], "-h")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
INFO("%s", "Quiet mode.");
|
INFO ("%s", "Quiet mode.");
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else if((arg == argc-1) && (strlen(argv[arg]) == 8)) { // See if UID was specified as HEX string
|
} else if ((arg == argc - 1) && (strlen (argv[arg]) == 8)) { // See if UID was specified as HEX string
|
||||||
byte_t abtTmp[3] = { 0x00,0x00,0x00 };
|
byte_t abtTmp[3] = { 0x00, 0x00, 0x00 };
|
||||||
printf("[+] Using UID: %s\n",argv[arg]);
|
printf ("[+] Using UID: %s\n", argv[arg]);
|
||||||
abtUidBcc[4]= 0x00;
|
abtUidBcc[4] = 0x00;
|
||||||
for(i= 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i) {
|
||||||
{
|
memcpy (abtTmp, argv[arg] + i * 2, 2);
|
||||||
memcpy(abtTmp,argv[arg]+i*2,2);
|
abtUidBcc[i] = (byte_t) strtol ((char *) abtTmp, NULL, 16);
|
||||||
abtUidBcc[i]= (byte_t) strtol((char*)abtTmp,NULL,16);
|
|
||||||
abtUidBcc[4] ^= abtUidBcc[i];
|
abtUidBcc[4] ^= abtUidBcc[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (pnd == NULL)
|
if (pnd == NULL) {
|
||||||
{
|
printf ("Error connecting NFC reader\n");
|
||||||
printf("Error connecting NFC reader\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
printf("[+] Connected to NFC reader: %s\n",pnd->acName);
|
printf ("[+] Connected to NFC reader: %s\n", pnd->acName);
|
||||||
printf("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
||||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
printf ("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
||||||
if (!nfc_target_init(pnd,abtRecv,&szRecvBits))
|
if (!nfc_target_init (pnd, abtRecv, &szRecvBits)) {
|
||||||
{
|
printf ("Error: Could not come out of auto-emulation, no command was received\n");
|
||||||
printf("Error: Could not come out of auto-emulation, no command was received\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("[+] Received initiator command: ");
|
printf ("[+] Received initiator command: ");
|
||||||
print_hex_bits(abtRecv,szRecvBits);
|
print_hex_bits (abtRecv, szRecvBits);
|
||||||
printf("[+] Configuring communication\n");
|
printf ("[+] Configuring communication\n");
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_CRC,false) || !nfc_configure(pnd,NDO_HANDLE_PARITY,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false) || !nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
printf("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n",abtUidBcc[0],abtUidBcc[1],abtUidBcc[2],abtUidBcc[3]);
|
printf ("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n", abtUidBcc[0], abtUidBcc[1],
|
||||||
|
abtUidBcc[2], abtUidBcc[3]);
|
||||||
|
|
||||||
while(true)
|
while (true) {
|
||||||
{
|
|
||||||
// Test if we received a frame
|
// Test if we received a frame
|
||||||
if (nfc_target_receive_bits(pnd,abtRecv,&szRecvBits,NULL))
|
if (nfc_target_receive_bits (pnd, abtRecv, &szRecvBits, NULL)) {
|
||||||
{
|
|
||||||
// Prepare the command to send back for the anti-collision request
|
// Prepare the command to send back for the anti-collision request
|
||||||
switch(szRecvBits)
|
switch (szRecvBits) {
|
||||||
{
|
case 7: // Request or Wakeup
|
||||||
case 7: // Request or Wakeup
|
pbtTx = abtAtqa;
|
||||||
pbtTx = abtAtqa;
|
szTxBits = 16;
|
||||||
szTxBits = 16;
|
// New anti-collsion session started
|
||||||
// New anti-collsion session started
|
if (!quiet_output)
|
||||||
if (!quiet_output) printf("\n");
|
printf ("\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16: // Select All
|
case 16: // Select All
|
||||||
pbtTx = abtUidBcc;
|
pbtTx = abtUidBcc;
|
||||||
szTxBits = 40;
|
szTxBits = 40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 72: // Select Tag
|
case 72: // Select Tag
|
||||||
pbtTx = abtSak;
|
pbtTx = abtSak;
|
||||||
szTxBits = 24;
|
szTxBits = 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // unknown length?
|
default: // unknown length?
|
||||||
szTxBits = 0;
|
szTxBits = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("R: ");
|
||||||
printf("R: ");
|
print_hex_bits (abtRecv, szRecvBits);
|
||||||
print_hex_bits(abtRecv,szRecvBits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if we know how to respond
|
// Test if we know how to respond
|
||||||
if(szTxBits)
|
if (szTxBits) {
|
||||||
{
|
|
||||||
// Send and print the command to the screen
|
// Send and print the command to the screen
|
||||||
if (!nfc_target_send_bits(pnd,pbtTx,szTxBits,NULL)) {
|
if (!nfc_target_send_bits (pnd, pbtTx, szTxBits, NULL)) {
|
||||||
nfc_perror(pnd, "nfc_target_send_bits");
|
nfc_perror (pnd, "nfc_target_send_bits");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("T: ");
|
||||||
printf("T: ");
|
print_hex_bits (pbtTx, szTxBits);
|
||||||
print_hex_bits(pbtTx,szTxBits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
exit(EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#ifdef HAVE_LIBUSB
|
#ifdef HAVE_LIBUSB
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
#include <sys/param.h>
|
# include <sys/param.h>
|
||||||
#include <usb.h>
|
# include <usb.h>
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
@ -46,35 +46,35 @@
|
||||||
#define MAX_DEVICE_COUNT 16
|
#define MAX_DEVICE_COUNT 16
|
||||||
#define MAX_TARGET_COUNT 16
|
#define MAX_TARGET_COUNT 16
|
||||||
|
|
||||||
static nfc_device_t* pnd;
|
static nfc_device_t *pnd;
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
const char* acLibnfcVersion;
|
const char *acLibnfcVersion;
|
||||||
size_t szDeviceFound;
|
size_t szDeviceFound;
|
||||||
size_t szTargetFound;
|
size_t szTargetFound;
|
||||||
size_t i;
|
size_t i;
|
||||||
nfc_device_desc_t *pnddDevices;
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
acLibnfcVersion = nfc_version();
|
acLibnfcVersion = nfc_version ();
|
||||||
printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
pnddDevices = parse_device_desc(argc, argv, &szDeviceFound);
|
pnddDevices = parse_device_desc (argc, argv, &szDeviceFound);
|
||||||
|
|
||||||
if (argc > 1 && szDeviceFound == 0) {
|
if (argc > 1 && szDeviceFound == 0) {
|
||||||
errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
|
errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
#ifdef HAVE_LIBUSB
|
# ifdef DEBUG
|
||||||
#ifdef DEBUG
|
usb_set_debug (4);
|
||||||
usb_set_debug(4);
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Lazy way to open an NFC device */
|
/* Lazy way to open an NFC device */
|
||||||
#if 0
|
#if 0
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
|
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
|
||||||
|
@ -84,13 +84,11 @@ int main(int argc, const char* argv[])
|
||||||
ndd.pcPort = "/dev/ttyUSB0";
|
ndd.pcPort = "/dev/ttyUSB0";
|
||||||
ndd.uiSpeed = 115200;
|
ndd.uiSpeed = 115200;
|
||||||
|
|
||||||
pnd = nfc_connect(&ndd);
|
pnd = nfc_connect (&ndd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (szDeviceFound == 0)
|
if (szDeviceFound == 0) {
|
||||||
{
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices))))
|
|
||||||
{
|
|
||||||
fprintf (stderr, "malloc() failed\n");
|
fprintf (stderr, "malloc() failed\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -98,94 +96,88 @@ int main(int argc, const char* argv[])
|
||||||
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound);
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szDeviceFound == 0)
|
if (szDeviceFound == 0) {
|
||||||
{
|
INFO ("%s", "No device found.");
|
||||||
INFO("%s", "No device found.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < szDeviceFound; i++)
|
for (i = 0; i < szDeviceFound; i++) {
|
||||||
{
|
|
||||||
nfc_target_info_t anti[MAX_TARGET_COUNT];
|
nfc_target_info_t anti[MAX_TARGET_COUNT];
|
||||||
pnd = nfc_connect(&(pnddDevices[i]));
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
|
|
||||||
|
|
||||||
if (pnd == NULL)
|
if (pnd == NULL) {
|
||||||
{
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
ERR("%s", "Unable to connect to NFC device.");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
nfc_initiator_init(pnd);
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (!nfc_configure(pnd,NDO_INFINITE_SELECT,false)) {
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
// Configure the CRC and Parity settings
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_CRC,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nfc_configure(pnd, NDO_AUTO_ISO14443_4, true)) {
|
if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Connected to NFC reader: %s\n",pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
// List ISO14443A targets
|
// 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("%d ISO14443A passive target(s) was found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
|
printf ("%d ISO14443A passive target(s) was found%s\n", (int) 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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// List Felica tags
|
// List Felica tags
|
||||||
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_212, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
if (nfc_initiator_list_passive_targets (pnd, NM_FELICA_212, anti, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
size_t n;
|
size_t n;
|
||||||
printf("%d Felica (212 kbps) passive target(s) was found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
|
printf ("%d Felica (212 kbps) passive target(s) was found%s\n", (int) szTargetFound,
|
||||||
for(n=0; n<szTargetFound; n++) {
|
(szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
print_nfc_felica_info (anti[n].nfi);
|
print_nfc_felica_info (anti[n].nfi);
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nfc_initiator_list_passive_targets(pnd, NM_FELICA_424, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
if (nfc_initiator_list_passive_targets (pnd, NM_FELICA_424, anti, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
size_t n;
|
size_t n;
|
||||||
printf("%d Felica (424 kbps) passive target(s) was found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
|
printf ("%d Felica (424 kbps) passive target(s) was found%s\n", (int) szTargetFound,
|
||||||
for(n=0; n<szTargetFound; n++) {
|
(szTargetFound == 0) ? ".\n" : ":");
|
||||||
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
print_nfc_felica_info (anti[n].nfi);
|
print_nfc_felica_info (anti[n].nfi);
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// List ISO14443B targets
|
// List ISO14443B targets
|
||||||
if (nfc_initiator_list_passive_targets(pnd, NM_ISO14443B_106, anti, MAX_TARGET_COUNT, &szTargetFound )) {
|
if (nfc_initiator_list_passive_targets (pnd, NM_ISO14443B_106, anti, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||||
size_t n;
|
size_t n;
|
||||||
printf("%d ISO14443B passive target(s) was found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
|
printf ("%d ISO14443B passive target(s) was found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
|
||||||
for(n=0; n<szTargetFound; n++) {
|
for (n = 0; n < szTargetFound; n++) {
|
||||||
print_nfc_iso14443b_info (anti[n].nbi);
|
print_nfc_iso14443b_info (anti[n].nbi);
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,8 +191,8 @@ int main(int argc, const char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (pnddDevices);
|
free (pnddDevices);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -69,7 +69,7 @@ print_success_or_failure (bool bFailure, uint32_t * uiBlockCounter)
|
||||||
*uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16;
|
*uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_first_block (uint32_t uiBlock)
|
is_first_block (uint32_t uiBlock)
|
||||||
{
|
{
|
||||||
// Test if we are in the small or big sectors
|
// Test if we are in the small or big sectors
|
||||||
|
@ -79,7 +79,7 @@ is_first_block (uint32_t uiBlock)
|
||||||
return ((uiBlock) % 16 == 0);
|
return ((uiBlock) % 16 == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_trailer_block (uint32_t uiBlock)
|
is_trailer_block (uint32_t uiBlock)
|
||||||
{
|
{
|
||||||
// Test if we are in the small or big sectors
|
// Test if we are in the small or big sectors
|
||||||
|
@ -89,7 +89,7 @@ is_trailer_block (uint32_t uiBlock)
|
||||||
return ((uiBlock + 1) % 16 == 0);
|
return ((uiBlock + 1) % 16 == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
get_trailer_block (uint32_t uiFirstBlock)
|
get_trailer_block (uint32_t uiFirstBlock)
|
||||||
{
|
{
|
||||||
// Test if we are in the small or big sectors
|
// Test if we are in the small or big sectors
|
||||||
|
@ -102,12 +102,12 @@ get_trailer_block (uint32_t uiFirstBlock)
|
||||||
return trailer_block;
|
return trailer_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
authenticate (uint32_t uiBlock)
|
authenticate (uint32_t uiBlock)
|
||||||
{
|
{
|
||||||
mifare_cmd mc;
|
mifare_cmd mc;
|
||||||
uint32_t uiTrailerBlock;
|
uint32_t uiTrailerBlock;
|
||||||
size_t key_index;
|
size_t key_index;
|
||||||
|
|
||||||
// Key file authentication.
|
// Key file authentication.
|
||||||
if (bUseKeyFile) {
|
if (bUseKeyFile) {
|
||||||
|
@ -156,11 +156,11 @@ authenticate (uint32_t uiBlock)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_card (void)
|
read_card (void)
|
||||||
{
|
{
|
||||||
int32_t iBlock;
|
int32_t iBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiReadBlocks = 0;
|
uint32_t uiReadBlocks = 0;
|
||||||
|
|
||||||
printf ("Reading out %d blocks |", uiBlocks + 1);
|
printf ("Reading out %d blocks |", uiBlocks + 1);
|
||||||
|
@ -197,7 +197,7 @@ read_card (void)
|
||||||
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 {
|
} else {
|
||||||
printf("!\nError: unable to read trailer block 0x%02x\n", iBlock);
|
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
|
||||||
|
@ -207,7 +207,7 @@ 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);
|
printf ("!\nError: unable to read block 0x%02x\n", iBlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,11 +221,11 @@ read_card (void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
write_card (void)
|
write_card (void)
|
||||||
{
|
{
|
||||||
uint32_t uiBlock;
|
uint32_t uiBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiWriteBlocks = 0;
|
uint32_t uiWriteBlocks = 0;
|
||||||
|
|
||||||
printf ("Writing %d blocks |", uiBlocks + 1);
|
printf ("Writing %d blocks |", uiBlocks + 1);
|
||||||
|
@ -295,8 +295,8 @@ mifare_classic_extract_payload (const char *abDump, char *pbPayload)
|
||||||
{
|
{
|
||||||
uint8_t uiSectorIndex;
|
uint8_t uiSectorIndex;
|
||||||
uint8_t uiBlockIndex;
|
uint8_t uiBlockIndex;
|
||||||
size_t szDumpOffset;
|
size_t szDumpOffset;
|
||||||
size_t szPayloadIndex = 0;
|
size_t szPayloadIndex = 0;
|
||||||
|
|
||||||
for (uiSectorIndex = 1; uiSectorIndex < 16; uiSectorIndex++) {
|
for (uiSectorIndex = 1; uiSectorIndex < 16; uiSectorIndex++) {
|
||||||
for (uiBlockIndex = 0; uiBlockIndex < 3; uiBlockIndex++) {
|
for (uiBlockIndex = 0; uiBlockIndex < 3; uiBlockIndex++) {
|
||||||
|
@ -308,8 +308,7 @@ mifare_classic_extract_payload (const char *abDump, char *pbPayload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
ACTION_READ,
|
ACTION_READ,
|
||||||
ACTION_WRITE,
|
ACTION_WRITE,
|
||||||
ACTION_EXTRACT,
|
ACTION_EXTRACT,
|
||||||
|
@ -335,11 +334,11 @@ print_usage (const char *pcProgramName)
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
bool b4K;
|
bool b4K;
|
||||||
action_t atAction = ACTION_USAGE;
|
action_t atAction = ACTION_USAGE;
|
||||||
byte_t *pbtUID;
|
byte_t *pbtUID;
|
||||||
FILE *pfKeys = NULL;
|
FILE *pfKeys = NULL;
|
||||||
FILE *pfDump = NULL;
|
FILE *pfDump = NULL;
|
||||||
const char *command = argv[1];
|
const char *command = argv[1];
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
|
@ -415,32 +414,29 @@ main (int argc, const char *argv[])
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
|
// Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
|
||||||
nfc_configure(pnd, NDO_AUTO_ISO14443_4, false);
|
nfc_configure (pnd, NDO_AUTO_ISO14443_4, false);
|
||||||
|
|
||||||
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
|
@ -499,11 +495,11 @@ main (int argc, const char *argv[])
|
||||||
const char *pcDump = argv[2];
|
const char *pcDump = argv[2];
|
||||||
const char *pcPayload = argv[3];
|
const char *pcPayload = argv[3];
|
||||||
|
|
||||||
FILE *pfDump = NULL;
|
FILE *pfDump = NULL;
|
||||||
FILE *pfPayload = NULL;
|
FILE *pfPayload = NULL;
|
||||||
|
|
||||||
char abDump[4096];
|
char abDump[4096];
|
||||||
char abPayload[4096];
|
char abPayload[4096];
|
||||||
|
|
||||||
pfDump = fopen (pcDump, "rb");
|
pfDump = fopen (pcDump, "rb");
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,11 @@ print_success_or_failure (bool bFailure, uint32_t * uiCounter)
|
||||||
*uiCounter += (bFailure) ? 0 : 1;
|
*uiCounter += (bFailure) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_card (void)
|
read_card (void)
|
||||||
{
|
{
|
||||||
uint32_t page;
|
uint32_t page;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiReadedPages = 0;
|
uint32_t uiReadedPages = 0;
|
||||||
|
|
||||||
printf ("Reading %d pages |", uiBlocks + 1);
|
printf ("Reading %d pages |", uiBlocks + 1);
|
||||||
|
@ -85,16 +85,16 @@ read_card (void)
|
||||||
return (!bFailure);
|
return (!bFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
write_card (void)
|
write_card (void)
|
||||||
{
|
{
|
||||||
uint32_t uiBlock = 0;
|
uint32_t uiBlock = 0;
|
||||||
int page = 0x4;
|
int page = 0x4;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiWritenPages = 0;
|
uint32_t uiWritenPages = 0;
|
||||||
|
|
||||||
char buffer[BUFSIZ];
|
char buffer[BUFSIZ];
|
||||||
bool write_otp;
|
bool write_otp;
|
||||||
|
|
||||||
printf ("Write OTP bytes ? [yN] ");
|
printf ("Write OTP bytes ? [yN] ");
|
||||||
fgets (buffer, BUFSIZ, stdin);
|
fgets (buffer, BUFSIZ, stdin);
|
||||||
|
@ -104,11 +104,11 @@ write_card (void)
|
||||||
printf ("Writing %d pages |", uiBlocks + 1);
|
printf ("Writing %d pages |", uiBlocks + 1);
|
||||||
printf ("sss");
|
printf ("sss");
|
||||||
|
|
||||||
if(write_otp) {
|
if (write_otp) {
|
||||||
page = 0x3;
|
page = 0x3;
|
||||||
} else {
|
} else {
|
||||||
/* If user don't want to write OTP, we skip 1 page more. */
|
/* If user don't want to write OTP, we skip 1 page more. */
|
||||||
printf("s");
|
printf ("s");
|
||||||
page = 0x4;
|
page = 0x4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,6 @@ write_card (void)
|
||||||
}
|
}
|
||||||
bFailure = false;
|
bFailure = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the Mifare Ultralight, this write command can be used
|
// For the Mifare Ultralight, this write command can be used
|
||||||
// in compatibility mode, which only actually writes the first
|
// in compatibility mode, which only actually writes the first
|
||||||
// page (4 bytes). The Ultralight-specific Write command only
|
// page (4 bytes). The Ultralight-specific Write command only
|
||||||
|
@ -130,12 +129,13 @@ write_card (void)
|
||||||
uiBlock = page / 4;
|
uiBlock = page / 4;
|
||||||
memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16);
|
memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16);
|
||||||
if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, page, &mp))
|
if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, page, &mp))
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
|
|
||||||
print_success_or_failure (bFailure, &uiWritenPages);
|
print_success_or_failure (bFailure, &uiWritenPages);
|
||||||
}
|
}
|
||||||
printf ("|\n");
|
printf ("|\n");
|
||||||
printf ("Done, %d of %d pages written (%d first pages are skipped).\n", uiWritenPages, uiBlocks + 1, write_otp?3:4);
|
printf ("Done, %d of %d pages written (%d first pages are skipped).\n", uiWritenPages, uiBlocks + 1,
|
||||||
|
write_otp ? 3 : 4);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -143,9 +143,9 @@ write_card (void)
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
bool bReadAction;
|
bool bReadAction;
|
||||||
byte_t *pbtUID;
|
byte_t *pbtUID;
|
||||||
FILE *pfDump;
|
FILE *pfDump;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
|
@ -191,28 +191,26 @@ main (int argc, const char *argv[])
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
@ -230,7 +228,6 @@ main (int argc, const char *argv[])
|
||||||
nfc_disconnect (pnd);
|
nfc_disconnect (pnd);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the info from the current tag (UID is stored little-endian)
|
// Get the info from the current tag (UID is stored little-endian)
|
||||||
pbtUID = nti.nai.abtUid;
|
pbtUID = nti.nai.abtUid;
|
||||||
printf ("Found MIFARE Ultralight card with UID: %02x%02x%02x%02x\n", pbtUID[3], pbtUID[2], pbtUID[1], pbtUID[0]);
|
printf ("Found MIFARE Ultralight card with UID: %02x%02x%02x%02x\n", pbtUID[3], pbtUID[2], pbtUID[1], pbtUID[0]);
|
||||||
|
|
|
@ -44,8 +44,8 @@ static nfc_device_t *pnd;
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
size_t szFound;
|
size_t szFound;
|
||||||
size_t i;
|
size_t i;
|
||||||
nfc_device_desc_t *pnddDevices;
|
nfc_device_desc_t *pnddDevices;
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
|
@ -76,8 +76,8 @@ main (int argc, const char *argv[])
|
||||||
const size_t szTargetTypes = 1;
|
const size_t szTargetTypes = 1;
|
||||||
|
|
||||||
nfc_target_t antTargets[2];
|
nfc_target_t antTargets[2];
|
||||||
size_t szTargetFound;
|
size_t szTargetFound;
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
pnd = nfc_connect (&(pnddDevices[i]));
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
|
|
||||||
|
@ -89,30 +89,27 @@ main (int argc, const char *argv[])
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
// Configure the CRC and Parity settings
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -46,55 +46,58 @@ static size_t szReaderRxBits;
|
||||||
static byte_t abtTagRx[MAX_FRAME_LEN];
|
static byte_t abtTagRx[MAX_FRAME_LEN];
|
||||||
static byte_t abtTagRxPar[MAX_FRAME_LEN];
|
static byte_t abtTagRxPar[MAX_FRAME_LEN];
|
||||||
static size_t szTagRxBits;
|
static size_t szTagRxBits;
|
||||||
static nfc_device_t* pndReader;
|
static nfc_device_t *pndReader;
|
||||||
static nfc_device_t* pndTag;
|
static nfc_device_t *pndTag;
|
||||||
static bool quitting=false;
|
static bool quitting = false;
|
||||||
|
|
||||||
void intr_hdlr(void)
|
void
|
||||||
|
intr_hdlr (void)
|
||||||
{
|
{
|
||||||
printf("\nQuitting...\n");
|
printf ("\nQuitting...\n");
|
||||||
quitting=true;
|
quitting = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_usage(char* argv[])
|
void
|
||||||
|
print_usage (char *argv[])
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
printf ("Usage: %s [OPTIONS]\n", argv[0]);
|
||||||
printf("Options:\n");
|
printf ("Options:\n");
|
||||||
printf("\t-h\tHelp. Print this message.\n");
|
printf ("\t-h\tHelp. Print this message.\n");
|
||||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc,char* argv[])
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int arg;
|
int arg;
|
||||||
bool quiet_output = false;
|
bool quiet_output = false;
|
||||||
size_t szFound;
|
size_t szFound;
|
||||||
nfc_device_desc_t *pnddDevices;
|
nfc_device_desc_t *pnddDevices;
|
||||||
const char* acLibnfcVersion = nfc_version();
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
|
|
||||||
// Get commandline options
|
// Get commandline options
|
||||||
for (arg=1;arg<argc;arg++) {
|
for (arg = 1; arg < argc; arg++) {
|
||||||
if (0 == strcmp(argv[arg], "-h")) {
|
if (0 == strcmp (argv[arg], "-h")) {
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
} else if (0 == strcmp (argv[arg], "-q")) {
|
||||||
INFO("%s", "Quiet mode.");
|
INFO ("%s", "Quiet mode.");
|
||||||
quiet_output = true;
|
quiet_output = true;
|
||||||
} else {
|
} else {
|
||||||
ERR("%s is not supported option.", argv[arg]);
|
ERR ("%s is not supported option.", argv[arg]);
|
||||||
print_usage(argv);
|
print_usage (argv);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
signal(SIGINT, (void (__cdecl*)(int)) intr_hdlr);
|
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
|
||||||
#else
|
#else
|
||||||
signal(SIGINT, (void (*)()) intr_hdlr);
|
signal (SIGINT, (void (*)()) intr_hdlr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Allocate memory to put the result of available devices listing
|
// Allocate memory to put the result of available devices listing
|
||||||
|
@ -102,105 +105,93 @@ int main(int argc,char* argv[])
|
||||||
fprintf (stderr, "malloc() failed\n");
|
fprintf (stderr, "malloc() failed\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// List available devices
|
// List available devices
|
||||||
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
|
|
||||||
if (szFound < 2) {
|
if (szFound < 2) {
|
||||||
ERR("%zd device found but two connected devices are needed to relay NFC.", szFound);
|
ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to open the NFC emulator device
|
// Try to open the NFC emulator device
|
||||||
pndTag = nfc_connect(&(pnddDevices[0]));
|
pndTag = nfc_connect (&(pnddDevices[0]));
|
||||||
if (pndTag == NULL)
|
if (pndTag == NULL) {
|
||||||
{
|
printf ("Error connecting NFC emulator device\n");
|
||||||
printf("Error connecting NFC emulator device\n");
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Hint: tag <---> emulator (relay) <---> reader (relay) <---> original reader\n\n");
|
printf ("Hint: tag <---> emulator (relay) <---> reader (relay) <---> original reader\n\n");
|
||||||
|
|
||||||
printf("Connected to the NFC emulator device: %s\n", pndTag->acName);
|
printf ("Connected to the NFC emulator device: %s\n", pndTag->acName);
|
||||||
printf("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
||||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
printf ("[+] To do this, please send any command after the anti-collision\n");
|
||||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
||||||
if (!nfc_target_init(pndTag,abtReaderRx,&szReaderRxBits))
|
if (!nfc_target_init (pndTag, abtReaderRx, &szReaderRxBits)) {
|
||||||
{
|
ERR ("%s", "Initialization of NFC emulator failed");
|
||||||
ERR("%s", "Initialization of NFC emulator failed");
|
nfc_disconnect (pndTag);
|
||||||
nfc_disconnect(pndTag);
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
printf("%s", "Configuring emulator settings...");
|
printf ("%s", "Configuring emulator settings...");
|
||||||
if (!nfc_configure(pndTag,NDO_HANDLE_CRC,false) ||
|
if (!nfc_configure (pndTag, NDO_HANDLE_CRC, false) ||
|
||||||
!nfc_configure(pndTag,NDO_HANDLE_PARITY,false) ||
|
!nfc_configure (pndTag, NDO_HANDLE_PARITY, false) || !nfc_configure (pndTag, NDO_ACCEPT_INVALID_FRAMES, true)) {
|
||||||
!nfc_configure(pndTag,NDO_ACCEPT_INVALID_FRAMES,true)) {
|
nfc_perror (pndTag, "nfc_configure");
|
||||||
nfc_perror(pndTag, "nfc_configure");
|
exit (EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
printf("%s", "Done, emulated tag is initialized");
|
printf ("%s", "Done, emulated tag is initialized");
|
||||||
|
|
||||||
// Try to open the NFC reader
|
// Try to open the NFC reader
|
||||||
pndReader = nfc_connect(&(pnddDevices[1]));
|
pndReader = nfc_connect (&(pnddDevices[1]));
|
||||||
|
|
||||||
printf("Connected to the NFC reader device: %s", pndReader->acName);
|
printf ("Connected to the NFC reader device: %s", pndReader->acName);
|
||||||
printf("%s", "Configuring NFC reader settings...");
|
printf ("%s", "Configuring NFC reader settings...");
|
||||||
nfc_initiator_init(pndReader);
|
nfc_initiator_init (pndReader);
|
||||||
if (!nfc_configure(pndReader,NDO_HANDLE_CRC,false) ||
|
if (!nfc_configure (pndReader, NDO_HANDLE_CRC, false) ||
|
||||||
!nfc_configure(pndReader,NDO_HANDLE_PARITY,false) ||
|
!nfc_configure (pndReader, NDO_HANDLE_PARITY, false) ||
|
||||||
!nfc_configure(pndReader,NDO_ACCEPT_INVALID_FRAMES,true)) {
|
!nfc_configure (pndReader, NDO_ACCEPT_INVALID_FRAMES, true)) {
|
||||||
nfc_perror(pndReader, "nfc_configure");
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
printf("%s", "Done, relaying frames now!");
|
printf ("%s", "Done, relaying frames now!");
|
||||||
|
|
||||||
while(!quitting)
|
while (!quitting) {
|
||||||
{
|
|
||||||
// Test if we received a frame from the reader
|
// Test if we received a frame from the reader
|
||||||
if (nfc_target_receive_bits(pndTag,abtReaderRx,&szReaderRxBits,abtReaderRxPar))
|
if (nfc_target_receive_bits (pndTag, abtReaderRx, &szReaderRxBits, abtReaderRxPar)) {
|
||||||
{
|
|
||||||
// Drop down the field before sending a REQA command and start a new session
|
// Drop down the field before sending a REQA command and start a new session
|
||||||
if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26)
|
if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) {
|
||||||
{
|
|
||||||
// Drop down field for a very short time (original tag will reboot)
|
// Drop down field for a very short time (original tag will reboot)
|
||||||
if (!nfc_configure(pndReader,NDO_ACTIVATE_FIELD,false)) {
|
if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pndReader, "nfc_configure");
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if(!quiet_output)
|
if (!quiet_output)
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
if (!nfc_configure(pndReader,NDO_ACTIVATE_FIELD,true)) {
|
if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pndReader, "nfc_configure");
|
nfc_perror (pndReader, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the reader frame to the screen
|
// Print the reader frame to the screen
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("R: ");
|
||||||
printf("R: ");
|
print_hex_par (abtReaderRx, szReaderRxBits, abtReaderRxPar);
|
||||||
print_hex_par(abtReaderRx,szReaderRxBits,abtReaderRxPar);
|
|
||||||
}
|
}
|
||||||
// Forward the frame to the original tag
|
// Forward the frame to the original tag
|
||||||
if (nfc_initiator_transceive_bits(pndReader,abtReaderRx,szReaderRxBits,abtReaderRxPar,abtTagRx,&szTagRxBits,abtTagRxPar))
|
if (nfc_initiator_transceive_bits
|
||||||
{
|
(pndReader, abtReaderRx, szReaderRxBits, abtReaderRxPar, abtTagRx, &szTagRxBits, abtTagRxPar)) {
|
||||||
// Redirect the answer back to the reader
|
// Redirect the answer back to the reader
|
||||||
if (!nfc_target_send_bits(pndTag,abtTagRx,szTagRxBits,abtTagRxPar)) {
|
if (!nfc_target_send_bits (pndTag, abtTagRx, szTagRxBits, abtTagRxPar)) {
|
||||||
nfc_perror(pndTag, "nfc_target_send_bits");
|
nfc_perror (pndTag, "nfc_target_send_bits");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the tag frame to the screen
|
// Print the tag frame to the screen
|
||||||
if(!quiet_output)
|
if (!quiet_output) {
|
||||||
{
|
printf ("T: ");
|
||||||
printf("T: ");
|
print_hex_par (abtTagRx, szTagRxBits, abtTagRxPar);
|
||||||
print_hex_par(abtTagRx,szTagRxBits,abtTagRxPar);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_disconnect(pndTag);
|
nfc_disconnect (pndTag);
|
||||||
nfc_disconnect(pndReader);
|
nfc_disconnect (pndReader);
|
||||||
exit(EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -32,14 +32,14 @@
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Needed by sleep() under Unix
|
// Needed by sleep() under Unix
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#define sleep sleep
|
# define sleep sleep
|
||||||
#define SUSP_TIME 1 // secs.
|
# define SUSP_TIME 1 // secs.
|
||||||
#else
|
#else
|
||||||
// Needed by Sleep() under Windows
|
// Needed by Sleep() under Windows
|
||||||
#include <winbase.h>
|
# include <winbase.h>
|
||||||
#define sleep Sleep
|
# define sleep Sleep
|
||||||
#define SUSP_TIME 1000 // msecs.
|
# define SUSP_TIME 1000 // msecs.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
@ -49,183 +49,178 @@
|
||||||
#include "chips/pn53x.h"
|
#include "chips/pn53x.h"
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
#define TIMEOUT 60 // secs.
|
#define TIMEOUT 60 // secs.
|
||||||
|
|
||||||
#define NORMAL_MODE 1
|
#define NORMAL_MODE 1
|
||||||
#define VIRTUAL_CARD_MODE 2
|
#define VIRTUAL_CARD_MODE 2
|
||||||
#define WIRED_CARD_MODE 3
|
#define WIRED_CARD_MODE 3
|
||||||
#define DUAL_CARD_MODE 4
|
#define DUAL_CARD_MODE 4
|
||||||
|
|
||||||
bool sam_connection(nfc_device_t* pnd, int mode)
|
bool
|
||||||
|
sam_connection (nfc_device_t * pnd, int mode)
|
||||||
{
|
{
|
||||||
byte_t pncmd_sam_config[] = { 0xD4,0x14,0x00,0x00 };
|
byte_t pncmd_sam_config[] = { 0xD4, 0x14, 0x00, 0x00 };
|
||||||
size_t szCmd = 0;
|
size_t szCmd = 0;
|
||||||
|
|
||||||
byte_t abtRx[MAX_FRAME_LEN];
|
byte_t abtRx[MAX_FRAME_LEN];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
|
|
||||||
pncmd_sam_config[2] = mode;
|
pncmd_sam_config[2] = mode;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode) {
|
||||||
{
|
case VIRTUAL_CARD_MODE:
|
||||||
case VIRTUAL_CARD_MODE:
|
|
||||||
{
|
{
|
||||||
// Only the VIRTUAL_CARD_MODE requires 4 bytes.
|
// Only the VIRTUAL_CARD_MODE requires 4 bytes.
|
||||||
szCmd = sizeof(pncmd_sam_config);
|
szCmd = sizeof (pncmd_sam_config);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
szCmd = sizeof(pncmd_sam_config)-1;
|
szCmd = sizeof (pncmd_sam_config) - 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Direct call
|
// FIXME: Direct call
|
||||||
if (!pn53x_transceive(pnd,pncmd_sam_config,szCmd,abtRx,&szRxLen)) {
|
if (!pn53x_transceive (pnd, pncmd_sam_config, szCmd, abtRx, &szRxLen)) {
|
||||||
ERR("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode);
|
ERR ("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_one_minute()
|
void
|
||||||
|
wait_one_minute ()
|
||||||
{
|
{
|
||||||
int secs = 0;
|
int secs = 0;
|
||||||
|
|
||||||
printf("|");
|
printf ("|");
|
||||||
fflush(stdout);
|
fflush (stdout);
|
||||||
|
|
||||||
while (secs < TIMEOUT)
|
while (secs < TIMEOUT) {
|
||||||
{
|
sleep (SUSP_TIME);
|
||||||
sleep(SUSP_TIME);
|
|
||||||
secs++;
|
secs++;
|
||||||
printf(".");
|
printf (".");
|
||||||
fflush(stdout);
|
fflush (stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("|\n");
|
printf ("|\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
nfc_device_t* pnd;
|
nfc_device_t *pnd;
|
||||||
|
|
||||||
(void)argc;
|
(void) argc;
|
||||||
(void)argv;
|
(void) argv;
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
const char* acLibnfcVersion = nfc_version();
|
const char *acLibnfcVersion = nfc_version ();
|
||||||
printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
// Connect using the first available NFC device
|
// Connect using the first available NFC device
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("%s", "Unable to connect to NFC device.");
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Connected to NFC reader: %s\n",pnd->acName);
|
printf ("Connected to NFC reader: %s\n", pnd->acName);
|
||||||
|
|
||||||
// Print the example's menu
|
// Print the example's menu
|
||||||
printf("\nSelect the comunication mode:\n");
|
printf ("\nSelect the comunication mode:\n");
|
||||||
printf("[1] Virtual card mode.\n");
|
printf ("[1] Virtual card mode.\n");
|
||||||
printf("[2] Wired card mode.\n");
|
printf ("[2] Wired card mode.\n");
|
||||||
printf("[3] Dual card mode.\n");
|
printf ("[3] Dual card mode.\n");
|
||||||
printf(">> ");
|
printf (">> ");
|
||||||
|
|
||||||
// Take user's choice
|
// Take user's choice
|
||||||
char input = getchar();
|
char input = getchar ();
|
||||||
int mode = input-'0'+1;
|
int mode = input - '0' + 1;
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
|
if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
|
||||||
ERR("%s", "Invalid selection.");
|
ERR ("%s", "Invalid selection.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect with the SAM
|
// Connect with the SAM
|
||||||
sam_connection(pnd, mode);
|
sam_connection (pnd, mode);
|
||||||
|
|
||||||
switch (mode)
|
switch (mode) {
|
||||||
{
|
case VIRTUAL_CARD_MODE:
|
||||||
case VIRTUAL_CARD_MODE:
|
|
||||||
{
|
{
|
||||||
// FIXME: after the loop the reader doesn't respond to host commands...
|
// FIXME: after the loop the reader doesn't respond to host commands...
|
||||||
printf("Now the SAM is readable for 1 minute from an external reader.\n");
|
printf ("Now the SAM is readable for 1 minute from an external reader.\n");
|
||||||
wait_one_minute();
|
wait_one_minute ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIRED_CARD_MODE:
|
case WIRED_CARD_MODE:
|
||||||
{
|
{
|
||||||
nfc_target_info_t nti;
|
nfc_target_info_t nti;
|
||||||
|
|
||||||
// Set connected NFC device to initiator mode
|
// Set connected NFC device to initiator mode
|
||||||
nfc_initiator_init(pnd);
|
nfc_initiator_init (pnd);
|
||||||
|
|
||||||
// Drop the field for a while
|
// Drop the field for a while
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,false)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (!nfc_configure(pnd,NDO_INFINITE_SELECT,false)) {
|
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the CRC and Parity settings
|
// Configure the CRC and Parity settings
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_CRC,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) {
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable field so more power consuming cards can power themselves up
|
// Enable field so more power consuming cards can power themselves up
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_FIELD,true)) {
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
|
||||||
nfc_perror(pnd, "nfc_configure");
|
nfc_perror (pnd, "nfc_configure");
|
||||||
exit(EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the SAM's info
|
// Read the SAM's info
|
||||||
if (!nfc_initiator_select_passive_target(pnd,NM_ISO14443A_106,NULL,0,&nti)) {
|
if (!nfc_initiator_select_passive_target (pnd, NM_ISO14443A_106, NULL, 0, &nti)) {
|
||||||
ERR("%s", "Reading of SAM info failed.");
|
ERR ("%s", "Reading of SAM info failed.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("The following ISO14443A tag (SAM) was found:\n\n");
|
printf ("The following ISO14443A tag (SAM) was found:\n\n");
|
||||||
print_nfc_iso14443a_info (nti.nai);
|
print_nfc_iso14443a_info (nti.nai);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DUAL_CARD_MODE:
|
case DUAL_CARD_MODE:
|
||||||
{
|
{
|
||||||
byte_t abtRx[MAX_FRAME_LEN];
|
byte_t abtRx[MAX_FRAME_LEN];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
|
|
||||||
// FIXME: it does not work as expected...Probably the issue is in "nfc_target_init"
|
// FIXME: it does not work as expected...Probably the issue is in "nfc_target_init"
|
||||||
// which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc.
|
// which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc.
|
||||||
if (!nfc_target_init(pnd,abtRx,&szRxLen))
|
if (!nfc_target_init (pnd, abtRx, &szRxLen))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
printf("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");
|
printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");
|
||||||
wait_one_minute();
|
wait_one_minute ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from the SAM
|
// Disconnect from the SAM
|
||||||
sam_connection(pnd, NORMAL_MODE);
|
sam_connection (pnd, NORMAL_MODE);
|
||||||
|
|
||||||
// Disconnect from NFC device
|
// Disconnect from NFC device
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,152 +21,165 @@ static const byte_t OddParity[256] = {
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
byte_t oddparity(const byte_t bt)
|
byte_t
|
||||||
|
oddparity (const byte_t bt)
|
||||||
{
|
{
|
||||||
return OddParity[bt];
|
return OddParity[bt];
|
||||||
}
|
}
|
||||||
|
|
||||||
void oddparity_bytes_ts(const byte_t* pbtData, const size_t szLen, byte_t* pbtPar)
|
void
|
||||||
|
oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
|
||||||
{
|
{
|
||||||
size_t szByteNr;
|
size_t szByteNr;
|
||||||
// Calculate the parity bits for the command
|
// Calculate the parity bits for the command
|
||||||
for (szByteNr=0; szByteNr<szLen; szByteNr++)
|
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
||||||
{
|
|
||||||
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex(const byte_t* pbtData, const size_t szBytes)
|
void
|
||||||
|
print_hex (const byte_t * pbtData, const size_t szBytes)
|
||||||
{
|
{
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
|
|
||||||
for (szPos=0; szPos < szBytes; szPos++)
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
{
|
printf ("%02x ", pbtData[szPos]);
|
||||||
printf("%02x ",pbtData[szPos]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_hex_bits(const byte_t* pbtData, const size_t szBits)
|
void
|
||||||
|
print_hex_bits (const byte_t * pbtData, const size_t szBits)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
size_t szBytes = szBits/8;
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
for (szPos=0; szPos < szBytes; szPos++)
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
{
|
printf ("%02x ", pbtData[szPos]);
|
||||||
printf("%02x ",pbtData[szPos]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uRemainder = szBits % 8;
|
uRemainder = szBits % 8;
|
||||||
// Print the rest bits
|
// Print the rest bits
|
||||||
if (uRemainder != 0)
|
if (uRemainder != 0) {
|
||||||
{
|
|
||||||
if (uRemainder < 5)
|
if (uRemainder < 5)
|
||||||
printf("%01x (%d bits)",pbtData[szBytes], uRemainder);
|
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
else
|
else
|
||||||
printf("%02x (%d bits)",pbtData[szBytes], uRemainder);
|
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
size_t szBytes = szBits/8;
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
for (szPos=0; szPos < szBytes; szPos++)
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
{
|
printf ("%02x", pbtData[szPos]);
|
||||||
printf("%02x",pbtData[szPos]);
|
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
|
||||||
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos])
|
printf ("! ");
|
||||||
{
|
|
||||||
printf("! ");
|
|
||||||
} else {
|
} else {
|
||||||
printf(" ");
|
printf (" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uRemainder = szBits % 8;
|
uRemainder = szBits % 8;
|
||||||
// Print the rest bits, these cannot have parity bit
|
// Print the rest bits, these cannot have parity bit
|
||||||
if (uRemainder != 0)
|
if (uRemainder != 0) {
|
||||||
{
|
|
||||||
if (uRemainder < 5)
|
if (uRemainder < 5)
|
||||||
printf("%01x (%d bits)",pbtData[szBytes], uRemainder);
|
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
else
|
else
|
||||||
printf("%02x (%d bits)",pbtData[szBytes], uRemainder);
|
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAK_ISO14443_4_COMPLIANT 0x20
|
#define SAK_ISO14443_4_COMPLIANT 0x20
|
||||||
#define SAK_ISO18092_COMPLIANT 0x40
|
#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): ");
|
||||||
printf(" UID (NFCID%c): ",(nai.abtUid[0]==0x08?'3':'1')); print_hex(nai.abtUid, nai.szUidLen);
|
print_hex (nai.abtAtqa, 2);
|
||||||
printf(" SAK (SEL_RES): "); print_hex(&nai.btSak,1);
|
printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
|
||||||
|
print_hex (nai.abtUid, nai.szUidLen);
|
||||||
|
printf (" SAK (SEL_RES): ");
|
||||||
|
print_hex (&nai.btSak, 1);
|
||||||
if (nai.szAtsLen) {
|
if (nai.szAtsLen) {
|
||||||
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) ) {
|
if ((nai.btSak & SAK_ISO14443_4_COMPLIANT) || (nai.btSak & SAK_ISO18092_COMPLIANT)) {
|
||||||
printf(" Compliant with: ");
|
printf (" Compliant with: ");
|
||||||
if (nai.btSak & SAK_ISO14443_4_COMPLIANT) printf("ISO/IEC 14443-4 ");
|
if (nai.btSak & SAK_ISO14443_4_COMPLIANT)
|
||||||
if (nai.btSak & SAK_ISO18092_COMPLIANT) printf("ISO/IEC 18092");
|
printf ("ISO/IEC 14443-4 ");
|
||||||
printf("\n");
|
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)
|
void
|
||||||
|
print_nfc_felica_info (const nfc_felica_info_t nfi)
|
||||||
{
|
{
|
||||||
printf(" ATQB: "); print_hex(nbi.abtAtqb,12);
|
printf (" ID (NFCID2): ");
|
||||||
printf(" ID: "); print_hex(nbi.abtId,4);
|
print_hex (nfi.abtId, 8);
|
||||||
printf(" CID: %02x\n",nbi.btCid);
|
printf (" Parameter (PAD): ");
|
||||||
if (nbi.szInfLen>0) {
|
print_hex (nfi.abtPad, 8);
|
||||||
printf(" INF: "); print_hex(nbi.abtInf,nbi.szInfLen);
|
}
|
||||||
|
|
||||||
|
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);
|
printf (" PARAMS: %02x %02x %02x %02x\n", nbi.btParam1, nbi.btParam2, nbi.btParam3, nbi.btParam4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Tries to parse arguments to find device descriptions.
|
* @brief Tries to parse arguments to find device descriptions.
|
||||||
* @return Returns the list of found device descriptions.
|
* @return Returns the list of found device descriptions.
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
nfc_device_desc_t* pndd = 0;
|
nfc_device_desc_t *pndd = 0;
|
||||||
int arg;
|
int arg;
|
||||||
*szFound = 0;
|
*szFound = 0;
|
||||||
|
|
||||||
// Get commandline options
|
// Get commandline options
|
||||||
for (arg=1;arg<argc;arg++) {
|
for (arg = 1; arg < argc; arg++) {
|
||||||
|
|
||||||
if (0 == strcmp(argv[arg], "--device")) {
|
if (0 == strcmp (argv[arg], "--device")) {
|
||||||
|
|
||||||
if (argc > arg+1) {
|
if (argc > arg + 1) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
|
||||||
pndd = malloc(sizeof(nfc_device_desc_t));
|
pndd = malloc (sizeof (nfc_device_desc_t));
|
||||||
|
|
||||||
strncpy(buffer, argv[++arg], 256);
|
strncpy (buffer, argv[++arg], 256);
|
||||||
|
|
||||||
// Driver.
|
// Driver.
|
||||||
pndd->pcDriver = (char *)malloc(256);
|
pndd->pcDriver = (char *) malloc (256);
|
||||||
strcpy(pndd->pcDriver, strtok(buffer, ":"));
|
strcpy (pndd->pcDriver, strtok (buffer, ":"));
|
||||||
|
|
||||||
// Port.
|
// Port.
|
||||||
pndd->pcPort = (char *)malloc(256);
|
pndd->pcPort = (char *) malloc (256);
|
||||||
strcpy(pndd->pcPort, strtok(NULL, ":"));
|
strcpy (pndd->pcPort, strtok (NULL, ":"));
|
||||||
|
|
||||||
// Speed.
|
// Speed.
|
||||||
sscanf(strtok(NULL, ":"), "%u", &pndd->uiSpeed);
|
sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
|
||||||
|
|
||||||
*szFound = 1;
|
*szFound = 1;
|
||||||
}
|
}
|
||||||
|
@ -176,4 +189,3 @@ nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFou
|
||||||
|
|
||||||
return pndd;
|
return pndd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,22 +22,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _EXAMPLES_NFC_UTILS_H_
|
#ifndef _EXAMPLES_NFC_UTILS_H_
|
||||||
#define _EXAMPLES_NFC_UTILS_H_
|
# define _EXAMPLES_NFC_UTILS_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
#include <string.h>
|
# include <string.h>
|
||||||
|
|
||||||
byte_t oddparity(const byte_t bt);
|
byte_t oddparity (const byte_t bt);
|
||||||
void oddparity_byte_ts(const byte_t* pbtData, const size_t szLen, byte_t* pbtPar);
|
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);
|
||||||
|
|
||||||
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_iso14443b_info (const nfc_iso14443b_info_t nbi);
|
||||||
void print_nfc_felica_info(const nfc_felica_info_t nfi);
|
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
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
@ -33,40 +33,36 @@
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
nfc_device_t *pnd;
|
nfc_device_t *pnd;
|
||||||
nfc_target_info_t ti;
|
nfc_target_info_t ti;
|
||||||
byte_t abtRecv[MAX_FRAME_LEN];
|
byte_t abtRecv[MAX_FRAME_LEN];
|
||||||
size_t szRecvBits;
|
size_t szRecvBits;
|
||||||
byte_t send[] = "Hello World!";
|
byte_t send[] = "Hello World!";
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
errx (1, "usage: %s", argv[0]);
|
errx (1, "usage: %s", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pnd = nfc_connect(NULL);
|
pnd = nfc_connect (NULL);
|
||||||
if (!pnd || !nfc_initiator_init(pnd)
|
if (!pnd || !nfc_initiator_init (pnd)
|
||||||
|| !nfc_initiator_select_dep_target(pnd, NM_PASSIVE_DEP, NULL, 0,
|
|| !nfc_initiator_select_dep_target (pnd, NM_PASSIVE_DEP, NULL, 0, NULL, 0, NULL, 0, &ti)) {
|
||||||
NULL, 0, NULL, 0, &ti)) {
|
printf ("unable to connect, initialize, or select the target\n");
|
||||||
printf
|
|
||||||
("unable to connect, initialize, or select the target\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Sending : %s\n", send);
|
printf ("Sending : %s\n", send);
|
||||||
if (!nfc_initiator_transceive_bytes(pnd,
|
if (!nfc_initiator_transceive_bytes (pnd, send, strlen ((char *) send), abtRecv, &szRecvBits)) {
|
||||||
send,
|
printf ("unable to send data\n");
|
||||||
strlen((char*)send), abtRecv,
|
|
||||||
&szRecvBits)) {
|
|
||||||
printf("unable to send data\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
abtRecv[szRecvBits] = 0;
|
abtRecv[szRecvBits] = 0;
|
||||||
printf("Received: %s\n", abtRecv);
|
printf ("Received: %s\n", abtRecv);
|
||||||
|
|
||||||
nfc_initiator_deselect_target(pnd);
|
nfc_initiator_deselect_target (pnd);
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
@ -33,35 +33,36 @@
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
byte_t abtRecv[MAX_FRAME_LEN];
|
byte_t abtRecv[MAX_FRAME_LEN];
|
||||||
size_t szRecvBits;
|
size_t szRecvBits;
|
||||||
byte_t send[] = "Hello Mars!";
|
byte_t send[] = "Hello Mars!";
|
||||||
nfc_device_t *pnd = nfc_connect(NULL);
|
nfc_device_t *pnd = nfc_connect (NULL);
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
errx (1, "usage: %s", argv[0]);
|
errx (1, "usage: %s", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pnd || !nfc_target_init(pnd, abtRecv, &szRecvBits)) {
|
if (!pnd || !nfc_target_init (pnd, abtRecv, &szRecvBits)) {
|
||||||
printf("unable to connect or initialize\n");
|
printf ("unable to connect or initialize\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nfc_target_receive_bytes(pnd, abtRecv, &szRecvBits)) {
|
if (!nfc_target_receive_bytes (pnd, abtRecv, &szRecvBits)) {
|
||||||
printf("unable to receive data\n");
|
printf ("unable to receive data\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
abtRecv[szRecvBits] = 0;
|
abtRecv[szRecvBits] = 0;
|
||||||
printf("Received: %s\n", abtRecv);
|
printf ("Received: %s\n", abtRecv);
|
||||||
printf("Sending : %s\n", send);
|
printf ("Sending : %s\n", send);
|
||||||
|
|
||||||
if (!nfc_target_send_bytes(pnd, send, 11)) {
|
if (!nfc_target_send_bytes (pnd, send, 11)) {
|
||||||
printf("unable to send data\n");
|
printf ("unable to send data\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect (pnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,17 +35,18 @@
|
||||||
#define MAX_DEVICE_COUNT 16
|
#define MAX_DEVICE_COUNT 16
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int
|
||||||
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
size_t szFound;
|
size_t szFound;
|
||||||
size_t i;
|
size_t i;
|
||||||
nfc_device_t* pnd;
|
nfc_device_t *pnd;
|
||||||
nfc_device_desc_t *pnddDevices;
|
nfc_device_desc_t *pnddDevices;
|
||||||
const char* acLibnfcVersion;
|
const char *acLibnfcVersion;
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
byte_t abtRx[MAX_FRAME_LEN];
|
byte_t abtRx[MAX_FRAME_LEN];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
const byte_t pncmd_diagnose_communication_line_test[] = { 0xD4, 0x00, 0x00, 0x06, 'l', 'i', 'b', 'n', 'f', 'c' };
|
const byte_t pncmd_diagnose_communication_line_test[] = { 0xD4, 0x00, 0x00, 0x06, 'l', 'i', 'b', 'n', 'f', 'c' };
|
||||||
const byte_t pncmd_diagnose_rom_test[] = { 0xD4, 0x00, 0x01 };
|
const byte_t pncmd_diagnose_rom_test[] = { 0xD4, 0x00, 0x01 };
|
||||||
const byte_t pncmd_diagnose_ram_test[] = { 0xD4, 0x00, 0x02 };
|
const byte_t pncmd_diagnose_ram_test[] = { 0xD4, 0x00, 0x02 };
|
||||||
|
@ -53,10 +54,9 @@ int main(int argc, const char* argv[])
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
errx (1, "usage: %s", argv[0]);
|
errx (1, "usage: %s", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display libnfc version
|
// Display libnfc version
|
||||||
acLibnfcVersion = nfc_version();
|
acLibnfcVersion = nfc_version ();
|
||||||
printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
|
||||||
|
|
||||||
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
|
||||||
fprintf (stderr, "malloc() failed\n");
|
fprintf (stderr, "malloc() failed\n");
|
||||||
|
@ -66,38 +66,42 @@ int main(int argc, const char* argv[])
|
||||||
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
|
||||||
|
|
||||||
if (szFound == 0) {
|
if (szFound == 0) {
|
||||||
INFO("%s", "No device found.");
|
INFO ("%s", "No device found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < szFound; i++) {
|
for (i = 0; i < szFound; i++) {
|
||||||
pnd = nfc_connect(&(pnddDevices[i]));
|
pnd = nfc_connect (&(pnddDevices[i]));
|
||||||
|
|
||||||
if (pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
ERR("%s", "Unable to connect to NFC device.");
|
ERR ("%s", "Unable to connect to NFC device.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("NFC device [%s] connected.\n",pnd->acName);
|
printf ("NFC device [%s] connected.\n", pnd->acName);
|
||||||
|
|
||||||
// FIXME: Direct call
|
// FIXME: Direct call
|
||||||
result = pn53x_transceive(pnd,pncmd_diagnose_communication_line_test,sizeof(pncmd_diagnose_communication_line_test),abtRx,&szRxLen);
|
result =
|
||||||
if ( result ) {
|
pn53x_transceive (pnd, pncmd_diagnose_communication_line_test, sizeof (pncmd_diagnose_communication_line_test),
|
||||||
result = (memcmp(pncmd_diagnose_communication_line_test+2, abtRx, sizeof(pncmd_diagnose_communication_line_test)-2 ) == 0);
|
abtRx, &szRxLen);
|
||||||
|
if (result) {
|
||||||
|
result =
|
||||||
|
(memcmp (pncmd_diagnose_communication_line_test + 2, abtRx, sizeof (pncmd_diagnose_communication_line_test) - 2)
|
||||||
|
== 0);
|
||||||
}
|
}
|
||||||
printf(" Communication line test: %s\n", result ? "OK" : "Failed");
|
printf (" Communication line test: %s\n", result ? "OK" : "Failed");
|
||||||
|
|
||||||
// FIXME: Direct call
|
// FIXME: Direct call
|
||||||
result = pn53x_transceive(pnd,pncmd_diagnose_rom_test,sizeof(pncmd_diagnose_rom_test),abtRx,&szRxLen);
|
result = pn53x_transceive (pnd, pncmd_diagnose_rom_test, sizeof (pncmd_diagnose_rom_test), abtRx, &szRxLen);
|
||||||
if ( result ) {
|
if (result) {
|
||||||
result = ((szRxLen == 1) && (abtRx[0] == 0x00));
|
result = ((szRxLen == 1) && (abtRx[0] == 0x00));
|
||||||
}
|
}
|
||||||
printf(" ROM test: %s\n", result ? "OK" : "Failed");
|
printf (" ROM test: %s\n", result ? "OK" : "Failed");
|
||||||
|
|
||||||
// FIXME: Direct call
|
// FIXME: Direct call
|
||||||
result = pn53x_transceive(pnd,pncmd_diagnose_ram_test,sizeof(pncmd_diagnose_ram_test),abtRx,&szRxLen);
|
result = pn53x_transceive (pnd, pncmd_diagnose_ram_test, sizeof (pncmd_diagnose_ram_test), abtRx, &szRxLen);
|
||||||
if ( result ) {
|
if (result) {
|
||||||
result = ((szRxLen == 1) && (abtRx[0] == 0x00));
|
result = ((szRxLen == 1) && (abtRx[0] == 0x00));
|
||||||
}
|
}
|
||||||
printf(" RAM test: %s\n", result ? "OK" : "Failed");
|
printf (" RAM test: %s\n", result ? "OK" : "Failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,25 +22,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBNFC_MESSAGES_H_
|
#ifndef _LIBNFC_MESSAGES_H_
|
||||||
#define _LIBNFC_MESSAGES_H_
|
# define _LIBNFC_MESSAGES_H_
|
||||||
|
|
||||||
#include <err.h>
|
# include <err.h>
|
||||||
|
|
||||||
// #define DEBUG /* DEBUG flag can also be enabled using ./configure --enable-debug */
|
// #define DEBUG /* DEBUG flag can also be enabled using ./configure --enable-debug */
|
||||||
|
|
||||||
// Useful macros
|
// Useful macros
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
// #define DBG(x, args...) printf("DBG %s:%d: " x "\n", __FILE__, __LINE__,## args )
|
// #define DBG(x, args...) printf("DBG %s:%d: " x "\n", __FILE__, __LINE__,## args )
|
||||||
#define DBG(...) do { \
|
# define DBG(...) do { \
|
||||||
warnx ("DBG %s:%d", __FILE__, __LINE__); \
|
warnx ("DBG %s:%d", __FILE__, __LINE__); \
|
||||||
warnx (" " __VA_ARGS__ ); \
|
warnx (" " __VA_ARGS__ ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
# else
|
||||||
#define DBG(...) {}
|
# define DBG(...) {}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#define INFO(...) warnx ("INFO: " __VA_ARGS__ )
|
# define INFO(...) warnx ("INFO: " __VA_ARGS__ )
|
||||||
#define WARN(...) warnx ("WARNING: " __VA_ARGS__ )
|
# define WARN(...) warnx ("WARNING: " __VA_ARGS__ )
|
||||||
#define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
||||||
|
|
||||||
#endif // _LIBNFC_MESSAGES_H_
|
#endif // _LIBNFC_MESSAGES_H_
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_TYPES_H__
|
#ifndef __NFC_TYPES_H__
|
||||||
#define __NFC_TYPES_H__
|
# define __NFC_TYPES_H__
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file types.h
|
* @file types.h
|
||||||
|
@ -30,45 +30,45 @@
|
||||||
*
|
*
|
||||||
* Define libnfc specific types: typedef, enum, struct, etc.
|
* Define libnfc specific types: typedef, enum, struct, etc.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
# include <stddef.h>
|
||||||
#include <stdint.h>
|
# include <stdint.h>
|
||||||
#include <stdbool.h>
|
# include <stdbool.h>
|
||||||
#include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
||||||
typedef uint8_t byte_t;
|
typedef uint8_t byte_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NC_PN531 = 0x10,
|
NC_PN531 = 0x10,
|
||||||
NC_PN532 = 0x20,
|
NC_PN532 = 0x20,
|
||||||
NC_PN533 = 0x30,
|
NC_PN533 = 0x30,
|
||||||
} nfc_chip_t;
|
} nfc_chip_t;
|
||||||
|
|
||||||
struct driver_callbacks; // Prototype the callback struct
|
struct driver_callbacks; // Prototype the callback struct
|
||||||
|
|
||||||
typedef void* nfc_device_spec_t; // Device connection specification
|
typedef void *nfc_device_spec_t; // Device connection specification
|
||||||
|
|
||||||
#define DEVICE_NAME_LENGTH 256
|
# define DEVICE_NAME_LENGTH 256
|
||||||
/**
|
/**
|
||||||
* @struct nfc_device_t
|
* @struct nfc_device_t
|
||||||
* @brief NFC device information
|
* @brief NFC device information
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** Callback functions for handling device specific wrapping */
|
/** Callback functions for handling device specific wrapping */
|
||||||
const struct driver_callbacks* pdc;
|
const struct driver_callbacks *pdc;
|
||||||
/** Device name string, including device wrapper firmware */
|
/** Device name string, including device wrapper firmware */
|
||||||
char acName[DEVICE_NAME_LENGTH];
|
char acName[DEVICE_NAME_LENGTH];
|
||||||
/** PN53X chip type, this is useful for some "bug" work-arounds */
|
/** PN53X chip type, this is useful for some "bug" work-arounds */
|
||||||
nfc_chip_t nc;
|
nfc_chip_t nc;
|
||||||
/** Pointer to the device connection specification */
|
/** Pointer to the device connection specification */
|
||||||
nfc_device_spec_t nds;
|
nfc_device_spec_t nds;
|
||||||
/** This represents if the PN53X device was initialized succesful */
|
/** This represents if the PN53X device was initialized succesful */
|
||||||
bool bActive;
|
bool bActive;
|
||||||
/** Is the crc automaticly added, checked and removed from the frames */
|
/** Is the crc automaticly added, checked and removed from the frames */
|
||||||
bool bCrc;
|
bool bCrc;
|
||||||
/** Does the PN53x chip handles parity bits, all parities are handled as data */
|
/** Does the PN53x chip handles parity bits, all parities are handled as data */
|
||||||
bool bPar;
|
bool bPar;
|
||||||
/** Should the PN53x chip handle frames encapsulation and chaining */
|
/** Should the PN53x chip handle frames encapsulation and chaining */
|
||||||
bool bEasyFraming;
|
bool bEasyFraming;
|
||||||
/** The last tx bits setting, we need to reset this if it does not apply anymore */
|
/** The last tx bits setting, we need to reset this if it does not apply anymore */
|
||||||
uint8_t ui8TxBits;
|
uint8_t ui8TxBits;
|
||||||
/** Last error reported by the PCD / encountered by the PCD driver
|
/** Last error reported by the PCD / encountered by the PCD driver
|
||||||
|
@ -79,7 +79,7 @@ typedef struct {
|
||||||
* |+---------- Driver-level specific error
|
* |+---------- Driver-level specific error
|
||||||
* +----------- Driver-level general error (common to all drivers)
|
* +----------- Driver-level general error (common to all drivers)
|
||||||
*/
|
*/
|
||||||
int iLastError;
|
int iLastError;
|
||||||
} nfc_device_t;
|
} nfc_device_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,11 +91,11 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** Device name (e.g. "ACS ACR 38U-CCID 00 00") */
|
/** Device name (e.g. "ACS ACR 38U-CCID 00 00") */
|
||||||
char acDevice[DEVICE_NAME_LENGTH];
|
char acDevice[DEVICE_NAME_LENGTH];
|
||||||
/** Driver name (e.g. "PN532_UART")*/
|
/** Driver name (e.g. "PN532_UART")*/
|
||||||
char* pcDriver;
|
char *pcDriver;
|
||||||
/** Port (e.g. "/dev/ttyUSB0") */
|
/** Port (e.g. "/dev/ttyUSB0") */
|
||||||
char* pcPort;
|
char *pcPort;
|
||||||
/** Port speed (e.g. "115200") */
|
/** Port speed (e.g. "115200") */
|
||||||
uint32_t uiSpeed;
|
uint32_t uiSpeed;
|
||||||
/** Device index for backward compatibility (used to choose one specific device in USB or PSCS devices list) */
|
/** Device index for backward compatibility (used to choose one specific device in USB or PSCS devices list) */
|
||||||
|
@ -108,7 +108,7 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
struct chip_callbacks {
|
struct chip_callbacks {
|
||||||
/** Error lookup */
|
/** Error lookup */
|
||||||
const char* (*strerror) (const nfc_device_t *pnd);
|
const char *(*strerror) (const nfc_device_t * pnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,23 +117,27 @@ struct chip_callbacks {
|
||||||
*/
|
*/
|
||||||
struct driver_callbacks {
|
struct driver_callbacks {
|
||||||
/** Driver name */
|
/** Driver name */
|
||||||
const char* acDriver;
|
const char *acDriver;
|
||||||
/** Chip specific callback functions */
|
/** Chip specific callback functions */
|
||||||
const struct chip_callbacks *pcc;
|
const struct chip_callbacks *pcc;
|
||||||
/** Pick devices callback */
|
/** Pick devices callback */
|
||||||
nfc_device_desc_t *(*pick_device)(void);
|
nfc_device_desc_t *(*pick_device) (void);
|
||||||
/** List devices callback */
|
/** List devices callback */
|
||||||
bool (*list_devices)(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool (*list_devices) (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
/** Connect callback */
|
/** Connect callback */
|
||||||
nfc_device_t* (*connect)(const nfc_device_desc_t* pndd);
|
nfc_device_t *(*connect) (const nfc_device_desc_t * pndd);
|
||||||
/** Transceive callback */
|
/** Transceive callback */
|
||||||
bool (*transceive)(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
|
||||||
|
|
||||||
|
|
||||||
|
bool (*transceive) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen);
|
||||||
/** Disconnect callback */
|
/** Disconnect callback */
|
||||||
void (*disconnect)(nfc_device_t* pnd);
|
void (*disconnect) (nfc_device_t * pnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
#pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum nfc_device_option_t
|
* @enum nfc_device_option_t
|
||||||
|
@ -141,23 +145,23 @@ struct driver_callbacks {
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** Let the PN53X chip handle the CRC bytes. This means that the chip appends the CRC bytes to the frames that are transmitted. It will parse the last bytes from received frames as incoming CRC bytes. They will be verified against the used modulation and protocol. If an frame is expected with incorrect CRC bytes this option should be disabled. Example frames where this is useful are the ATQA and UID+BCC that are transmitted without CRC bytes during the anti-collision phase of the ISO14443-A protocol. */
|
/** Let the PN53X chip handle the CRC bytes. This means that the chip appends the CRC bytes to the frames that are transmitted. It will parse the last bytes from received frames as incoming CRC bytes. They will be verified against the used modulation and protocol. If an frame is expected with incorrect CRC bytes this option should be disabled. Example frames where this is useful are the ATQA and UID+BCC that are transmitted without CRC bytes during the anti-collision phase of the ISO14443-A protocol. */
|
||||||
NDO_HANDLE_CRC = 0x00,
|
NDO_HANDLE_CRC = 0x00,
|
||||||
/** Parity bits in the network layer of ISO14443-A are by default generated and validated in the PN53X chip. This is a very convenient feature. On certain times though it is useful to get full control of the transmitted data. The proprietary MIFARE Classic protocol uses for example custom (encrypted) parity bits. For interoperability it is required to be completely compatible, including the arbitrary parity bits. When this option is disabled, the functions to communicating bits should be used. */
|
/** Parity bits in the network layer of ISO14443-A are by default generated and validated in the PN53X chip. This is a very convenient feature. On certain times though it is useful to get full control of the transmitted data. The proprietary MIFARE Classic protocol uses for example custom (encrypted) parity bits. For interoperability it is required to be completely compatible, including the arbitrary parity bits. When this option is disabled, the functions to communicating bits should be used. */
|
||||||
NDO_HANDLE_PARITY = 0x01,
|
NDO_HANDLE_PARITY = 0x01,
|
||||||
/** This option can be used to enable or disable the electronic field of the NFC device. */
|
/** This option can be used to enable or disable the electronic field of the NFC device. */
|
||||||
NDO_ACTIVATE_FIELD = 0x10,
|
NDO_ACTIVATE_FIELD = 0x10,
|
||||||
/** The internal CRYPTO1 co-processor can be used to transmit messages encrypted. This option is automatically activated after a successful MIFARE Classic authentication. */
|
/** The internal CRYPTO1 co-processor can be used to transmit messages encrypted. This option is automatically activated after a successful MIFARE Classic authentication. */
|
||||||
NDO_ACTIVATE_CRYPTO1 = 0x11,
|
NDO_ACTIVATE_CRYPTO1 = 0x11,
|
||||||
/** The default configuration defines that the PN53X chip will try indefinitely to invite a tag in the field to respond. This could be desired when it is certain a tag will enter the field. On the other hand, when this is uncertain, it will block the application. This option could best be compared to the (NON)BLOCKING option used by (socket)network programming. */
|
/** The default configuration defines that the PN53X chip will try indefinitely to invite a tag in the field to respond. This could be desired when it is certain a tag will enter the field. On the other hand, when this is uncertain, it will block the application. This option could best be compared to the (NON)BLOCKING option used by (socket)network programming. */
|
||||||
NDO_INFINITE_SELECT = 0x20,
|
NDO_INFINITE_SELECT = 0x20,
|
||||||
/** If this option is enabled, frames that carry less than 4 bits are allowed. According to the standards these frames should normally be handles as invalid frames. */
|
/** If this option is enabled, frames that carry less than 4 bits are allowed. According to the standards these frames should normally be handles as invalid frames. */
|
||||||
NDO_ACCEPT_INVALID_FRAMES = 0x30,
|
NDO_ACCEPT_INVALID_FRAMES = 0x30,
|
||||||
/** If the NFC device should only listen to frames, it could be useful to let it gather multiple frames in a sequence. They will be stored in the internal FIFO of the PN53X chip. This could be retrieved by using the receive data functions. Note that if the chip runs out of bytes (FIFO = 64 bytes long), it will overwrite the first received frames, so quick retrieving of the received data is desirable. */
|
/** If the NFC device should only listen to frames, it could be useful to let it gather multiple frames in a sequence. They will be stored in the internal FIFO of the PN53X chip. This could be retrieved by using the receive data functions. Note that if the chip runs out of bytes (FIFO = 64 bytes long), it will overwrite the first received frames, so quick retrieving of the received data is desirable. */
|
||||||
NDO_ACCEPT_MULTIPLE_FRAMES = 0x31,
|
NDO_ACCEPT_MULTIPLE_FRAMES = 0x31,
|
||||||
/** This option can be used to enable or disable the auto-switching mode to ISO14443-4 is device is compliant */
|
/** This option can be used to enable or disable the auto-switching mode to ISO14443-4 is device is compliant */
|
||||||
NDO_AUTO_ISO14443_4 = 0x40,
|
NDO_AUTO_ISO14443_4 = 0x40,
|
||||||
/** Use automatic frames encapsulation and chaining. */
|
/** Use automatic frames encapsulation and chaining. */
|
||||||
NDO_EASY_FRAMING = 0x41,
|
NDO_EASY_FRAMING = 0x41,
|
||||||
} nfc_device_option_t;
|
} nfc_device_option_t;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -169,15 +173,15 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** ISO14443-A (NXP MIFARE) http://en.wikipedia.org/wiki/MIFARE */
|
/** ISO14443-A (NXP MIFARE) http://en.wikipedia.org/wiki/MIFARE */
|
||||||
NM_ISO14443A_106 = 0x00,
|
NM_ISO14443A_106 = 0x00,
|
||||||
/** JIS X 6319-4 (Sony Felica) http://en.wikipedia.org/wiki/FeliCa */
|
/** JIS X 6319-4 (Sony Felica) http://en.wikipedia.org/wiki/FeliCa */
|
||||||
NM_FELICA_212 = 0x01,
|
NM_FELICA_212 = 0x01,
|
||||||
/** JIS X 6319-4 (Sony Felica) http://en.wikipedia.org/wiki/FeliCa */
|
/** JIS X 6319-4 (Sony Felica) http://en.wikipedia.org/wiki/FeliCa */
|
||||||
NM_FELICA_424 = 0x02,
|
NM_FELICA_424 = 0x02,
|
||||||
/** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 */
|
/** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 */
|
||||||
NM_ISO14443B_106 = 0x03,
|
NM_ISO14443B_106 = 0x03,
|
||||||
/** Jewel Topaz (Innovision Research & Development) */
|
/** Jewel Topaz (Innovision Research & Development) */
|
||||||
NM_JEWEL_106 = 0x04,
|
NM_JEWEL_106 = 0x04,
|
||||||
/** Active DEP */
|
/** Active DEP */
|
||||||
NM_ACTIVE_DEP = 0x05,
|
NM_ACTIVE_DEP = 0x05,
|
||||||
/** Passive DEP */
|
/** Passive DEP */
|
||||||
|
@ -189,10 +193,10 @@ typedef enum {
|
||||||
* @brief NFC tag information in Data Exchange Protocol
|
* @brief NFC tag information in Data Exchange Protocol
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t NFCID3i[10];
|
byte_t NFCID3i[10];
|
||||||
byte_t btDID;
|
byte_t btDID;
|
||||||
byte_t btBSt;
|
byte_t btBSt;
|
||||||
byte_t btBRt;
|
byte_t btBRt;
|
||||||
} nfc_dep_info_t;
|
} nfc_dep_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -200,12 +204,12 @@ typedef struct {
|
||||||
* @brief NFC ISO14443A tag (MIFARE) information
|
* @brief NFC ISO14443A tag (MIFARE) information
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtAtqa[2];
|
byte_t abtAtqa[2];
|
||||||
byte_t btSak;
|
byte_t btSak;
|
||||||
size_t szUidLen;
|
size_t szUidLen;
|
||||||
byte_t abtUid[10];
|
byte_t abtUid[10];
|
||||||
size_t szAtsLen;
|
size_t szAtsLen;
|
||||||
byte_t abtAts[36];
|
byte_t abtAts[36];
|
||||||
} nfc_iso14443a_info_t;
|
} nfc_iso14443a_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,11 +217,11 @@ typedef struct {
|
||||||
* @brief NFC FeLiCa tag information
|
* @brief NFC FeLiCa tag information
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t szLen;
|
size_t szLen;
|
||||||
byte_t btResCode;
|
byte_t btResCode;
|
||||||
byte_t abtId[8];
|
byte_t abtId[8];
|
||||||
byte_t abtPad[8];
|
byte_t abtPad[8];
|
||||||
byte_t abtSysCode[2];
|
byte_t abtSysCode[2];
|
||||||
} nfc_felica_info_t;
|
} nfc_felica_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,15 +229,15 @@ typedef struct {
|
||||||
* @brief NFC ISO14443B tag information
|
* @brief NFC ISO14443B tag information
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtAtqb[12];
|
byte_t abtAtqb[12];
|
||||||
byte_t abtId[4];
|
byte_t abtId[4];
|
||||||
byte_t btParam1;
|
byte_t btParam1;
|
||||||
byte_t btParam2;
|
byte_t btParam2;
|
||||||
byte_t btParam3;
|
byte_t btParam3;
|
||||||
byte_t btParam4;
|
byte_t btParam4;
|
||||||
byte_t btCid;
|
byte_t btCid;
|
||||||
size_t szInfLen;
|
size_t szInfLen;
|
||||||
byte_t abtInf[64];
|
byte_t abtInf[64];
|
||||||
} nfc_iso14443b_info_t;
|
} nfc_iso14443b_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,8 +245,8 @@ typedef struct {
|
||||||
* @brief NFC Jewel tag information
|
* @brief NFC Jewel tag information
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t btSensRes[2];
|
byte_t btSensRes[2];
|
||||||
byte_t btId[4];
|
byte_t btId[4];
|
||||||
} nfc_jewel_info_t;
|
} nfc_jewel_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,6 +310,6 @@ typedef struct {
|
||||||
} nfc_target_t;
|
} nfc_target_t;
|
||||||
|
|
||||||
// Reset struct alignment to default
|
// Reset struct alignment to default
|
||||||
#pragma pack()
|
# pragma pack()
|
||||||
|
|
||||||
#endif // _LIBNFC_TYPES_H_
|
#endif // _LIBNFC_TYPES_H_
|
||||||
|
|
|
@ -25,79 +25,96 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBNFC_H_
|
#ifndef _LIBNFC_H_
|
||||||
#define _LIBNFC_H_
|
# define _LIBNFC_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
# include <stdint.h>
|
||||||
#include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
# ifdef _WIN32
|
||||||
/* Windows platform */
|
/* Windows platform */
|
||||||
#ifndef _WINDLL
|
# ifndef _WINDLL
|
||||||
/* CMake compilation */
|
/* CMake compilation */
|
||||||
#ifdef nfc_EXPORTS
|
# ifdef nfc_EXPORTS
|
||||||
#define NFC_EXPORT __declspec(dllexport)
|
# define NFC_EXPORT __declspec(dllexport)
|
||||||
#else /* nfc_EXPORTS */
|
# else
|
||||||
#define NFC_EXPORT __declspec(dllimport)
|
/* nfc_EXPORTS */
|
||||||
#endif /* nfc_EXPORTS */
|
# define NFC_EXPORT __declspec(dllimport)
|
||||||
#else /* _WINDLL */
|
# endif
|
||||||
|
/* nfc_EXPORTS */
|
||||||
|
# else
|
||||||
|
/* _WINDLL */
|
||||||
/* Manual makefile */
|
/* Manual makefile */
|
||||||
#define NFC_EXPORT
|
# define NFC_EXPORT
|
||||||
#endif /* _WINDLL */
|
# endif
|
||||||
#else /* _WIN32 */
|
/* _WINDLL */
|
||||||
#define NFC_EXPORT
|
# else
|
||||||
#endif /* _WIN32 */
|
/* _WIN32 */
|
||||||
|
# define NFC_EXPORT
|
||||||
|
# endif
|
||||||
|
/* _WIN32 */
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif // __cplusplus
|
# endif // __cplusplus
|
||||||
|
|
||||||
/* NFC Device/Hardware manipulation */
|
/* NFC Device/Hardware manipulation */
|
||||||
NFC_EXPORT void nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
NFC_EXPORT void nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
NFC_EXPORT nfc_device_t* nfc_connect(nfc_device_desc_t* pndd);
|
NFC_EXPORT nfc_device_t *nfc_connect (nfc_device_desc_t * pndd);
|
||||||
NFC_EXPORT void nfc_disconnect(nfc_device_t* pnd);
|
NFC_EXPORT void nfc_disconnect (nfc_device_t * pnd);
|
||||||
NFC_EXPORT bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool bEnable);
|
NFC_EXPORT bool nfc_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
||||||
|
|
||||||
/* NFC initiator: act as "reader" */
|
/* NFC initiator: act as "reader" */
|
||||||
NFC_EXPORT bool nfc_initiator_init(nfc_device_t* pnd);
|
NFC_EXPORT bool nfc_initiator_init (nfc_device_t * pnd);
|
||||||
NFC_EXPORT bool nfc_initiator_select_passive_target(nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti);
|
NFC_EXPORT bool nfc_initiator_select_passive_target (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation,
|
||||||
NFC_EXPORT 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 );
|
const byte_t * pbtInitData, const size_t szInitDataLen,
|
||||||
NFC_EXPORT bool nfc_initiator_poll_targets(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);
|
nfc_target_info_t * pti);
|
||||||
NFC_EXPORT bool nfc_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, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti);
|
NFC_EXPORT bool nfc_initiator_list_passive_targets (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation,
|
||||||
NFC_EXPORT bool nfc_initiator_deselect_target(nfc_device_t* pnd);
|
nfc_target_info_t anti[], const size_t szTargets,
|
||||||
NFC_EXPORT bool nfc_initiator_transceive_bits(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);
|
size_t * pszTargetFound);
|
||||||
NFC_EXPORT bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
NFC_EXPORT bool nfc_initiator_poll_targets (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);
|
||||||
|
NFC_EXPORT bool nfc_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,
|
||||||
|
const byte_t * pbtGbData, const size_t szGbDataLen,
|
||||||
|
nfc_target_info_t * pti);
|
||||||
|
NFC_EXPORT bool nfc_initiator_deselect_target (nfc_device_t * pnd);
|
||||||
|
NFC_EXPORT bool nfc_initiator_transceive_bits (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);
|
||||||
|
NFC_EXPORT bool nfc_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen,
|
||||||
|
byte_t * pbtRx, size_t * pszRxLen);
|
||||||
|
|
||||||
/* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */
|
/* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */
|
||||||
NFC_EXPORT bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits);
|
NFC_EXPORT bool nfc_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits);
|
||||||
NFC_EXPORT bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar);
|
NFC_EXPORT bool nfc_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar);
|
||||||
NFC_EXPORT bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen);
|
NFC_EXPORT bool nfc_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen);
|
||||||
NFC_EXPORT bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar);
|
NFC_EXPORT bool nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,
|
||||||
NFC_EXPORT bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen);
|
const byte_t * pbtTxPar);
|
||||||
|
NFC_EXPORT bool nfc_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen);
|
||||||
|
|
||||||
/* Error reporting */
|
/* Error reporting */
|
||||||
NFC_EXPORT const char *nfc_strerror (const nfc_device_t *pnd);
|
NFC_EXPORT const char *nfc_strerror (const nfc_device_t * pnd);
|
||||||
NFC_EXPORT int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen);
|
NFC_EXPORT int nfc_strerror_r (const nfc_device_t * pnd, char *pcStrErrBuf, size_t szBufLen);
|
||||||
NFC_EXPORT void nfc_perror (const nfc_device_t *pnd, const char *pcString);
|
NFC_EXPORT void nfc_perror (const nfc_device_t * pnd, const char *pcString);
|
||||||
|
|
||||||
/* Special data accessors */
|
/* Special data accessors */
|
||||||
NFC_EXPORT const char* nfc_device_name(nfc_device_t* pnd);
|
NFC_EXPORT const char *nfc_device_name (nfc_device_t * pnd);
|
||||||
|
|
||||||
/* Misc. functions */
|
/* Misc. functions */
|
||||||
NFC_EXPORT void iso14443a_crc(byte_t* pbtData, size_t szLen, byte_t* pbtCrc);
|
NFC_EXPORT void iso14443a_crc (byte_t * pbtData, size_t szLen, byte_t * pbtCrc);
|
||||||
NFC_EXPORT void append_iso14443a_crc(byte_t* pbtData, size_t szLen);
|
NFC_EXPORT void append_iso14443a_crc (byte_t * pbtData, size_t szLen);
|
||||||
NFC_EXPORT const char* nfc_version(void);
|
NFC_EXPORT const char *nfc_version (void);
|
||||||
|
|
||||||
/* Common device-level errors */
|
/* Common device-level errors */
|
||||||
#define DEIO 0x1000 /* Input/output error */
|
# define DEIO 0x1000/* Input/output error */
|
||||||
#define DEINVAL 0x2000 /* Invalid argument */
|
# define DEINVAL 0x2000/* Invalid argument */
|
||||||
#define DETIMEOUT 0x3000 /* Operation timeout */
|
# define DETIMEOUT 0x3000/* Operation timeout */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
# endif // __cplusplus
|
||||||
|
#endif // _LIBNFC_H_
|
||||||
|
|
||||||
#endif // _LIBNFC_H_
|
|
||||||
|
|
||||||
|
|
|
@ -22,4 +22,3 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ http://www.teuniz.net/RS-232/index.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
@ -42,50 +42,47 @@ http://www.teuniz.net/RS-232/index.html
|
||||||
// Test if we are dealing with unix operating systems
|
// Test if we are dealing with unix operating systems
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
#include <sys/select.h>
|
# include <sys/select.h>
|
||||||
#include <termios.h>
|
# include <termios.h>
|
||||||
typedef struct termios term_info;
|
typedef struct termios term_info;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd; // Serial port file descriptor
|
int fd; // Serial port file descriptor
|
||||||
term_info tiOld; // Terminal info before using the port
|
term_info tiOld; // Terminal info before using the port
|
||||||
term_info tiNew; // Terminal info during the transaction
|
term_info tiNew; // Terminal info during the transaction
|
||||||
} serial_port_unix;
|
} serial_port_unix;
|
||||||
|
|
||||||
// timeval struct that define timeout delay for serial port
|
// 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 = 60000 // 60 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
|
||||||
#define CCLAIMED 0x80000000
|
# define CCLAIMED 0x80000000
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName)
|
serial_port
|
||||||
|
uart_open (const char *pcPortName)
|
||||||
{
|
{
|
||||||
serial_port_unix* sp = malloc(sizeof(serial_port_unix));
|
serial_port_unix *sp = malloc (sizeof (serial_port_unix));
|
||||||
|
|
||||||
if (sp == 0) return INVALID_SERIAL_PORT;
|
if (sp == 0)
|
||||||
|
return INVALID_SERIAL_PORT;
|
||||||
|
|
||||||
sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
sp->fd = open (pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
if(sp->fd == -1)
|
if (sp->fd == -1) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tcgetattr(sp->fd,&sp->tiOld) == -1)
|
if (tcgetattr (sp->fd, &sp->tiOld) == -1) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the port is not claimed already
|
// Make sure the port is not claimed already
|
||||||
if (sp->tiOld.c_iflag & CCLAIMED)
|
if (sp->tiOld.c_iflag & CCLAIMED) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return CLAIMED_SERIAL_PORT;
|
return CLAIMED_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the old terminal info struct
|
// Copy the old terminal info struct
|
||||||
sp->tiNew = sp->tiOld;
|
sp->tiNew = sp->tiOld;
|
||||||
|
|
||||||
|
@ -94,103 +91,118 @@ serial_port uart_open(const char* pcPortName)
|
||||||
sp->tiNew.c_oflag = 0;
|
sp->tiNew.c_oflag = 0;
|
||||||
sp->tiNew.c_lflag = 0;
|
sp->tiNew.c_lflag = 0;
|
||||||
|
|
||||||
sp->tiNew.c_cc[VMIN] = 0; // block until n bytes are received
|
sp->tiNew.c_cc[VMIN] = 0; // block until n bytes are received
|
||||||
sp->tiNew.c_cc[VTIME] = 0; // block until a timer expires (n * 100 mSec.)
|
sp->tiNew.c_cc[VTIME] = 0; // block until a timer expires (n * 100 mSec.)
|
||||||
|
|
||||||
if(tcsetattr(sp->fd,TCSANOW,&sp->tiNew) == -1)
|
if (tcsetattr (sp->fd, TCSANOW, &sp->tiNew) == -1) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcflush(sp->fd, TCIFLUSH);
|
tcflush (sp->fd, TCIFLUSH);
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
void
|
||||||
|
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||||
{
|
{
|
||||||
DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
DBG ("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
||||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
const serial_port_unix *spu = (serial_port_unix *) sp;
|
||||||
|
|
||||||
// Portability note: on some systems, B9600 != 9600 so we have to do
|
// Portability note: on some systems, B9600 != 9600 so we have to do
|
||||||
// uint32_t <=> speed_t associations by hand.
|
// uint32_t <=> speed_t associations by hand.
|
||||||
speed_t stPortSpeed = B9600;
|
speed_t stPortSpeed = B9600;
|
||||||
switch(uiPortSpeed) {
|
switch (uiPortSpeed) {
|
||||||
case 9600: stPortSpeed = B9600;
|
case 9600:
|
||||||
|
stPortSpeed = B9600;
|
||||||
break;
|
break;
|
||||||
case 19200: stPortSpeed = B19200;
|
case 19200:
|
||||||
|
stPortSpeed = B19200;
|
||||||
break;
|
break;
|
||||||
case 38400: stPortSpeed = B38400;
|
case 38400:
|
||||||
|
stPortSpeed = B38400;
|
||||||
break;
|
break;
|
||||||
#ifdef B57600
|
# ifdef B57600
|
||||||
case 57600: stPortSpeed = B57600;
|
case 57600:
|
||||||
|
stPortSpeed = B57600;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B115200
|
# ifdef B115200
|
||||||
case 115200: stPortSpeed = B115200;
|
case 115200:
|
||||||
|
stPortSpeed = B115200;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B230400
|
# ifdef B230400
|
||||||
case 230400: stPortSpeed = B230400;
|
case 230400:
|
||||||
|
stPortSpeed = B230400;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B460800
|
# ifdef B460800
|
||||||
case 460800: stPortSpeed = B460800;
|
case 460800:
|
||||||
|
stPortSpeed = B460800;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
default:
|
default:
|
||||||
ERR("Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).", uiPortSpeed);
|
ERR ("Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).",
|
||||||
|
uiPortSpeed);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set port speed (Input and Output)
|
// Set port speed (Input and Output)
|
||||||
cfsetispeed((struct termios*)&(spu->tiNew), stPortSpeed);
|
cfsetispeed ((struct termios *) &(spu->tiNew), stPortSpeed);
|
||||||
cfsetospeed((struct termios*)&(spu->tiNew), stPortSpeed);
|
cfsetospeed ((struct termios *) &(spu->tiNew), stPortSpeed);
|
||||||
if( tcsetattr(spu->fd, TCSADRAIN, &(spu->tiNew)) == -1)
|
if (tcsetattr (spu->fd, TCSADRAIN, &(spu->tiNew)) == -1) {
|
||||||
{
|
ERR ("%s", "Unable to apply new speed settings.");
|
||||||
ERR("%s", "Unable to apply new speed settings.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t uart_get_speed(serial_port sp)
|
uint32_t
|
||||||
|
uart_get_speed (serial_port sp)
|
||||||
{
|
{
|
||||||
uint32_t uiPortSpeed = 0;
|
uint32_t uiPortSpeed = 0;
|
||||||
const serial_port_unix* spu = (serial_port_unix*)sp;
|
const serial_port_unix *spu = (serial_port_unix *) sp;
|
||||||
switch (cfgetispeed(&spu->tiNew))
|
switch (cfgetispeed (&spu->tiNew)) {
|
||||||
{
|
case B9600:
|
||||||
case B9600: uiPortSpeed = 9600;
|
uiPortSpeed = 9600;
|
||||||
break;
|
break;
|
||||||
case B19200: uiPortSpeed = 19200;
|
case B19200:
|
||||||
|
uiPortSpeed = 19200;
|
||||||
break;
|
break;
|
||||||
case B38400: uiPortSpeed = 38400;
|
case B38400:
|
||||||
|
uiPortSpeed = 38400;
|
||||||
break;
|
break;
|
||||||
#ifdef B57600
|
# ifdef B57600
|
||||||
case B57600: uiPortSpeed = 57600;
|
case B57600:
|
||||||
|
uiPortSpeed = 57600;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B115200
|
# ifdef B115200
|
||||||
case B115200: uiPortSpeed = 115200;
|
case B115200:
|
||||||
|
uiPortSpeed = 115200;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B230400
|
# ifdef B230400
|
||||||
case B230400: uiPortSpeed = 230400;
|
case B230400:
|
||||||
|
uiPortSpeed = 230400;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
#ifdef B460800
|
# ifdef B460800
|
||||||
case B460800: uiPortSpeed = 460800;
|
case B460800:
|
||||||
|
uiPortSpeed = 460800;
|
||||||
break;
|
break;
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return uiPortSpeed;
|
return uiPortSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_close(const serial_port sp)
|
void
|
||||||
|
uart_close (const serial_port sp)
|
||||||
{
|
{
|
||||||
if (((serial_port_unix*)sp)->fd >= 0) {
|
if (((serial_port_unix *) sp)->fd >= 0) {
|
||||||
tcsetattr(((serial_port_unix*)sp)->fd,TCSANOW,&((serial_port_unix*)sp)->tiOld);
|
tcsetattr (((serial_port_unix *) sp)->fd, TCSANOW, &((serial_port_unix *) sp)->tiOld);
|
||||||
close(((serial_port_unix*)sp)->fd);
|
close (((serial_port_unix *) sp)->fd);
|
||||||
}
|
}
|
||||||
free(sp);
|
free (sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,11 +211,11 @@ void uart_close(const serial_port sp)
|
||||||
* @return 0 on success, otherwise driver error code
|
* @return 0 on success, otherwise driver error code
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
|
uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
int byteCount;
|
int byteCount;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
// Reset the output count
|
// Reset the output count
|
||||||
|
@ -211,37 +223,34 @@ uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO (&rfds);
|
||||||
FD_SET(((serial_port_unix*)sp)->fd,&rfds);
|
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
||||||
tv = timeout;
|
tv = timeout;
|
||||||
res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &tv);
|
res = select (((serial_port_unix *) sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
|
||||||
// Read error
|
// Read error
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
DBG("%s", "RX error.");
|
DBG ("%s", "RX error.");
|
||||||
return DEIO;
|
return DEIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read time-out
|
// Read time-out
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (*pszRxLen == 0) {
|
if (*pszRxLen == 0) {
|
||||||
// Error, we received no data
|
// Error, we received no data
|
||||||
DBG("%s", "RX time-out, buffer empty.");
|
DBG ("%s", "RX time-out, buffer empty.");
|
||||||
return DETIMEOUT;
|
return DETIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
// We received some data, but nothing more is available
|
// We received some data, but nothing more is available
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the count of the incoming bytes
|
// Retrieve the count of the incoming bytes
|
||||||
res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount);
|
res = ioctl (((serial_port_unix *) sp)->fd, FIONREAD, &byteCount);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return DEIO;
|
return DEIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is something available, read the data
|
// There is something available, read the data
|
||||||
res = read(((serial_port_unix*)sp)->fd,pbtRx+(*pszRxLen),byteCount);
|
res = read (((serial_port_unix *) sp)->fd, pbtRx + (*pszRxLen), byteCount);
|
||||||
|
|
||||||
// Stop if the OS has some troubles reading the data
|
// Stop if the OS has some troubles reading the data
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
@ -261,35 +270,32 @@ uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
|
||||||
* @return 0 on success, otherwise a driver error is returned
|
* @return 0 on success, otherwise a driver error is returned
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen)
|
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTxLen)
|
||||||
{
|
{
|
||||||
int32_t res;
|
int32_t res;
|
||||||
size_t szPos = 0;
|
size_t szPos = 0;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
while (szPos < szTxLen)
|
while (szPos < szTxLen) {
|
||||||
{
|
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO (&rfds);
|
||||||
FD_SET(((serial_port_unix*)sp)->fd,&rfds);
|
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
||||||
tv = timeout;
|
tv = timeout;
|
||||||
res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv);
|
res = select (((serial_port_unix *) sp)->fd + 1, NULL, &rfds, NULL, &tv);
|
||||||
|
|
||||||
// Write error
|
// Write error
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
DBG("%s", "TX error.");
|
DBG ("%s", "TX error.");
|
||||||
return DEIO;
|
return DEIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write time-out
|
// Write time-out
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
DBG("%s", "TX time-out.");
|
DBG ("%s", "TX time-out.");
|
||||||
return DETIMEOUT;
|
return DETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send away the bytes
|
// Send away the bytes
|
||||||
res = write(((serial_port_unix*)sp)->fd,pbtTx+szPos,szTxLen-szPos);
|
res = write (((serial_port_unix *) sp)->fd, pbtTx + szPos, szTxLen - szPos);
|
||||||
|
|
||||||
// Stop if the OS has some troubles sending the data
|
// Stop if the OS has some troubles sending the data
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
@ -305,108 +311,108 @@ uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen)
|
||||||
// The windows serial port implementation
|
// The windows serial port implementation
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
HANDLE hPort; // Serial port handle
|
HANDLE hPort; // Serial port handle
|
||||||
DCB dcb; // Device control settings
|
DCB dcb; // Device control settings
|
||||||
COMMTIMEOUTS ct; // Serial port time-out configuration
|
COMMTIMEOUTS ct; // Serial port time-out configuration
|
||||||
} serial_port_windows;
|
} serial_port_windows;
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName)
|
serial_port
|
||||||
|
uart_open (const char *pcPortName)
|
||||||
{
|
{
|
||||||
char acPortName[255];
|
char acPortName[255];
|
||||||
serial_port_windows* sp = malloc(sizeof(serial_port_windows));
|
serial_port_windows *sp = malloc (sizeof (serial_port_windows));
|
||||||
|
|
||||||
// Copy the input "com?" to "\\.\COM?" format
|
// Copy the input "com?" to "\\.\COM?" format
|
||||||
sprintf(acPortName,"\\\\.\\%s",pcPortName);
|
sprintf (acPortName, "\\\\.\\%s", pcPortName);
|
||||||
_strupr(acPortName);
|
_strupr (acPortName);
|
||||||
|
|
||||||
// Try to open the serial port
|
// Try to open the serial port
|
||||||
sp->hPort = CreateFileA(acPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
|
sp->hPort = CreateFileA (acPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
if (sp->hPort == INVALID_HANDLE_VALUE)
|
if (sp->hPort == INVALID_HANDLE_VALUE) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the device control
|
// Prepare the device control
|
||||||
memset(&sp->dcb, 0, sizeof(DCB));
|
memset (&sp->dcb, 0, sizeof (DCB));
|
||||||
sp->dcb.DCBlength = sizeof(DCB);
|
sp->dcb.DCBlength = sizeof (DCB);
|
||||||
if(!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb))
|
if (!BuildCommDCBA ("baud=9600 data=8 parity=N stop=1", &sp->dcb)) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the active serial port
|
// Update the active serial port
|
||||||
if(!SetCommState(sp->hPort,&sp->dcb))
|
if (!SetCommState (sp->hPort, &sp->dcb)) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp->ct.ReadIntervalTimeout = 0;
|
sp->ct.ReadIntervalTimeout = 0;
|
||||||
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
sp->ct.ReadTotalTimeoutMultiplier = 0;
|
||||||
sp->ct.ReadTotalTimeoutConstant = 30;
|
sp->ct.ReadTotalTimeoutConstant = 30;
|
||||||
sp->ct.WriteTotalTimeoutMultiplier = 0;
|
sp->ct.WriteTotalTimeoutMultiplier = 0;
|
||||||
sp->ct.WriteTotalTimeoutConstant = 30;
|
sp->ct.WriteTotalTimeoutConstant = 30;
|
||||||
|
|
||||||
if(!SetCommTimeouts(sp->hPort,&sp->ct))
|
if (!SetCommTimeouts (sp->hPort, &sp->ct)) {
|
||||||
{
|
uart_close (sp);
|
||||||
uart_close(sp);
|
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
PurgeComm (sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_close(const serial_port sp)
|
void
|
||||||
|
uart_close (const serial_port sp)
|
||||||
{
|
{
|
||||||
if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE) {
|
if (((serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(((serial_port_windows*)sp)->hPort);
|
CloseHandle (((serial_port_windows *) sp)->hPort);
|
||||||
}
|
}
|
||||||
free(sp);
|
free (sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
void
|
||||||
|
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||||
{
|
{
|
||||||
serial_port_windows* spw;
|
serial_port_windows *spw;
|
||||||
|
|
||||||
DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
DBG ("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
||||||
// Set port speed (Input and Output)
|
// Set port speed (Input and Output)
|
||||||
switch(uiPortSpeed) {
|
switch (uiPortSpeed) {
|
||||||
case 9600:
|
case 9600:
|
||||||
case 19200:
|
case 19200:
|
||||||
case 38400:
|
case 38400:
|
||||||
case 57600:
|
case 57600:
|
||||||
case 115200:
|
case 115200:
|
||||||
case 230400:
|
case 230400:
|
||||||
case 460800:
|
case 460800:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
|
ERR
|
||||||
|
("Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.",
|
||||||
|
uiPortSpeed);
|
||||||
};
|
};
|
||||||
|
|
||||||
spw = (serial_port_windows*)sp;
|
spw = (serial_port_windows *) sp;
|
||||||
spw->dcb.BaudRate = uiPortSpeed;
|
spw->dcb.BaudRate = uiPortSpeed;
|
||||||
if (!SetCommState(spw->hPort, &spw->dcb))
|
if (!SetCommState (spw->hPort, &spw->dcb)) {
|
||||||
{
|
ERR ("Unable to apply new speed settings.");
|
||||||
ERR("Unable to apply new speed settings.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t uart_get_speed(const serial_port sp)
|
uint32_t
|
||||||
|
uart_get_speed (const serial_port sp)
|
||||||
{
|
{
|
||||||
const serial_port_windows* spw = (serial_port_windows*)sp;
|
const serial_port_windows *spw = (serial_port_windows *) sp;
|
||||||
if (!GetCommState(spw->hPort, (serial_port)&spw->dcb))
|
if (!GetCommState (spw->hPort, (serial_port) & spw->dcb))
|
||||||
return spw->dcb.BaudRate;
|
return spw->dcb.BaudRate;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
|
int
|
||||||
|
uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
if (!ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,*pszRxLen,(LPDWORD)pszRxLen,NULL)) {
|
if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, *pszRxLen, (LPDWORD) pszRxLen, NULL)) {
|
||||||
return DEIO;
|
return DEIO;
|
||||||
}
|
}
|
||||||
if (!*pszRxLen)
|
if (!*pszRxLen)
|
||||||
|
@ -414,10 +420,11 @@ int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen)
|
int
|
||||||
|
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTxLen)
|
||||||
{
|
{
|
||||||
DWORD dwTxLen = 0;
|
DWORD dwTxLen = 0;
|
||||||
if (!WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL)) {
|
if (!WriteFile (((serial_port_windows *) sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL)) {
|
||||||
return DEIO;
|
return DEIO;
|
||||||
}
|
}
|
||||||
if (!dwTxLen)
|
if (!dwTxLen)
|
||||||
|
|
|
@ -24,68 +24,67 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_BUS_UART_H__
|
#ifndef __NFC_BUS_UART_H__
|
||||||
#define __NFC_BUS_UART_H__
|
# define __NFC_BUS_UART_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
# include <stdio.h>
|
||||||
#include <string.h>
|
# include <string.h>
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
// Handle platform specific includes
|
// Handle platform specific includes
|
||||||
#ifndef _WIN32
|
# ifndef _WIN32
|
||||||
#include <termios.h>
|
# include <termios.h>
|
||||||
#include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
#include <limits.h>
|
# include <limits.h>
|
||||||
#include <sys/time.h>
|
# include <sys/time.h>
|
||||||
|
|
||||||
// unistd.h is needed for usleep() fct.
|
// unistd.h is needed for usleep() fct.
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#define delay_ms( X ) usleep( X * 1000 )
|
# define delay_ms( X ) usleep( X * 1000 )
|
||||||
#else
|
# else
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
|
|
||||||
#define snprintf _snprintf
|
# define snprintf _snprintf
|
||||||
#define strdup _strdup
|
# define strdup _strdup
|
||||||
#define delay_ms( X ) Sleep( X )
|
# define delay_ms( X ) Sleep( X )
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Path to the serial port is OS-dependant.
|
// Path to the serial port is OS-dependant.
|
||||||
// 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 DEFAULT_SERIAL_PORTS { "COM1", "COM2", "COM3", "COM4", NULL }
|
# define DEFAULT_SERIAL_PORTS { "COM1", "COM2", "COM3", "COM4", NULL }
|
||||||
#elif defined(__APPLE__)
|
# elif defined(__APPLE__)
|
||||||
// XXX: find UART connection string for PN53X device on Mac OS X when multiples devices are used
|
// 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 }
|
# 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 DEFAULT_SERIAL_PORTS { "/dev/cuau0", "/dev/cuau1", "/dev/cuau2", "/dev/cuau3", NULL }
|
# define DEFAULT_SERIAL_PORTS { "/dev/cuau0", "/dev/cuau1", "/dev/cuau2", "/dev/cuau3", NULL }
|
||||||
#elif defined (__linux__)
|
# elif defined (__linux__)
|
||||||
#define DEFAULT_SERIAL_PORTS { "/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3", "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3", NULL }
|
# 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
|
||||||
|
|
||||||
// Define shortcut to types to make code more readable
|
// Define shortcut to types to make code more readable
|
||||||
typedef void* serial_port;
|
typedef void *serial_port;
|
||||||
#define INVALID_SERIAL_PORT (void*)(~1)
|
# define INVALID_SERIAL_PORT (void*)(~1)
|
||||||
#define CLAIMED_SERIAL_PORT (void*)(~2)
|
# define CLAIMED_SERIAL_PORT (void*)(~2)
|
||||||
|
|
||||||
serial_port uart_open(const char* pcPortName);
|
serial_port uart_open (const char *pcPortName);
|
||||||
void uart_close(const serial_port sp);
|
void uart_close (const serial_port sp);
|
||||||
|
|
||||||
void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
|
void uart_set_speed (serial_port sp, const uint32_t uiPortSpeed);
|
||||||
uint32_t uart_get_speed(const serial_port sp);
|
uint32_t uart_get_speed (const serial_port sp);
|
||||||
|
|
||||||
int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen);
|
int uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRxLen);
|
||||||
int uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen);
|
int uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTxLen);
|
||||||
|
|
||||||
#endif // __NFC_BUS_UART_H__
|
#endif // __NFC_BUS_UART_H__
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_CHIPS_H__
|
#ifndef __NFC_CHIPS_H__
|
||||||
#define __NFC_CHIPS_H__
|
# define __NFC_CHIPS_H__
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#include "chips/pn53x.h"
|
# include "chips/pn53x.h"
|
||||||
|
|
||||||
#endif // __NFC_CHIPS_H__
|
#endif // __NFC_CHIPS_H__
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,94 +23,111 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_CHIPS_PN53X_H__
|
#ifndef __NFC_CHIPS_PN53X_H__
|
||||||
#define __NFC_CHIPS_PN53X_H__
|
# define __NFC_CHIPS_PN53X_H__
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
# define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
// Registers and symbols masks used to covers parts within a register
|
// Registers and symbols masks used to covers parts within a register
|
||||||
#define REG_CIU_TX_MODE 0x6302
|
# define REG_CIU_TX_MODE 0x6302
|
||||||
#define SYMBOL_TX_CRC_ENABLE 0x80
|
# define SYMBOL_TX_CRC_ENABLE 0x80
|
||||||
#define REG_CIU_RX_MODE 0x6303
|
# define REG_CIU_RX_MODE 0x6303
|
||||||
#define SYMBOL_RX_CRC_ENABLE 0x80
|
# define SYMBOL_RX_CRC_ENABLE 0x80
|
||||||
#define SYMBOL_RX_NO_ERROR 0x08
|
# define SYMBOL_RX_NO_ERROR 0x08
|
||||||
#define SYMBOL_RX_MULTIPLE 0x04
|
# define SYMBOL_RX_MULTIPLE 0x04
|
||||||
#define REG_CIU_TX_AUTO 0x6305
|
# define REG_CIU_TX_AUTO 0x6305
|
||||||
#define SYMBOL_FORCE_100_ASK 0x40
|
# define SYMBOL_FORCE_100_ASK 0x40
|
||||||
#define SYMBOL_AUTO_WAKE_UP 0x20
|
# define SYMBOL_AUTO_WAKE_UP 0x20
|
||||||
#define SYMBOL_INITIAL_RF_ON 0x04
|
# define SYMBOL_INITIAL_RF_ON 0x04
|
||||||
#define REG_CIU_MANUAL_RCV 0x630D
|
# define REG_CIU_MANUAL_RCV 0x630D
|
||||||
#define SYMBOL_PARITY_DISABLE 0x10
|
# define SYMBOL_PARITY_DISABLE 0x10
|
||||||
#define REG_CIU_STATUS2 0x6338
|
# define REG_CIU_STATUS2 0x6338
|
||||||
#define SYMBOL_MF_CRYPTO1_ON 0x08
|
# define SYMBOL_MF_CRYPTO1_ON 0x08
|
||||||
#define REG_CIU_CONTROL 0x633C
|
# define REG_CIU_CONTROL 0x633C
|
||||||
#define SYMBOL_INITIATOR 0x10
|
# define SYMBOL_INITIATOR 0x10
|
||||||
#define SYMBOL_RX_LAST_BITS 0x07
|
# define SYMBOL_RX_LAST_BITS 0x07
|
||||||
#define REG_CIU_BIT_FRAMING 0x633D
|
# define REG_CIU_BIT_FRAMING 0x633D
|
||||||
#define SYMBOL_TX_LAST_BITS 0x07
|
# define SYMBOL_TX_LAST_BITS 0x07
|
||||||
|
|
||||||
#define SYMBOL_PARAM_fAutomaticRATS 0x10
|
# define SYMBOL_PARAM_fAutomaticRATS 0x10
|
||||||
#define SYMBOL_PARAM_fAutomaticATR_RES 0x04
|
# define SYMBOL_PARAM_fAutomaticATR_RES 0x04
|
||||||
|
|
||||||
// Internal parameters flags
|
// Internal parameters flags
|
||||||
#define PARAM_NONE 0x00
|
# define PARAM_NONE 0x00
|
||||||
#define PARAM_NAD_USED 0x01
|
# define PARAM_NAD_USED 0x01
|
||||||
#define PARAM_DID_USED 0x02
|
# define PARAM_DID_USED 0x02
|
||||||
#define PARAM_AUTO_ATR_RES 0x04
|
# define PARAM_AUTO_ATR_RES 0x04
|
||||||
#define PARAM_AUTO_RATS 0x10
|
# define PARAM_AUTO_RATS 0x10
|
||||||
#define PARAM_14443_4_PICC 0x20
|
# define PARAM_14443_4_PICC 0x20
|
||||||
#define PARAM_NO_AMBLE 0x40
|
# define PARAM_NO_AMBLE 0x40
|
||||||
|
|
||||||
// Radio Field Configure Items // Configuration Data length
|
// Radio Field Configure Items // Configuration Data length
|
||||||
#define RFCI_FIELD 0x01 // 1
|
# define RFCI_FIELD 0x01 // 1
|
||||||
#define RFCI_TIMING 0x02 // 3
|
# define RFCI_TIMING 0x02 // 3
|
||||||
#define RFCI_RETRY_DATA 0x04 // 1
|
# define RFCI_RETRY_DATA 0x04 // 1
|
||||||
#define RFCI_RETRY_SELECT 0x05 // 3
|
# define RFCI_RETRY_SELECT 0x05 // 3
|
||||||
#define RFCI_ANALOG_TYPE_A_106 0x0A // 11
|
# define RFCI_ANALOG_TYPE_A_106 0x0A // 11
|
||||||
#define RFCI_ANALOG_TYPE_A_212_424 0x0B // 8
|
# define RFCI_ANALOG_TYPE_A_212_424 0x0B // 8
|
||||||
#define RFCI_ANALOG_TYPE_B 0x0C // 3
|
# define RFCI_ANALOG_TYPE_B 0x0C // 3
|
||||||
#define RFCI_ANALOG_TYPE_14443_4 0x0D // 9
|
# define RFCI_ANALOG_TYPE_14443_4 0x0D // 9
|
||||||
|
|
||||||
/* PN53x specific device-level errors */
|
/* PN53x specific device-level errors */
|
||||||
#define DENACK 0x0100 /* NACK */
|
# define DENACK 0x0100/* NACK */
|
||||||
#define DEACKMISMATCH 0x0200 /* Unexpected data */
|
# define DEACKMISMATCH 0x0200/* Unexpected data */
|
||||||
#define DEISERRFRAME 0x0300 /* Error frame */
|
# define DEISERRFRAME 0x0300/* Error frame */
|
||||||
#define DENOTSUP 0x0400 /* Not supported */
|
# define DENOTSUP 0x0400/* Not supported */
|
||||||
|
|
||||||
bool pn53x_transceive_check_ack_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen);
|
bool pn53x_transceive_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
|
||||||
bool pn53x_transceive_check_error_frame_callback(nfc_device_t* pnd, const byte_t *pbtRxFrame, const size_t szRxFrameLen);
|
const size_t szRxFrameLen);
|
||||||
bool pn53x_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
bool pn53x_transceive_check_error_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
|
||||||
bool pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t* ui8Value);
|
const size_t szRxFrameLen);
|
||||||
bool pn53x_set_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value);
|
bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
bool pn53x_set_parameters(nfc_device_t* pnd, uint8_t ui8Value);
|
size_t * pszRxLen);
|
||||||
bool pn53x_set_tx_bits(nfc_device_t* pnd, uint8_t ui8Bits);
|
bool pn53x_get_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value);
|
||||||
bool pn53x_wrap_frame(const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtFrame, size_t* pszFrameBits);
|
bool pn53x_set_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value);
|
||||||
bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar);
|
bool pn53x_set_parameters (nfc_device_t * pnd, uint8_t ui8Value);
|
||||||
bool pn53x_decode_target_data(const byte_t* pbtRawData, size_t szDataLen, nfc_chip_t nc, nfc_target_type_t ntt, nfc_target_info_t* pnti);
|
bool pn53x_set_tx_bits (nfc_device_t * pnd, uint8_t ui8Bits);
|
||||||
|
bool pn53x_wrap_frame (const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar, byte_t * pbtFrame,
|
||||||
|
size_t * pszFrameBits);
|
||||||
|
bool pn53x_unwrap_frame (const byte_t * pbtFrame, const size_t szFrameBits, byte_t * pbtRx, size_t * pszRxBits,
|
||||||
|
byte_t * pbtRxPar);
|
||||||
|
bool pn53x_decode_target_data (const byte_t * pbtRawData, size_t szDataLen, nfc_chip_t nc, nfc_target_type_t ntt,
|
||||||
|
nfc_target_info_t * pnti);
|
||||||
|
|
||||||
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,
|
||||||
bool pn53x_InDeselect(nfc_device_t* pnd, const uint8_t ui8Target);
|
const byte_t szMaxTargets, const byte_t * pbtInitiatorData,
|
||||||
bool pn53x_InRelease(nfc_device_t* pnd, const uint8_t ui8Target);
|
const size_t szInitiatorDataLen, byte_t * pbtTargetsData, size_t * pszTargetsData);
|
||||||
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_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);
|
||||||
|
|
||||||
bool pn53x_get_firmware_version (nfc_device_t *pnd);
|
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);
|
bool pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
||||||
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, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pnti);
|
bool pn53x_initiator_select_dep_target (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation,
|
||||||
bool pn53x_initiator_transceive_bits(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);
|
const byte_t * pbtPidData, const size_t szPidDataLen,
|
||||||
bool pn53x_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
const byte_t * pbtNFCID3i, const size_t szNFCID3iDataLen,
|
||||||
|
const byte_t * pbtGbData, const size_t szGbDataLen,
|
||||||
|
nfc_target_info_t * pnti);
|
||||||
|
bool pn53x_initiator_transceive_bits (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);
|
||||||
|
bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen,
|
||||||
|
byte_t * pbtRx, size_t * pszRxLen);
|
||||||
|
|
||||||
bool pn53x_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits);
|
bool pn53x_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits);
|
||||||
bool pn53x_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar);
|
bool pn53x_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar);
|
||||||
bool pn53x_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen);
|
bool pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen);
|
||||||
bool pn53x_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar);
|
bool pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,
|
||||||
bool pn53x_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen);
|
const byte_t * pbtTxPar);
|
||||||
|
bool pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen);
|
||||||
|
|
||||||
const char *pn53x_strerror (const nfc_device_t *pnd);
|
const char *pn53x_strerror (const nfc_device_t * pnd);
|
||||||
|
|
||||||
static const struct chip_callbacks pn53x_callbacks_list = {
|
static const struct chip_callbacks pn53x_callbacks_list = {
|
||||||
pn53x_strerror
|
pn53x_strerror
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __NFC_CHIPS_PN53X_H__
|
#endif // __NFC_CHIPS_PN53X_H__
|
||||||
|
|
||||||
|
|
|
@ -23,65 +23,81 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVERS_H__
|
#ifndef __NFC_DRIVERS_H__
|
||||||
#define __NFC_DRIVERS_H__
|
# define __NFC_DRIVERS_H__
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#include "chips/pn53x.h"
|
# include "chips/pn53x.h"
|
||||||
|
|
||||||
#if defined (DRIVER_ACR122_ENABLED)
|
# if defined (DRIVER_ACR122_ENABLED)
|
||||||
#include "drivers/acr122.h"
|
# include "drivers/acr122.h"
|
||||||
#endif /* DRIVER_ACR122_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_ACR122_ENABLED */
|
||||||
|
|
||||||
#if defined (DRIVER_PN531_USB_ENABLED) || defined (DRIVER_PN533_USB_ENABLED)
|
# if defined (DRIVER_PN531_USB_ENABLED) || defined (DRIVER_PN533_USB_ENABLED)
|
||||||
#include "drivers/pn53x_usb.h"
|
# include "drivers/pn53x_usb.h"
|
||||||
#endif /* DRIVER_PN531_USB_ENABLED || DRIVER_PN533_USB_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_PN531_USB_ENABLED || DRIVER_PN533_USB_ENABLED */
|
||||||
|
|
||||||
#if defined (DRIVER_PN531_USB_ENABLED)
|
# if defined (DRIVER_PN531_USB_ENABLED)
|
||||||
#include "drivers/pn531_usb.h"
|
# include "drivers/pn531_usb.h"
|
||||||
#endif /* DRIVER_PN531_USB_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_PN531_USB_ENABLED */
|
||||||
|
|
||||||
#if defined (DRIVER_PN533_USB_ENABLED)
|
# if defined (DRIVER_PN533_USB_ENABLED)
|
||||||
#include "drivers/pn533_usb.h"
|
# include "drivers/pn533_usb.h"
|
||||||
#endif /* DRIVER_PN533_USB_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_PN533_USB_ENABLED */
|
||||||
|
|
||||||
#if defined (DRIVER_ARYGON_ENABLED)
|
# if defined (DRIVER_ARYGON_ENABLED)
|
||||||
#include "drivers/arygon.h"
|
# include "drivers/arygon.h"
|
||||||
#endif /* DRIVER_ARYGON_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_ARYGON_ENABLED */
|
||||||
|
|
||||||
#if defined (DRIVER_PN532_UART_ENABLED)
|
# if defined (DRIVER_PN532_UART_ENABLED)
|
||||||
#include "drivers/pn532_uart.h"
|
# include "drivers/pn532_uart.h"
|
||||||
#endif /* DRIVER_PN532_UART_ENABLED */
|
# endif
|
||||||
|
/* DRIVER_PN532_UART_ENABLED */
|
||||||
|
|
||||||
#define DRIVERS_MAX_DEVICES 16
|
# define DRIVERS_MAX_DEVICES 16
|
||||||
#define MAX_FRAME_LEN 264
|
# define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
static const struct driver_callbacks drivers_callbacks_list[] = {
|
static const struct driver_callbacks drivers_callbacks_list[] = {
|
||||||
// Driver Name Chip callbacks Pick Device List Devices Connect Transceive Disconnect
|
// Driver Name Chip callbacks Pick Device List Devices Connect Transceive Disconnect
|
||||||
#if defined (DRIVER_ACR122_ENABLED)
|
# if defined (DRIVER_ACR122_ENABLED)
|
||||||
{ ACR122_DRIVER_NAME, &pn53x_callbacks_list, acr122_pick_device, acr122_list_devices, acr122_connect, acr122_transceive, acr122_disconnect },
|
{ACR122_DRIVER_NAME, &pn53x_callbacks_list, acr122_pick_device, acr122_list_devices, acr122_connect,
|
||||||
#endif /* DRIVER_ACR122_ENABLED */
|
acr122_transceive, acr122_disconnect},
|
||||||
#if defined (DRIVER_PN531_USB_ENABLED)
|
# endif
|
||||||
{ PN531_USB_DRIVER_NAME, &pn53x_callbacks_list, pn531_usb_pick_device, pn531_usb_list_devices, pn531_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect },
|
/* DRIVER_ACR122_ENABLED */
|
||||||
#endif /* DRIVER_PN531_USB_ENABLED */
|
# if defined (DRIVER_PN531_USB_ENABLED)
|
||||||
#if defined (DRIVER_PN533_USB_ENABLED)
|
{PN531_USB_DRIVER_NAME, &pn53x_callbacks_list, pn531_usb_pick_device, pn531_usb_list_devices, pn531_usb_connect,
|
||||||
{ PN533_USB_DRIVER_NAME, &pn53x_callbacks_list, pn533_usb_pick_device, pn533_usb_list_devices, pn533_usb_connect, pn53x_usb_transceive, pn53x_usb_disconnect },
|
pn53x_usb_transceive, pn53x_usb_disconnect},
|
||||||
#endif /* DRIVER_PN533_USB_ENABLED */
|
# endif
|
||||||
#if defined (DRIVER_ARYGON_ENABLED)
|
/* DRIVER_PN531_USB_ENABLED */
|
||||||
{ ARYGON_DRIVER_NAME, &pn53x_callbacks_list, arygon_pick_device, arygon_list_devices, arygon_connect, arygon_transceive, arygon_disconnect },
|
# if defined (DRIVER_PN533_USB_ENABLED)
|
||||||
#endif /* DRIVER_ARYGON_ENABLED */
|
{PN533_USB_DRIVER_NAME, &pn53x_callbacks_list, pn533_usb_pick_device, pn533_usb_list_devices, pn533_usb_connect,
|
||||||
#if defined (DRIVER_PN532_UART_ENABLED)
|
pn53x_usb_transceive, pn53x_usb_disconnect},
|
||||||
{ PN532_UART_DRIVER_NAME, &pn53x_callbacks_list, pn532_uart_pick_device, pn532_uart_list_devices, pn532_uart_connect, pn532_uart_transceive, pn532_uart_disconnect },
|
# endif
|
||||||
#endif /* DRIVER_PN532_UART_ENABLED */
|
/* DRIVER_PN533_USB_ENABLED */
|
||||||
|
# if defined (DRIVER_ARYGON_ENABLED)
|
||||||
|
{ARYGON_DRIVER_NAME, &pn53x_callbacks_list, arygon_pick_device, arygon_list_devices, arygon_connect,
|
||||||
|
arygon_transceive, arygon_disconnect},
|
||||||
|
# endif
|
||||||
|
/* DRIVER_ARYGON_ENABLED */
|
||||||
|
# if defined (DRIVER_PN532_UART_ENABLED)
|
||||||
|
{PN532_UART_DRIVER_NAME, &pn53x_callbacks_list, pn532_uart_pick_device, pn532_uart_list_devices, pn532_uart_connect,
|
||||||
|
pn532_uart_transceive, pn532_uart_disconnect},
|
||||||
|
# endif
|
||||||
|
/* DRIVER_PN532_UART_ENABLED */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
/*
|
/*
|
||||||
* FIXME: Helper macro for dumping drivers messages.
|
* FIXME: Helper macro for dumping drivers messages.
|
||||||
* Here is not the best place for such a macro, however, I
|
* Here is not the best place for such a macro, however, I
|
||||||
* can't see any convenient place ATM.
|
* can't see any convenient place ATM.
|
||||||
*/
|
*/
|
||||||
# define PRINT_HEX(pcTag, pbtData, szBytes) do { \
|
# define PRINT_HEX(pcTag, pbtData, szBytes) do { \
|
||||||
size_t __szPos; \
|
size_t __szPos; \
|
||||||
printf(" %s: ", pcTag); \
|
printf(" %s: ", pcTag); \
|
||||||
for (__szPos=0; __szPos < (size_t)(szBytes); __szPos++) { \
|
for (__szPos=0; __szPos < (size_t)(szBytes); __szPos++) { \
|
||||||
|
@ -89,7 +105,6 @@ static const struct driver_callbacks drivers_callbacks_list[] = {
|
||||||
} \
|
} \
|
||||||
printf("\n"); \
|
printf("\n"); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#endif // __NFC_DRIVERS_H__
|
#endif // __NFC_DRIVERS_H__
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#include <winscard.h>
|
#include <winscard.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <wintypes.h>
|
# include <wintypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
#define SCARD_OPERATION_ERROR 0x63
|
#define SCARD_OPERATION_ERROR 0x63
|
||||||
|
|
||||||
#ifndef SCARD_PROTOCOL_UNDEFINED
|
#ifndef SCARD_PROTOCOL_UNDEFINED
|
||||||
#define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET
|
# define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS)
|
#define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS)
|
||||||
|
@ -74,12 +74,12 @@ typedef struct {
|
||||||
static SCARDCONTEXT _SCardContext;
|
static SCARDCONTEXT _SCardContext;
|
||||||
static int _iSCardContextRefCount = 0;
|
static int _iSCardContextRefCount = 0;
|
||||||
|
|
||||||
SCARDCONTEXT*
|
SCARDCONTEXT *
|
||||||
acr122_get_scardcontext(void)
|
acr122_get_scardcontext (void)
|
||||||
{
|
{
|
||||||
if ( _iSCardContextRefCount == 0 )
|
if (_iSCardContextRefCount == 0) {
|
||||||
{
|
if (SCardEstablishContext (SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS)
|
||||||
if (SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&_SCardContext) != SCARD_S_SUCCESS) return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_iSCardContextRefCount++;
|
_iSCardContextRefCount++;
|
||||||
|
|
||||||
|
@ -87,14 +87,12 @@ acr122_get_scardcontext(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
acr122_free_scardcontext(void)
|
acr122_free_scardcontext (void)
|
||||||
{
|
{
|
||||||
if (_iSCardContextRefCount)
|
if (_iSCardContextRefCount) {
|
||||||
{
|
|
||||||
_iSCardContextRefCount--;
|
_iSCardContextRefCount--;
|
||||||
if (!_iSCardContextRefCount)
|
if (!_iSCardContextRefCount) {
|
||||||
{
|
SCardReleaseContext (_SCardContext);
|
||||||
SCardReleaseContext(_SCardContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,15 +104,15 @@ acr122_pick_device (void)
|
||||||
nfc_device_desc_t *pndd;
|
nfc_device_desc_t *pndd;
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd)))) {
|
if ((pndd = malloc (sizeof (*pndd)))) {
|
||||||
size_t szN;
|
size_t szN;
|
||||||
|
|
||||||
if (!acr122_list_devices (pndd, 1, &szN)) {
|
if (!acr122_list_devices (pndd, 1, &szN)) {
|
||||||
DBG("%s", "acr122_list_devices failed");
|
DBG ("%s", "acr122_list_devices failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szN == 0) {
|
if (szN == 0) {
|
||||||
DBG("%s", "No device found");
|
DBG ("%s", "No device found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,30 +131,29 @@ acr122_pick_device (void)
|
||||||
* @return true if succeeded, false otherwise.
|
* @return true if succeeded, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
acr122_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
size_t szPos = 0;
|
size_t szPos = 0;
|
||||||
char acDeviceNames[256+64*DRIVERS_MAX_DEVICES];
|
char acDeviceNames[256 + 64 * DRIVERS_MAX_DEVICES];
|
||||||
size_t szDeviceNamesLen = sizeof(acDeviceNames);
|
size_t szDeviceNamesLen = sizeof (acDeviceNames);
|
||||||
uint32_t uiBusIndex = 0;
|
uint32_t uiBusIndex = 0;
|
||||||
SCARDCONTEXT *pscc;
|
SCARDCONTEXT *pscc;
|
||||||
bool bSupported;
|
bool bSupported;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Clear the reader list
|
// Clear the reader list
|
||||||
memset(acDeviceNames, '\0', szDeviceNamesLen);
|
memset (acDeviceNames, '\0', szDeviceNamesLen);
|
||||||
|
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
// Test if context succeeded
|
// Test if context succeeded
|
||||||
if (!(pscc = acr122_get_scardcontext ()))
|
if (!(pscc = acr122_get_scardcontext ())) {
|
||||||
{
|
DBG ("%s", "PCSC context not found");
|
||||||
DBG("%s","PCSC context not found");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the string array of all available pcsc readers
|
// Retrieve the string array of all available pcsc readers
|
||||||
if (SCardListReaders(*pscc,NULL,acDeviceNames,(void*)&szDeviceNamesLen) != SCARD_S_SUCCESS) return false;
|
if (SCardListReaders (*pscc, NULL, acDeviceNames, (void *) &szDeviceNamesLen) != SCARD_S_SUCCESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
// DBG("%s", "PCSC reports following device(s):");
|
// DBG("%s", "PCSC reports following device(s):");
|
||||||
|
|
||||||
|
@ -167,22 +164,19 @@ acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
|
||||||
|
|
||||||
bSupported = false;
|
bSupported = false;
|
||||||
for (i = 0; supported_devices[i] && !bSupported; i++) {
|
for (i = 0; supported_devices[i] && !bSupported; i++) {
|
||||||
int l = strlen(supported_devices[i]);
|
int l = strlen (supported_devices[i]);
|
||||||
bSupported = 0 == strncmp(supported_devices[i], acDeviceNames + szPos, l);
|
bSupported = 0 == strncmp (supported_devices[i], acDeviceNames + szPos, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bSupported)
|
if (bSupported) {
|
||||||
{
|
|
||||||
// Supported ACR122 device found
|
// Supported ACR122 device found
|
||||||
strncpy(pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1);
|
strncpy (pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1);
|
||||||
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME;
|
pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME;
|
||||||
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
}
|
} else {
|
||||||
else
|
DBG ("PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos);
|
||||||
{
|
|
||||||
DBG("PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next device name position
|
// Find next device name position
|
||||||
|
@ -190,52 +184,54 @@ acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *p
|
||||||
}
|
}
|
||||||
acr122_free_scardcontext ();
|
acr122_free_scardcontext ();
|
||||||
|
|
||||||
if(*pszDeviceFound)
|
if (*pszDeviceFound)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd)
|
nfc_device_t *
|
||||||
|
acr122_connect (const nfc_device_desc_t * pndd)
|
||||||
{
|
{
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t *pnd = NULL;
|
||||||
acr122_spec_t as;
|
acr122_spec_t as;
|
||||||
acr122_spec_t* pas;
|
acr122_spec_t *pas;
|
||||||
char* pcFirmware;
|
char *pcFirmware;
|
||||||
|
|
||||||
SCARDCONTEXT *pscc;
|
SCARDCONTEXT *pscc;
|
||||||
|
|
||||||
DBG("Attempt to connect to %s",pndd->acDevice);
|
DBG ("Attempt to connect to %s", pndd->acDevice);
|
||||||
// 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
|
||||||
if (SCardConnect(*pscc,pndd->acDevice,SCARD_SHARE_EXCLUSIVE,SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
|
if (SCardConnect
|
||||||
{
|
(*pscc, pndd->acDevice, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(as.hCard),
|
||||||
|
(void *) &(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS) {
|
||||||
// Connect to ACR122 firmware version >2.0
|
// Connect to ACR122 firmware version >2.0
|
||||||
if (SCardConnect(*pscc,pndd->acDevice,SCARD_SHARE_DIRECT,0,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
|
if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_DIRECT, 0, &(as.hCard), (void *) &(as.ioCard.dwProtocol)) !=
|
||||||
{
|
SCARD_S_SUCCESS) {
|
||||||
// We can not connect to this device.
|
// We can not connect to this device.
|
||||||
DBG("%s","PCSC connect failed");
|
DBG ("%s", "PCSC connect failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Configure I/O settings for card communication
|
// Configure I/O settings for card communication
|
||||||
as.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST);
|
as.ioCard.cbPciLength = sizeof (SCARD_IO_REQUEST);
|
||||||
|
|
||||||
// Retrieve the current firmware version
|
// Retrieve the current firmware version
|
||||||
pcFirmware = acr122_firmware((nfc_device_t*)&as);
|
pcFirmware = acr122_firmware ((nfc_device_t *) & as);
|
||||||
if (strstr(pcFirmware,FIRMWARE_TEXT) != NULL)
|
if (strstr (pcFirmware, FIRMWARE_TEXT) != NULL) {
|
||||||
{
|
|
||||||
// Allocate memory and store the device specification
|
// Allocate memory and store the device specification
|
||||||
pas = malloc(sizeof(acr122_spec_t));
|
pas = malloc (sizeof (acr122_spec_t));
|
||||||
*pas = as;
|
*pas = as;
|
||||||
|
|
||||||
// Done, we found the reader we are looking for
|
// Done, we found the reader we are looking for
|
||||||
pnd = malloc(sizeof(nfc_device_t));
|
pnd = malloc (sizeof (nfc_device_t));
|
||||||
strcpy(pnd->acName,pndd->acDevice);
|
strcpy (pnd->acName, pndd->acDevice);
|
||||||
strcpy(pnd->acName + strlen(pnd->acName)," / ");
|
strcpy (pnd->acName + strlen (pnd->acName), " / ");
|
||||||
strcpy(pnd->acName + strlen(pnd->acName),pcFirmware);
|
strcpy (pnd->acName + strlen (pnd->acName), pcFirmware);
|
||||||
pnd->nc = NC_PN532;
|
pnd->nc = NC_PN532;
|
||||||
pnd->nds = (nfc_device_spec_t)pas;
|
pnd->nds = (nfc_device_spec_t) pas;
|
||||||
pnd->bActive = true;
|
pnd->bActive = true;
|
||||||
pnd->bCrc = true;
|
pnd->bCrc = true;
|
||||||
pnd->bPar = true;
|
pnd->bPar = true;
|
||||||
|
@ -246,23 +242,25 @@ nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acr122_disconnect(nfc_device_t* pnd)
|
void
|
||||||
|
acr122_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
acr122_spec_t* pas = (acr122_spec_t*)pnd->nds;
|
acr122_spec_t *pas = (acr122_spec_t *) pnd->nds;
|
||||||
SCardDisconnect(pas->hCard,SCARD_LEAVE_CARD);
|
SCardDisconnect (pas->hCard, SCARD_LEAVE_CARD);
|
||||||
acr122_free_scardcontext ();
|
acr122_free_scardcontext ();
|
||||||
free(pas);
|
free (pas);
|
||||||
free(pnd);
|
free (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acr122_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
acr122_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
byte_t abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 };
|
byte_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 };
|
||||||
size_t szRxCmdLen = sizeof(abtRxCmd);
|
size_t szRxCmdLen = sizeof (abtRxCmd);
|
||||||
byte_t abtRxBuf[ACR122_RESPONSE_LEN];
|
byte_t abtRxBuf[ACR122_RESPONSE_LEN];
|
||||||
size_t szRxBufLen;
|
size_t szRxBufLen;
|
||||||
byte_t abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 };
|
byte_t abtTxBuf[ACR122_WRAP_LEN + ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 };
|
||||||
acr122_spec_t* pas = (acr122_spec_t*)pnd->nds;
|
acr122_spec_t *pas = (acr122_spec_t *) pnd->nds;
|
||||||
|
|
||||||
// FIXME: Should be handled by the library.
|
// FIXME: Should be handled by the library.
|
||||||
// Make sure the command does not overflow the send buffer
|
// Make sure the command does not overflow the send buffer
|
||||||
|
@ -270,111 +268,116 @@ bool acr122_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the length of the command we are going to send
|
// Store the length of the command we are going to send
|
||||||
abtTxBuf[4] = szTxLen;
|
abtTxBuf[4] = szTxLen;
|
||||||
|
|
||||||
// Prepare and transmit the send buffer
|
// Prepare and transmit the send buffer
|
||||||
memcpy(abtTxBuf+5,pbtTx,szTxLen);
|
memcpy (abtTxBuf + 5, pbtTx, szTxLen);
|
||||||
szRxBufLen = sizeof(abtRxBuf);
|
szRxBufLen = sizeof (abtRxBuf);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", abtTxBuf,szTxLen+5);
|
PRINT_HEX ("TX", abtTxBuf, szTxLen + 5);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) {
|
||||||
{
|
if (SCardControl
|
||||||
if (SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtTxBuf,szTxLen+5,abtRxBuf,szRxBufLen,(void*)&szRxBufLen) != SCARD_S_SUCCESS) {
|
(pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtTxBuf, szTxLen + 5, abtRxBuf, szRxBufLen,
|
||||||
|
(void *) &szRxBufLen) != SCARD_S_SUCCESS) {
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (SCardTransmit(pas->hCard,&(pas->ioCard),abtTxBuf,szTxLen+5,NULL,abtRxBuf,(void*)&szRxBufLen) != SCARD_S_SUCCESS) {
|
if (SCardTransmit (pas->hCard, &(pas->ioCard), abtTxBuf, szTxLen + 5, NULL, abtRxBuf, (void *) &szRxBufLen) !=
|
||||||
|
SCARD_S_SUCCESS) {
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_T0)
|
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_T0) {
|
||||||
{
|
|
||||||
// Make sure we received the byte-count we expected
|
// Make sure we received the byte-count we expected
|
||||||
if (szRxBufLen != 2) {
|
if (szRxBufLen != 2) {
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the operation was successful, so an answer is available
|
// Check if the operation was successful, so an answer is available
|
||||||
if (*abtRxBuf == SCARD_OPERATION_ERROR) {
|
if (*abtRxBuf == SCARD_OPERATION_ERROR) {
|
||||||
pnd->iLastError = DEISERRFRAME;
|
pnd->iLastError = DEISERRFRAME;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the response bytes
|
// Retrieve the response bytes
|
||||||
abtRxCmd[4] = abtRxBuf[1];
|
abtRxCmd[4] = abtRxBuf[1];
|
||||||
szRxBufLen = sizeof(abtRxBuf);
|
szRxBufLen = sizeof (abtRxBuf);
|
||||||
if (SCardTransmit(pas->hCard,&(pas->ioCard),abtRxCmd,szRxCmdLen,NULL,abtRxBuf,(void*)&szRxBufLen) != SCARD_S_SUCCESS) {
|
if (SCardTransmit (pas->hCard, &(pas->ioCard), abtRxCmd, szRxCmdLen, NULL, abtRxBuf, (void *) &szRxBufLen) !=
|
||||||
|
SCARD_S_SUCCESS) {
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 succesful result
|
// When the answer should be ignored, just return a succesful result
|
||||||
if (pbtRx == NULL || pszRxLen == NULL) return true;
|
if (pbtRx == NULL || pszRxLen == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Make sure we have an emulated answer that fits the return buffer
|
// Make sure we have an emulated answer that fits the return buffer
|
||||||
if (szRxBufLen < 4 || (szRxBufLen-4) > *pszRxLen) {
|
if (szRxBufLen < 4 || (szRxBufLen - 4) > *pszRxLen) {
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00
|
// Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00
|
||||||
*pszRxLen = ((size_t)szRxBufLen)-4;
|
*pszRxLen = ((size_t) szRxBufLen) - 4;
|
||||||
memcpy(pbtRx,abtRxBuf+2,*pszRxLen);
|
memcpy (pbtRx, abtRxBuf + 2, *pszRxLen);
|
||||||
|
|
||||||
// Transmission went successful
|
// Transmission went successful
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* acr122_firmware(const nfc_device_spec_t nds)
|
char *
|
||||||
|
acr122_firmware (const nfc_device_spec_t nds)
|
||||||
{
|
{
|
||||||
byte_t abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 };
|
byte_t abtGetFw[5] = { 0xFF, 0x00, 0x48, 0x00, 0x00 };
|
||||||
uint32_t uiResult;
|
uint32_t uiResult;
|
||||||
|
|
||||||
acr122_spec_t* pas = (acr122_spec_t*)nds;
|
acr122_spec_t *pas = (acr122_spec_t *) nds;
|
||||||
static char abtFw[11];
|
static char abtFw[11];
|
||||||
size_t szFwLen = sizeof(abtFw);
|
size_t szFwLen = sizeof (abtFw);
|
||||||
memset(abtFw,0x00,szFwLen);
|
memset (abtFw, 0x00, szFwLen);
|
||||||
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) {
|
||||||
{
|
uiResult =
|
||||||
uiResult = SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtGetFw,sizeof(abtGetFw),abtFw,szFwLen,(void*)&szFwLen);
|
SCardControl (pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtGetFw, sizeof (abtGetFw), abtFw, szFwLen,
|
||||||
|
(void *) &szFwLen);
|
||||||
} else {
|
} else {
|
||||||
uiResult = SCardTransmit(pas->hCard,&(pas->ioCard),abtGetFw,sizeof(abtGetFw),NULL,(byte_t*)abtFw,(void*)&szFwLen);
|
uiResult =
|
||||||
|
SCardTransmit (pas->hCard, &(pas->ioCard), abtGetFw, sizeof (abtGetFw), NULL, (byte_t *) abtFw,
|
||||||
|
(void *) &szFwLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (uiResult != SCARD_S_SUCCESS)
|
if (uiResult != SCARD_S_SUCCESS) {
|
||||||
{
|
printf ("No ACR122 firmware received, Error: %08x\n", uiResult);
|
||||||
printf("No ACR122 firmware received, Error: %08x\n",uiResult);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return abtFw;
|
return abtFw;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acr122_led_red(const nfc_device_spec_t nds, bool bOn)
|
bool
|
||||||
|
acr122_led_red (const nfc_device_spec_t nds, bool bOn)
|
||||||
{
|
{
|
||||||
byte_t abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 };
|
byte_t abtLed[9] = { 0xFF, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00 };
|
||||||
acr122_spec_t* pas = (acr122_spec_t*)nds;
|
acr122_spec_t *pas = (acr122_spec_t *) nds;
|
||||||
byte_t abtBuf[2];
|
byte_t abtBuf[2];
|
||||||
size_t szBufLen = sizeof(abtBuf);
|
size_t szBufLen = sizeof (abtBuf);
|
||||||
(void)bOn;
|
(void) bOn;
|
||||||
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) {
|
||||||
{
|
return (SCardControl
|
||||||
return (SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtLed,sizeof(abtLed),abtBuf,szBufLen,(void*)&szBufLen) == SCARD_S_SUCCESS);
|
(pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtLed, sizeof (abtLed), abtBuf, szBufLen,
|
||||||
|
(void *) &szBufLen) == SCARD_S_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
return (SCardTransmit(pas->hCard,&(pas->ioCard),abtLed,sizeof(abtLed),NULL,(byte_t*)abtBuf,(void*)&szBufLen) == SCARD_S_SUCCESS);
|
return (SCardTransmit
|
||||||
|
(pas->hCard, &(pas->ioCard), abtLed, sizeof (abtLed), NULL, (byte_t *) abtBuf,
|
||||||
|
(void *) &szBufLen) == SCARD_S_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,29 +22,29 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVER_ACR122_H__
|
#ifndef __NFC_DRIVER_ACR122_H__
|
||||||
#define __NFC_DRIVER_ACR122_H__
|
# define __NFC_DRIVER_ACR122_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
# include <stdint.h>
|
||||||
#include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#define ACR122_DRIVER_NAME "ACR122"
|
# define ACR122_DRIVER_NAME "ACR122"
|
||||||
|
|
||||||
nfc_device_desc_t* acr122_pick_device(void);
|
nfc_device_desc_t *acr122_pick_device (void);
|
||||||
bool acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool acr122_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
// Functions used by developer to handle connection to this device
|
||||||
nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd);
|
nfc_device_t *acr122_connect (const nfc_device_desc_t * pndd);
|
||||||
void acr122_disconnect(nfc_device_t* pnd);
|
void acr122_disconnect (nfc_device_t * pnd);
|
||||||
|
|
||||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
// Callback function used by libnfc to transmit commands to the PN53X chip
|
||||||
bool acr122_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
bool acr122_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen);
|
||||||
|
|
||||||
// Various additional features this device supports
|
// Various additional features this device supports
|
||||||
char* acr122_firmware(const nfc_device_spec_t nds);
|
char *acr122_firmware (const nfc_device_spec_t nds);
|
||||||
bool acr122_led_red(const nfc_device_spec_t nds, bool bOn);
|
bool acr122_led_red (const nfc_device_spec_t nds, bool bOn);
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_ACR122_H__
|
#endif // ! __NFC_DRIVER_ACR122_H__
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "../drivers.h"
|
#include "../drivers.h"
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
#define SERIAL_DEFAULT_PORT_SPEED 9600
|
#define SERIAL_DEFAULT_PORT_SPEED 9600
|
||||||
|
|
||||||
bool arygon_check_communication(const nfc_device_spec_t nds);
|
bool arygon_check_communication (const nfc_device_spec_t nds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note ARYGON-ADRA (PN531): ???,n,8,1
|
* @note ARYGON-ADRA (PN531): ???,n,8,1
|
||||||
|
@ -84,15 +84,15 @@ arygon_pick_device (void)
|
||||||
nfc_device_desc_t *pndd;
|
nfc_device_desc_t *pndd;
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd)))) {
|
if ((pndd = malloc (sizeof (*pndd)))) {
|
||||||
size_t szN;
|
size_t szN;
|
||||||
|
|
||||||
if (!arygon_list_devices (pndd, 1, &szN)) {
|
if (!arygon_list_devices (pndd, 1, &szN)) {
|
||||||
DBG("%s", "arygon_list_devices failed");
|
DBG ("%s", "arygon_list_devices failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szN == 0) {
|
if (szN == 0) {
|
||||||
DBG("%s", "No device found");
|
DBG ("%s", "No device found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,79 +101,87 @@ arygon_pick_device (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
/** @note: Due to UART bus we can't know if its really a pn532 without
|
/** @note: Due to UART bus we can't know if its really a pn532 without
|
||||||
* sending some PN53x commands. But using this way to probe devices, we can
|
* sending some PN53x commands. But using this way to probe devices, we can
|
||||||
* have serious problem with other device on this bus */
|
* have serious problem with other device on this bus */
|
||||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||||
(void)pnddDevices;
|
(void) pnddDevices;
|
||||||
(void)szDevices;
|
(void) szDevices;
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
DBG("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||||
return false;
|
return false;
|
||||||
#else /* SERIAL_AUTOPROBE_ENABLED */
|
#else /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
|
const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
|
||||||
const char* pcPort;
|
const char *pcPort;
|
||||||
int iDevice = 0;
|
int iDevice = 0;
|
||||||
|
|
||||||
while( (pcPort = pcPorts[iDevice++]) ) {
|
while ((pcPort = pcPorts[iDevice++])) {
|
||||||
sp = uart_open(pcPort);
|
sp = uart_open (pcPort);
|
||||||
DBG("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
|
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))
|
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
||||||
{
|
uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
|
||||||
uart_set_speed(sp, SERIAL_DEFAULT_PORT_SPEED);
|
if (!arygon_check_communication ((nfc_device_spec_t) sp))
|
||||||
if(!arygon_check_communication((nfc_device_spec_t)sp)) continue;
|
continue;
|
||||||
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", pcPort);
|
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(pcPort);
|
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)++;
|
||||||
|
|
||||||
// Test if we reach the maximum "wanted" devices
|
// Test if we reach the maximum "wanted" devices
|
||||||
if((*pszDeviceFound) >= szDevices) break;
|
if ((*pszDeviceFound) >= szDevices)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
|
if (sp == INVALID_SERIAL_PORT)
|
||||||
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
|
DBG ("Invalid serial port: %s", pcPort);
|
||||||
#endif /* DEBUG */
|
if (sp == CLAIMED_SERIAL_PORT)
|
||||||
|
DBG ("Serial port already claimed: %s", pcPort);
|
||||||
|
# endif
|
||||||
|
/* DEBUG */
|
||||||
}
|
}
|
||||||
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
|
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;
|
||||||
|
|
||||||
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
|
||||||
sp = uart_open(pndd->pcPort);
|
sp = uart_open (pndd->pcPort);
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
if (sp == INVALID_SERIAL_PORT)
|
||||||
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
ERR ("Invalid serial port: %s", pndd->pcPort);
|
||||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
if (sp == CLAIMED_SERIAL_PORT)
|
||||||
|
ERR ("Serial port already claimed: %s", pndd->pcPort);
|
||||||
|
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);
|
||||||
|
|
||||||
// We have a connection
|
// We have a connection
|
||||||
pnd = malloc(sizeof(nfc_device_t));
|
pnd = malloc (sizeof (nfc_device_t));
|
||||||
strncpy(pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
||||||
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
|
|
||||||
pnd->nc = NC_PN532;
|
pnd->nc = NC_PN532;
|
||||||
pnd->nds = (nfc_device_spec_t)sp;
|
pnd->nds = (nfc_device_spec_t) sp;
|
||||||
pnd->bActive = true;
|
pnd->bActive = true;
|
||||||
pnd->bCrc = true;
|
pnd->bCrc = true;
|
||||||
pnd->bPar = true;
|
pnd->bPar = true;
|
||||||
|
@ -181,19 +189,21 @@ nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arygon_disconnect(nfc_device_t* pnd)
|
void
|
||||||
|
arygon_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
uart_close((serial_port)pnd->nds);
|
uart_close ((serial_port) pnd->nds);
|
||||||
free(pnd);
|
free (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
byte_t abtTxBuf[BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
byte_t abtTxBuf[BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||||
byte_t abtRxBuf[BUFFER_LENGTH];
|
byte_t abtRxBuf[BUFFER_LENGTH];
|
||||||
size_t szRxBufLen = BUFFER_LENGTH;
|
size_t szRxBufLen = BUFFER_LENGTH;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
int res;
|
int res;
|
||||||
// TODO: Move this one level up for libnfc-1.6
|
// TODO: Move this one level up for libnfc-1.6
|
||||||
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
||||||
|
|
||||||
|
@ -202,57 +212,55 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx
|
||||||
// Packet length checksum
|
// Packet length checksum
|
||||||
abtTxBuf[5] = BUFFER_LENGTH - abtTxBuf[4];
|
abtTxBuf[5] = BUFFER_LENGTH - abtTxBuf[4];
|
||||||
// Copy the PN53X command into the packet buffer
|
// Copy the PN53X command into the packet buffer
|
||||||
memmove(abtTxBuf+6,pbtTx,szTxLen);
|
memmove (abtTxBuf + 6, pbtTx, szTxLen);
|
||||||
|
|
||||||
// Calculate data payload checksum
|
// Calculate data payload checksum
|
||||||
abtTxBuf[szTxLen+6] = 0;
|
abtTxBuf[szTxLen + 6] = 0;
|
||||||
for(szPos=0; szPos < szTxLen; szPos++) {
|
for (szPos = 0; szPos < szTxLen; szPos++) {
|
||||||
abtTxBuf[szTxLen+6] -= abtTxBuf[szPos+6];
|
abtTxBuf[szTxLen + 6] -= abtTxBuf[szPos + 6];
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of stream marker
|
// End of stream marker
|
||||||
abtTxBuf[szTxLen+7] = 0;
|
abtTxBuf[szTxLen + 7] = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", abtTxBuf,szTxLen+8);
|
PRINT_HEX ("TX", abtTxBuf, szTxLen + 8);
|
||||||
#endif
|
#endif
|
||||||
res = uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+8);
|
res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTxLen + 8);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bzero(abtRxBuf, sizeof(abtRxBuf));
|
bzero (abtRxBuf, sizeof (abtRxBuf));
|
||||||
#endif
|
#endif
|
||||||
res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen);
|
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to receive data. (RX)");
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
|
// WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
|
||||||
if (!pn53x_transceive_check_ack_frame_callback(pnd, abtRxBuf, szRxBufLen))
|
if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
szRxBufLen -= sizeof(ack_frame);
|
szRxBufLen -= sizeof (ack_frame);
|
||||||
memmove(abtRxBuf, abtRxBuf+sizeof(ack_frame), szRxBufLen);
|
memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen);
|
||||||
|
|
||||||
if (szRxBufLen == 0) {
|
if (szRxBufLen == 0) {
|
||||||
szRxBufLen = BUFFER_LENGTH;
|
szRxBufLen = BUFFER_LENGTH;
|
||||||
do {
|
do {
|
||||||
delay_ms(10);
|
delay_ms (10);
|
||||||
res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen);
|
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
||||||
} while (res != 0 );
|
} while (res != 0);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -266,56 +274,61 @@ bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTx
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (!pn53x_transceive_check_error_frame_callback(pnd, abtRxBuf, szRxBufLen))
|
if (!pn53x_transceive_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// When the answer should be ignored, just return a successful result
|
// When the answer should be ignored, just return a successful result
|
||||||
if(pbtRx == NULL || pszRxLen == NULL) return true;
|
if (pbtRx == NULL || pszRxLen == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
||||||
if(szRxBufLen < 9) return false;
|
if (szRxBufLen < 9)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
// Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
||||||
*pszRxLen = szRxBufLen - 9;
|
*pszRxLen = szRxBufLen - 9;
|
||||||
memcpy(pbtRx, abtRxBuf+7, *pszRxLen);
|
memcpy (pbtRx, abtRxBuf + 7, *pszRxLen);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Use tranceive function instead of raw uart send/receive for communication check.
|
//TODO Use tranceive function instead of raw uart send/receive for communication check.
|
||||||
bool
|
bool
|
||||||
arygon_check_communication(const nfc_device_spec_t nds)
|
arygon_check_communication (const nfc_device_spec_t nds)
|
||||||
{
|
{
|
||||||
byte_t abtRx[BUFFER_LENGTH];
|
byte_t abtRx[BUFFER_LENGTH];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
const byte_t attempted_result[] = { 0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0xff,0x09,0xf7,0xD5,0x01,0x00,'l','i','b','n','f','c',0xbc,0x00};
|
const byte_t attempted_result[] =
|
||||||
int res;
|
{ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c',
|
||||||
|
0xbc, 0x00 };
|
||||||
|
int res;
|
||||||
|
|
||||||
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
|
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
|
||||||
const byte_t pncmd_communication_test[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00,0x00,0xff,0x09,0xf7,0xd4,0x00,0x00,'l','i','b','n','f','c',0xbe,0x00 };
|
const byte_t pncmd_communication_test[] =
|
||||||
|
{ DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe,
|
||||||
|
0x00 };
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", pncmd_communication_test,sizeof(pncmd_communication_test));
|
PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
|
||||||
#endif
|
#endif
|
||||||
res = uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test));
|
res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = uart_receive((serial_port)nds,abtRx,&szRxLen);
|
res = uart_receive ((serial_port) nds, abtRx, &szRxLen);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to receive data. (RX)");
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRx,szRxLen);
|
PRINT_HEX ("RX", abtRx, szRxLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(0 != memcmp(abtRx,attempted_result,sizeof(attempted_result))) {
|
if (0 != memcmp (abtRx, attempted_result, sizeof (attempted_result))) {
|
||||||
DBG("%s", "Communication test failed, result doesn't match to attempted one.");
|
DBG ("%s", "Communication test failed, result doesn't match to attempted one.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVER_ARYGON_H__
|
#ifndef __NFC_DRIVER_ARYGON_H__
|
||||||
#define __NFC_DRIVER_ARYGON_H__
|
# define __NFC_DRIVER_ARYGON_H__
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#define ARYGON_DRIVER_NAME "ARYGON"
|
# define ARYGON_DRIVER_NAME "ARYGON"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
// Functions used by developer to handle connection to this device
|
||||||
nfc_device_desc_t * arygon_pick_device (void);
|
nfc_device_desc_t *arygon_pick_device (void);
|
||||||
bool arygon_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
|
|
||||||
nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd);
|
nfc_device_t *arygon_connect (const nfc_device_desc_t * pndd);
|
||||||
void arygon_disconnect(nfc_device_t* pnd);
|
void arygon_disconnect (nfc_device_t * pnd);
|
||||||
|
|
||||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
// Callback function used by libnfc to transmit commands to the PN53X chip
|
||||||
bool arygon_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
bool arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen);
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_ARYGON_H__
|
#endif // ! __NFC_DRIVER_ARYGON_H__
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ Thanks to d18c7db and Okko for example code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -35,39 +35,41 @@ Thanks to d18c7db and Okko for example code
|
||||||
#include "../drivers.h"
|
#include "../drivers.h"
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
nfc_device_desc_t * pn531_usb_pick_device (void)
|
nfc_device_desc_t *
|
||||||
|
pn531_usb_pick_device (void)
|
||||||
{
|
{
|
||||||
nfc_device_desc_t *pndd;
|
nfc_device_desc_t *pndd;
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd))))
|
if ((pndd = malloc (sizeof (*pndd)))) {
|
||||||
{
|
size_t szN;
|
||||||
size_t szN;
|
|
||||||
|
|
||||||
if (!pn531_usb_list_devices (pndd, 1, &szN))
|
if (!pn531_usb_list_devices (pndd, 1, &szN)) {
|
||||||
{
|
DBG ("%s", "pn531_usb_list_devices failed");
|
||||||
DBG("%s", "pn531_usb_list_devices failed");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szN == 0)
|
if (szN == 0) {
|
||||||
{
|
DBG ("%s", "No device found");
|
||||||
DBG("%s", "No device found");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pndd;
|
return pndd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn531_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
bool
|
||||||
|
pn531_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
// array of {vendor,product} pairs for USB devices
|
// array of {vendor,product} pairs for USB devices
|
||||||
usb_candidate_t candidates[]= {{0x04CC,0x0531},{0x054c,0x0193}};
|
usb_candidate_t candidates[] = { {0x04CC, 0x0531}
|
||||||
|
, {0x054c, 0x0193}
|
||||||
|
};
|
||||||
|
|
||||||
return pn53x_usb_list_devices(&pnddDevices[0], szDevices, pszDeviceFound, &candidates[0], sizeof(candidates) / sizeof(usb_candidate_t),PN531_USB_DRIVER_NAME);
|
return pn53x_usb_list_devices (&pnddDevices[0], szDevices, pszDeviceFound, &candidates[0],
|
||||||
|
sizeof (candidates) / sizeof (usb_candidate_t), PN531_USB_DRIVER_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* pn531_usb_connect(const nfc_device_desc_t* pndd)
|
nfc_device_t *
|
||||||
|
pn531_usb_connect (const nfc_device_desc_t * pndd)
|
||||||
{
|
{
|
||||||
return pn53x_usb_connect(pndd, pndd->acDevice, NC_PN531);
|
return pn53x_usb_connect (pndd, pndd->acDevice, NC_PN531);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVER_PN531_USB_H__
|
#ifndef __NFC_DRIVER_PN531_USB_H__
|
||||||
#define __NFC_DRIVER_PN531_USB_H__
|
# define __NFC_DRIVER_PN531_USB_H__
|
||||||
|
|
||||||
#define PN531_USB_DRIVER_NAME "PN531_USB"
|
# define PN531_USB_DRIVER_NAME "PN531_USB"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
// Functions used by developer to handle connection to this device
|
||||||
nfc_device_t* pn531_usb_connect(const nfc_device_desc_t* pndd);
|
nfc_device_t *pn531_usb_connect (const nfc_device_desc_t * pndd);
|
||||||
bool pn531_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool pn531_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
nfc_device_desc_t * pn531_usb_pick_device (void);
|
nfc_device_desc_t *pn531_usb_pick_device (void);
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_PN531_USB_H__
|
#endif // ! __NFC_DRIVER_PN531_USB_H__
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "../drivers.h"
|
#include "../drivers.h"
|
||||||
|
@ -43,8 +43,8 @@
|
||||||
|
|
||||||
#define SERIAL_DEFAULT_PORT_SPEED 115200
|
#define SERIAL_DEFAULT_PORT_SPEED 115200
|
||||||
|
|
||||||
void pn532_uart_wakeup(const nfc_device_spec_t nds);
|
void pn532_uart_wakeup (const nfc_device_spec_t nds);
|
||||||
bool pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success);
|
bool pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success);
|
||||||
|
|
||||||
nfc_device_desc_t *
|
nfc_device_desc_t *
|
||||||
pn532_uart_pick_device (void)
|
pn532_uart_pick_device (void)
|
||||||
|
@ -52,15 +52,15 @@ pn532_uart_pick_device (void)
|
||||||
nfc_device_desc_t *pndd;
|
nfc_device_desc_t *pndd;
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd)))) {
|
if ((pndd = malloc (sizeof (*pndd)))) {
|
||||||
size_t szN;
|
size_t szN;
|
||||||
|
|
||||||
if (!pn532_uart_list_devices (pndd, 1, &szN)) {
|
if (!pn532_uart_list_devices (pndd, 1, &szN)) {
|
||||||
DBG("%s", "pn532_uart_list_devices failed");
|
DBG ("%s", "pn532_uart_list_devices failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szN == 0) {
|
if (szN == 0) {
|
||||||
DBG("%s", "No device found");
|
DBG ("%s", "No device found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,95 +69,102 @@ pn532_uart_pick_device (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
/** @note: Due to UART bus we can't know if its really a pn532 without
|
/** @note: Due to UART bus we can't know if its really a pn532 without
|
||||||
* sending some PN53x commands. But using this way to probe devices, we can
|
* sending some PN53x commands. But using this way to probe devices, we can
|
||||||
* have serious problem with other device on this bus */
|
* have serious problem with other device on this bus */
|
||||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||||
(void)pnddDevices;
|
(void) pnddDevices;
|
||||||
(void)szDevices;
|
(void) szDevices;
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
DBG("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||||
return false;
|
return false;
|
||||||
#else /* SERIAL_AUTOPROBE_ENABLED */
|
#else /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
const char* pcPorts[] = DEFAULT_SERIAL_PORTS;
|
const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
|
||||||
const char* pcPort;
|
const char *pcPort;
|
||||||
int iDevice = 0;
|
int iDevice = 0;
|
||||||
|
|
||||||
while( (pcPort = pcPorts[iDevice++]) ) {
|
while ((pcPort = pcPorts[iDevice++])) {
|
||||||
sp = uart_open(pcPort);
|
sp = uart_open (pcPort);
|
||||||
DBG("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
|
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))
|
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
||||||
{
|
bool bComOk;
|
||||||
bool bComOk;
|
|
||||||
// Serial port claimed but we need to check if a PN532_UART is connected.
|
// Serial port claimed but we need to check if a PN532_UART is connected.
|
||||||
uart_set_speed(sp, SERIAL_DEFAULT_PORT_SPEED);
|
uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
|
||||||
// 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)
|
||||||
if(!pn532_uart_check_communication((nfc_device_spec_t)sp, &bComOk))
|
if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
|
||||||
return false;
|
return false;
|
||||||
if (!bComOk)
|
if (!bComOk)
|
||||||
continue;
|
continue;
|
||||||
uart_close(sp);
|
uart_close (sp);
|
||||||
|
|
||||||
snprintf(pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
|
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(pcPort);
|
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)++;
|
||||||
|
|
||||||
// Test if we reach the maximum "wanted" devices
|
// Test if we reach the maximum "wanted" devices
|
||||||
if((*pszDeviceFound) >= szDevices) break;
|
if ((*pszDeviceFound) >= szDevices)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s", pcPort);
|
if (sp == INVALID_SERIAL_PORT)
|
||||||
if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s", pcPort);
|
DBG ("Invalid serial port: %s", pcPort);
|
||||||
#endif /* DEBUG */
|
if (sp == CLAIMED_SERIAL_PORT)
|
||||||
|
DBG ("Serial port already claimed: %s", pcPort);
|
||||||
|
# endif
|
||||||
|
/* DEBUG */
|
||||||
}
|
}
|
||||||
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd)
|
nfc_device_t *
|
||||||
|
pn532_uart_connect (const nfc_device_desc_t * pndd)
|
||||||
{
|
{
|
||||||
serial_port sp;
|
serial_port sp;
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t *pnd = NULL;
|
||||||
bool bComOk;
|
bool bComOk;
|
||||||
|
|
||||||
DBG("Attempt to connect to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
|
DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
|
||||||
sp = uart_open(pndd->pcPort);
|
sp = uart_open (pndd->pcPort);
|
||||||
|
|
||||||
if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",pndd->pcPort);
|
if (sp == INVALID_SERIAL_PORT)
|
||||||
if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",pndd->pcPort);
|
ERR ("Invalid serial port: %s", pndd->pcPort);
|
||||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
|
if (sp == CLAIMED_SERIAL_PORT)
|
||||||
|
ERR ("Serial port already claimed: %s", pndd->pcPort);
|
||||||
|
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)
|
||||||
if(!pn532_uart_check_communication((nfc_device_spec_t)sp, &bComOk))
|
if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!bComOk)
|
if (!bComOk)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
DBG("Successfully connected to: %s",pndd->pcPort);
|
DBG ("Successfully connected to: %s", pndd->pcPort);
|
||||||
|
|
||||||
// We have a connection
|
// We have a connection
|
||||||
pnd = malloc(sizeof(nfc_device_t));
|
pnd = malloc (sizeof (nfc_device_t));
|
||||||
strncpy(pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
||||||
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
|
|
||||||
pnd->nc = NC_PN532;
|
pnd->nc = NC_PN532;
|
||||||
pnd->nds = (nfc_device_spec_t)sp;
|
pnd->nds = (nfc_device_spec_t) sp;
|
||||||
pnd->bActive = true;
|
pnd->bActive = true;
|
||||||
pnd->bCrc = true;
|
pnd->bCrc = true;
|
||||||
pnd->bPar = true;
|
pnd->bPar = true;
|
||||||
|
@ -165,19 +172,22 @@ nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd)
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn532_uart_disconnect(nfc_device_t* pnd)
|
void
|
||||||
|
pn532_uart_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
uart_close((serial_port)pnd->nds);
|
uart_close ((serial_port) pnd->nds);
|
||||||
free(pnd);
|
free (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
byte_t abtTxBuf[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
byte_t abtTxBuf[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||||
byte_t abtRxBuf[BUFFER_LENGTH];
|
byte_t abtRxBuf[BUFFER_LENGTH];
|
||||||
size_t szRxBufLen = BUFFER_LENGTH;
|
size_t szRxBufLen = BUFFER_LENGTH;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
int res;
|
int res;
|
||||||
// TODO: Move this one level up for libnfc-1.6
|
// TODO: Move this one level up for libnfc-1.6
|
||||||
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
||||||
|
|
||||||
|
@ -186,63 +196,60 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t
|
||||||
// Packet length checksum
|
// Packet length checksum
|
||||||
abtTxBuf[4] = BUFFER_LENGTH - abtTxBuf[3];
|
abtTxBuf[4] = BUFFER_LENGTH - abtTxBuf[3];
|
||||||
// Copy the PN53X command into the packet buffer
|
// Copy the PN53X command into the packet buffer
|
||||||
memmove(abtTxBuf+5,pbtTx,szTxLen);
|
memmove (abtTxBuf + 5, pbtTx, szTxLen);
|
||||||
|
|
||||||
// Calculate data payload checksum
|
// Calculate data payload checksum
|
||||||
abtTxBuf[szTxLen+5] = 0;
|
abtTxBuf[szTxLen + 5] = 0;
|
||||||
for(szPos=0; szPos < szTxLen; szPos++)
|
for (szPos = 0; szPos < szTxLen; szPos++) {
|
||||||
{
|
abtTxBuf[szTxLen + 5] -= abtTxBuf[szPos + 5];
|
||||||
abtTxBuf[szTxLen+5] -= abtTxBuf[szPos+5];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of stream marker
|
// End of stream marker
|
||||||
abtTxBuf[szTxLen+6] = 0;
|
abtTxBuf[szTxLen + 6] = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", abtTxBuf,szTxLen+7);
|
PRINT_HEX ("TX", abtTxBuf, szTxLen + 7);
|
||||||
#endif
|
#endif
|
||||||
res = uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7);
|
res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTxLen + 7);
|
||||||
if(res != 0) {
|
|
||||||
ERR("%s", "Unable to transmit data. (TX)");
|
|
||||||
pnd->iLastError = res;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen);
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to receive data. (RX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
||||||
|
if (res != 0) {
|
||||||
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
|
pnd->iLastError = res;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
|
// WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
|
||||||
if (!pn53x_transceive_check_ack_frame_callback(pnd, abtRxBuf, szRxBufLen))
|
if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
|
||||||
return false;
|
return false;
|
||||||
szRxBufLen -= sizeof(ack_frame);
|
szRxBufLen -= sizeof (ack_frame);
|
||||||
memmove(abtRxBuf, abtRxBuf+sizeof(ack_frame), szRxBufLen);
|
memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen);
|
||||||
|
|
||||||
if (szRxBufLen == 0) {
|
if (szRxBufLen == 0) {
|
||||||
szRxBufLen = BUFFER_LENGTH;
|
szRxBufLen = BUFFER_LENGTH;
|
||||||
do {
|
do {
|
||||||
delay_ms(10);
|
delay_ms (10);
|
||||||
res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen);
|
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
||||||
} while (res != 0 );
|
} while (res != 0);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRxBuf,szRxBufLen);
|
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", ack_frame,6);
|
PRINT_HEX ("TX", ack_frame, 6);
|
||||||
#endif
|
#endif
|
||||||
res = uart_send((serial_port)pnd->nds,ack_frame,6);
|
res = uart_send ((serial_port) pnd->nds, ack_frame, 6);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -251,76 +258,79 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// When the answer should be ignored, just return a successful result
|
// When the answer should be ignored, just return a successful result
|
||||||
if(pbtRx == NULL || pszRxLen == NULL) return true;
|
if (pbtRx == NULL || pszRxLen == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
||||||
if(szRxBufLen < 9) {
|
if (szRxBufLen < 9) {
|
||||||
pnd->iLastError = DEINVAL;
|
pnd->iLastError = DEINVAL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
// Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
||||||
*pszRxLen = szRxBufLen - 9;
|
*pszRxLen = szRxBufLen - 9;
|
||||||
memcpy(pbtRx, abtRxBuf+7, *pszRxLen);
|
memcpy (pbtRx, abtRxBuf + 7, *pszRxLen);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pn532_uart_wakeup(const nfc_device_spec_t nds)
|
pn532_uart_wakeup (const nfc_device_spec_t nds)
|
||||||
{
|
{
|
||||||
byte_t abtRx[BUFFER_LENGTH];
|
byte_t abtRx[BUFFER_LENGTH];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
/** PN532C106 wakeup. */
|
/** PN532C106 wakeup. */
|
||||||
/** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
|
/** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
|
||||||
/** After the preamble we request the PN532C106 chip to switch to "normal" mode (SAM is not used) */
|
/** After the preamble we request the PN532C106 chip to switch to "normal" mode (SAM is not used) */
|
||||||
const byte_t pncmd_pn532c106_wakeup_preamble[] = { 0x55,0x55,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00,0x00,0xff,0x03,0xfd,0xd4,0x14,0x01,0x17,0x00 };
|
const byte_t pncmd_pn532c106_wakeup_preamble[] =
|
||||||
|
{ 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00, 0x00, 0xff, 0x03, 0xfd,
|
||||||
|
0xd4, 0x14, 0x01, 0x17, 0x00 };
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", pncmd_pn532c106_wakeup_preamble,sizeof(pncmd_pn532c106_wakeup_preamble));
|
PRINT_HEX ("TX", pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
|
||||||
#endif
|
#endif
|
||||||
uart_send((serial_port)nds, pncmd_pn532c106_wakeup_preamble, sizeof(pncmd_pn532c106_wakeup_preamble));
|
uart_send ((serial_port) nds, pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
|
||||||
if(0 == uart_receive((serial_port)nds,abtRx,&szRxLen)) {
|
if (0 == uart_receive ((serial_port) nds, abtRx, &szRxLen)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRx,szRxLen);
|
PRINT_HEX ("RX", abtRx, szRxLen);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success)
|
pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success)
|
||||||
{
|
{
|
||||||
byte_t abtRx[BUFFER_LENGTH];
|
byte_t abtRx[BUFFER_LENGTH];
|
||||||
size_t szRxLen;
|
size_t szRxLen;
|
||||||
const byte_t attempted_result[] = { 0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0xff,0x09,0xf7,0xD5,0x01,0x00,'l','i','b','n','f','c',0xbc,0x00};
|
const byte_t attempted_result[] =
|
||||||
int res;
|
{ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c',
|
||||||
|
0xbc, 0x00 };
|
||||||
|
int res;
|
||||||
|
|
||||||
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
|
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
|
||||||
const byte_t pncmd_communication_test[] = { 0x00,0x00,0xff,0x09,0xf7,0xd4,0x00,0x00,'l','i','b','n','f','c',0xbe,0x00 };
|
const byte_t pncmd_communication_test[] =
|
||||||
|
{ 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
|
||||||
|
|
||||||
*success = false;
|
*success = false;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", pncmd_communication_test,sizeof(pncmd_communication_test));
|
PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
|
||||||
#endif
|
#endif
|
||||||
res = uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test));
|
res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = uart_receive((serial_port)nds,abtRx,&szRxLen);
|
res = uart_receive ((serial_port) nds, abtRx, &szRxLen);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR("%s", "Unable to receive data. (RX)");
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRx,szRxLen);
|
PRINT_HEX ("RX", abtRx, szRxLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(0 == memcmp(abtRx,attempted_result,sizeof(attempted_result)))
|
if (0 == memcmp (abtRx, attempted_result, sizeof (attempted_result)))
|
||||||
*success = true;
|
*success = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVER_PN532_UART_H__
|
#ifndef __NFC_DRIVER_PN532_UART_H__
|
||||||
#define __NFC_DRIVER_PN532_UART_H__
|
# define __NFC_DRIVER_PN532_UART_H__
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
#define PN532_UART_DRIVER_NAME "PN532_UART"
|
# define PN532_UART_DRIVER_NAME "PN532_UART"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
// Functions used by developer to handle connection to this device
|
||||||
nfc_device_desc_t * pn532_uart_pick_device (void);
|
nfc_device_desc_t *pn532_uart_pick_device (void);
|
||||||
bool pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
|
|
||||||
nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd);
|
nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd);
|
||||||
void pn532_uart_disconnect(nfc_device_t* pnd);
|
void pn532_uart_disconnect (nfc_device_t * pnd);
|
||||||
|
|
||||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
// Callback function used by libnfc to transmit commands to the PN53X chip
|
||||||
bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
bool pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen);
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_PN532_UART_H__
|
#endif // ! __NFC_DRIVER_PN532_UART_H__
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ Thanks to d18c7db and Okko for example code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -35,20 +35,21 @@ Thanks to d18c7db and Okko for example code
|
||||||
#include "../drivers.h"
|
#include "../drivers.h"
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
nfc_device_desc_t * pn533_usb_pick_device (void)
|
nfc_device_desc_t *
|
||||||
|
pn533_usb_pick_device (void)
|
||||||
{
|
{
|
||||||
nfc_device_desc_t *pndd;
|
nfc_device_desc_t *pndd;
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd)))) {
|
if ((pndd = malloc (sizeof (*pndd)))) {
|
||||||
size_t szN;
|
size_t szN;
|
||||||
|
|
||||||
if (!pn533_usb_list_devices (pndd, 1, &szN)) {
|
if (!pn533_usb_list_devices (pndd, 1, &szN)) {
|
||||||
DBG("%s", "pn533_usb_list_devices failed");
|
DBG ("%s", "pn533_usb_list_devices failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szN == 0) {
|
if (szN == 0) {
|
||||||
DBG("%s", "No device found");
|
DBG ("%s", "No device found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,16 +57,20 @@ nfc_device_desc_t * pn533_usb_pick_device (void)
|
||||||
return pndd;
|
return pndd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn533_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
bool
|
||||||
|
pn533_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
// array of {vendor,product} pairs for USB devices
|
// array of {vendor,product} pairs for USB devices
|
||||||
usb_candidate_t candidates[]= {{0x04CC,0x2533},{0x04E6,0x5591}};
|
usb_candidate_t candidates[] = { {0x04CC, 0x2533}
|
||||||
|
, {0x04E6, 0x5591}
|
||||||
|
};
|
||||||
|
|
||||||
return pn53x_usb_list_devices(&pnddDevices[0], szDevices, pszDeviceFound, &candidates[0], sizeof(candidates) / sizeof(usb_candidate_t),PN533_USB_DRIVER_NAME);
|
return pn53x_usb_list_devices (&pnddDevices[0], szDevices, pszDeviceFound, &candidates[0],
|
||||||
|
sizeof (candidates) / sizeof (usb_candidate_t), PN533_USB_DRIVER_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* pn533_usb_connect(const nfc_device_desc_t* pndd)
|
nfc_device_t *
|
||||||
|
pn533_usb_connect (const nfc_device_desc_t * pndd)
|
||||||
{
|
{
|
||||||
return pn53x_usb_connect(pndd, pndd->acDevice, NC_PN533);
|
return pn53x_usb_connect (pndd, pndd->acDevice, NC_PN533);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __NFC_DRIVER_PN533_USB_H__
|
#ifndef __NFC_DRIVER_PN533_USB_H__
|
||||||
#define __NFC_DRIVER_PN533_USB_H__
|
# define __NFC_DRIVER_PN533_USB_H__
|
||||||
|
|
||||||
#define PN533_USB_DRIVER_NAME "PN533_USB"
|
# define PN533_USB_DRIVER_NAME "PN533_USB"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
// Functions used by developer to handle connection to this device
|
||||||
nfc_device_t* pn533_usb_connect(const nfc_device_desc_t* pndd);
|
nfc_device_t *pn533_usb_connect (const nfc_device_desc_t * pndd);
|
||||||
bool pn533_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound);
|
bool pn533_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
nfc_device_desc_t * pn533_usb_pick_device (void);
|
nfc_device_desc_t *pn533_usb_pick_device (void);
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_PN533_USB_H__
|
#endif // ! __NFC_DRIVER_PN533_USB_H__
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -46,113 +46,109 @@ Thanks to d18c7db and Okko for example code
|
||||||
#define USB_TIMEOUT 30000
|
#define USB_TIMEOUT 30000
|
||||||
|
|
||||||
// Find transfer endpoints for bulk transfers
|
// Find transfer endpoints for bulk transfers
|
||||||
void get_end_points(struct usb_device *dev, usb_spec_t* pus)
|
void
|
||||||
|
get_end_points (struct usb_device *dev, usb_spec_t * pus)
|
||||||
{
|
{
|
||||||
uint32_t uiIndex;
|
uint32_t uiIndex;
|
||||||
uint32_t uiEndPoint;
|
uint32_t uiEndPoint;
|
||||||
struct usb_interface_descriptor* puid = dev->config->interface->altsetting;
|
struct usb_interface_descriptor *puid = dev->config->interface->altsetting;
|
||||||
|
|
||||||
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
|
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
|
||||||
for(uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++)
|
for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) {
|
||||||
{
|
|
||||||
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
|
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
|
||||||
if(puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) continue;
|
if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Copy the endpoint to a local var, makes it more readable code
|
// Copy the endpoint to a local var, makes it more readable code
|
||||||
uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress;
|
uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress;
|
||||||
|
|
||||||
// Test if we dealing with a bulk IN endpoint
|
// Test if we dealing with a bulk IN endpoint
|
||||||
if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
|
if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) {
|
||||||
{
|
|
||||||
pus->uiEndPointIn = uiEndPoint;
|
pus->uiEndPointIn = uiEndPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if we dealing with a bulk OUT endpoint
|
// Test if we dealing with a bulk OUT endpoint
|
||||||
if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
|
if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) {
|
||||||
{
|
|
||||||
pus->uiEndPointOut = uiEndPoint;
|
pus->uiEndPointOut = uiEndPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn53x_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound,usb_candidate_t candidates[], int num_candidates, char * target_name)
|
bool
|
||||||
|
pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound,
|
||||||
|
usb_candidate_t candidates[], int num_candidates, char *target_name)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret,
|
||||||
|
i;
|
||||||
|
|
||||||
struct usb_bus *bus;
|
struct usb_bus *bus;
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
usb_dev_handle *udev;
|
usb_dev_handle *udev;
|
||||||
uint32_t uiBusIndex = 0;
|
uint32_t uiBusIndex = 0;
|
||||||
char string[256];
|
char string[256];
|
||||||
|
|
||||||
string[0]= '\0';
|
string[0] = '\0';
|
||||||
usb_init();
|
usb_init ();
|
||||||
|
|
||||||
// usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed).
|
// usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed).
|
||||||
if ((ret= usb_find_busses() < 0)) return false;
|
if ((ret = usb_find_busses () < 0))
|
||||||
|
return false;
|
||||||
// usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed).
|
// usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed).
|
||||||
if ((ret= usb_find_devices() < 0)) return false;
|
if ((ret = usb_find_devices () < 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
for (bus = usb_get_busses(); bus; bus = bus->next)
|
for (bus = usb_get_busses (); bus; bus = bus->next) {
|
||||||
{
|
for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) {
|
||||||
for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++)
|
for (i = 0; i < num_candidates; ++i) {
|
||||||
{
|
|
||||||
for(i = 0; i < num_candidates; ++i)
|
|
||||||
{
|
|
||||||
// DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct);
|
// DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct);
|
||||||
if (candidates[i].idVendor==dev->descriptor.idVendor && candidates[i].idProduct==dev->descriptor.idProduct)
|
if (candidates[i].idVendor == dev->descriptor.idVendor && candidates[i].idProduct == dev->descriptor.idProduct) {
|
||||||
{
|
|
||||||
// Make sure there are 2 endpoints available
|
// Make sure there are 2 endpoints available
|
||||||
// with libusb-win32 we got some null pointers so be robust before looking at endpoints:
|
// with libusb-win32 we got some null pointers so be robust before looking at endpoints:
|
||||||
if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL)
|
if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) {
|
||||||
{
|
|
||||||
// Nope, we maybe want the next one, let's try to find another
|
// Nope, we maybe want the next one, let's try to find another
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dev->config->interface->altsetting->bNumEndpoints < 2)
|
if (dev->config->interface->altsetting->bNumEndpoints < 2) {
|
||||||
{
|
|
||||||
// Nope, we maybe want the next one, let's try to find another
|
// Nope, we maybe want the next one, let's try to find another
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dev->descriptor.iManufacturer || dev->descriptor.iProduct)
|
if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
|
||||||
{
|
udev = usb_open (dev);
|
||||||
udev = usb_open(dev);
|
if (udev) {
|
||||||
if(udev)
|
usb_get_string_simple (udev, dev->descriptor.iManufacturer, string, sizeof (string));
|
||||||
{
|
if (strlen (string) > 0)
|
||||||
usb_get_string_simple(udev, dev->descriptor.iManufacturer, string, sizeof(string));
|
strcpy (string + strlen (string), " / ");
|
||||||
if(strlen(string) > 0)
|
usb_get_string_simple (udev, dev->descriptor.iProduct, string + strlen (string),
|
||||||
strcpy(string + strlen(string)," / ");
|
sizeof (string) - strlen (string));
|
||||||
usb_get_string_simple(udev, dev->descriptor.iProduct, string + strlen(string), sizeof(string) - strlen(string));
|
|
||||||
}
|
}
|
||||||
usb_close(udev);
|
usb_close (udev);
|
||||||
}
|
}
|
||||||
if(strlen(string) == 0)
|
if (strlen (string) == 0)
|
||||||
strcpy(pnddDevices[*pszDeviceFound].acDevice, target_name);
|
strcpy (pnddDevices[*pszDeviceFound].acDevice, target_name);
|
||||||
else
|
else
|
||||||
strcpy(pnddDevices[*pszDeviceFound].acDevice, string);
|
strcpy (pnddDevices[*pszDeviceFound].acDevice, string);
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = target_name;
|
pnddDevices[*pszDeviceFound].pcDriver = target_name;
|
||||||
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
// Test if we reach the maximum "wanted" devices
|
// Test if we reach the maximum "wanted" devices
|
||||||
if((*pszDeviceFound) == szDevices)
|
if ((*pszDeviceFound) == szDevices) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(*pszDeviceFound)
|
if (*pszDeviceFound)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * target_name, int target_chip)
|
nfc_device_t *
|
||||||
|
pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip)
|
||||||
{
|
{
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t *pnd = NULL;
|
||||||
usb_spec_t* pus;
|
usb_spec_t *pus;
|
||||||
usb_spec_t us;
|
usb_spec_t us;
|
||||||
struct usb_bus *bus;
|
struct usb_bus *bus;
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
|
@ -162,44 +158,39 @@ 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;
|
||||||
|
|
||||||
DBG("Attempt to connect to %s device", target_name);
|
DBG ("Attempt to connect to %s device", target_name);
|
||||||
usb_init();
|
usb_init ();
|
||||||
|
|
||||||
uiBusIndex= pndd->uiBusIndex;
|
uiBusIndex = pndd->uiBusIndex;
|
||||||
|
|
||||||
for (bus = usb_get_busses(); bus; bus = bus->next)
|
for (bus = usb_get_busses (); bus; bus = bus->next) {
|
||||||
{
|
for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) {
|
||||||
for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--)
|
|
||||||
{
|
|
||||||
// DBG("Checking device %04x:%04x",dev->descriptor.idVendor,dev->descriptor.idProduct);
|
// DBG("Checking device %04x:%04x",dev->descriptor.idVendor,dev->descriptor.idProduct);
|
||||||
if(uiBusIndex == 0)
|
if (uiBusIndex == 0) {
|
||||||
{
|
|
||||||
// Open the USB device
|
// Open the USB device
|
||||||
us.pudh = usb_open(dev);
|
us.pudh = usb_open (dev);
|
||||||
|
|
||||||
get_end_points(dev,&us);
|
get_end_points (dev, &us);
|
||||||
if(usb_set_configuration(us.pudh,1) < 0)
|
if (usb_set_configuration (us.pudh, 1) < 0) {
|
||||||
{
|
DBG ("%s", "Setting config failed");
|
||||||
DBG("%s", "Setting config failed");
|
usb_close (us.pudh);
|
||||||
usb_close(us.pudh);
|
|
||||||
// we failed to use the specified device
|
// we failed to use the specified device
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(usb_claim_interface(us.pudh,0) < 0)
|
if (usb_claim_interface (us.pudh, 0) < 0) {
|
||||||
{
|
DBG ("%s", "Can't claim interface");
|
||||||
DBG("%s", "Can't claim interface");
|
usb_close (us.pudh);
|
||||||
usb_close(us.pudh);
|
|
||||||
// we failed to use the specified device
|
// we failed to use the specified device
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Allocate memory for the device info and specification, fill it and return the info
|
// Allocate memory for the device info and specification, fill it and return the info
|
||||||
pus = malloc(sizeof(usb_spec_t));
|
pus = malloc (sizeof (usb_spec_t));
|
||||||
*pus = us;
|
*pus = us;
|
||||||
pnd = malloc(sizeof(nfc_device_t));
|
pnd = malloc (sizeof (nfc_device_t));
|
||||||
strcpy(pnd->acName,target_name);
|
strcpy (pnd->acName, target_name);
|
||||||
pnd->nc = target_chip;
|
pnd->nc = target_chip;
|
||||||
pnd->nds = (nfc_device_spec_t)pus;
|
pnd->nds = (nfc_device_spec_t) pus;
|
||||||
pnd->bActive = true;
|
pnd->bActive = true;
|
||||||
pnd->bCrc = true;
|
pnd->bCrc = true;
|
||||||
pnd->bPar = true;
|
pnd->bPar = true;
|
||||||
|
@ -209,38 +200,40 @@ nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * targe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We ran out of devices before the index required
|
// We ran out of devices before the index required
|
||||||
DBG("%s","Device index not found!");
|
DBG ("%s", "Device index not found!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn53x_usb_disconnect(nfc_device_t* pnd)
|
void
|
||||||
|
pn53x_usb_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
usb_spec_t* pus = (usb_spec_t*)pnd->nds;
|
usb_spec_t *pus = (usb_spec_t *) pnd->nds;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if((ret = usb_release_interface(pus->pudh,0)) < 0) {
|
if ((ret = usb_release_interface (pus->pudh, 0)) < 0) {
|
||||||
ERR("usb_release_interface failed (%i)",ret);
|
ERR ("usb_release_interface failed (%i)", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((ret = usb_close(pus->pudh)) < 0) {
|
if ((ret = usb_close (pus->pudh)) < 0) {
|
||||||
ERR("usb_close failed (%i)",ret);
|
ERR ("usb_close failed (%i)", ret);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if((ret = usb_reset(pus->pudh)) < 0) {
|
if((ret = usb_reset(pus->pudh)) < 0) {
|
||||||
ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret));
|
ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
free(pnd->nds);
|
free (pnd->nds);
|
||||||
free(pnd);
|
free (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
size_t uiPos = 0;
|
size_t uiPos = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||||
byte_t abtRx[BUFFER_LENGTH];
|
byte_t abtRx[BUFFER_LENGTH];
|
||||||
usb_spec_t* pus = (usb_spec_t*)pnd->nds;
|
usb_spec_t *pus = (usb_spec_t *) pnd->nds;
|
||||||
// TODO: Move this one level up for libnfc-1.6
|
// TODO: Move this one level up for libnfc-1.6
|
||||||
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
||||||
|
|
||||||
|
@ -249,88 +242,81 @@ bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s
|
||||||
// Packet length checksum
|
// Packet length checksum
|
||||||
abtTx[4] = 0x0100 - abtTx[3];
|
abtTx[4] = 0x0100 - abtTx[3];
|
||||||
// Copy the PN53X command into the packet abtTx
|
// Copy the PN53X command into the packet abtTx
|
||||||
memmove(abtTx+5,pbtTx,szTxLen);
|
memmove (abtTx + 5, pbtTx, szTxLen);
|
||||||
|
|
||||||
// Calculate data payload checksum
|
// Calculate data payload checksum
|
||||||
abtTx[szTxLen+5] = 0;
|
abtTx[szTxLen + 5] = 0;
|
||||||
for(uiPos=0; uiPos < szTxLen; uiPos++)
|
for (uiPos = 0; uiPos < szTxLen; uiPos++) {
|
||||||
{
|
abtTx[szTxLen + 5] -= abtTx[uiPos + 5];
|
||||||
abtTx[szTxLen+5] -= abtTx[uiPos+5];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of stream marker
|
// End of stream marker
|
||||||
abtTx[szTxLen+6] = 0;
|
abtTx[szTxLen + 6] = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", abtTx,szTxLen+7);
|
PRINT_HEX ("TX", abtTx, szTxLen + 7);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = usb_bulk_write(pus->pudh, pus->uiEndPointOut, (char*)abtTx, szTxLen+7, USB_TIMEOUT);
|
ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTxLen + 7, USB_TIMEOUT);
|
||||||
if( ret < 0 )
|
if (ret < 0) {
|
||||||
{
|
DBG ("usb_bulk_write failed with error %d", ret);
|
||||||
DBG("usb_bulk_write failed with error %d", ret);
|
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_bulk_read(pus->pudh, pus->uiEndPointIn, (char*)abtRx, BUFFER_LENGTH, USB_TIMEOUT);
|
ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
|
||||||
if( ret < 0 )
|
if (ret < 0) {
|
||||||
{
|
DBG ("usb_bulk_read failed with error %d", ret);
|
||||||
DBG( "usb_bulk_read failed with error %d", ret);
|
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRx,ret);
|
PRINT_HEX ("RX", abtRx, ret);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRx, ret))
|
if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRx, ret))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ret = usb_bulk_read(pus->pudh, pus->uiEndPointIn, (char*)abtRx, BUFFER_LENGTH, USB_TIMEOUT);
|
ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
|
||||||
if( ret < 0 )
|
if (ret < 0) {
|
||||||
{
|
DBG ("usb_bulk_read failed with error %d", ret);
|
||||||
DBG("usb_bulk_read failed with error %d", ret);
|
|
||||||
pnd->iLastError = DEIO;
|
pnd->iLastError = DEIO;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("RX", abtRx,ret);
|
PRINT_HEX ("RX", abtRx, ret);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRINT_HEX("TX", ack_frame,6);
|
PRINT_HEX ("TX", ack_frame, 6);
|
||||||
#endif
|
#endif
|
||||||
usb_bulk_write(pus->pudh, pus->uiEndPointOut, (char *)ack_frame, 6, USB_TIMEOUT);
|
usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT);
|
||||||
|
|
||||||
if (!pn53x_transceive_check_error_frame_callback (pnd, abtRx, ret))
|
if (!pn53x_transceive_check_error_frame_callback (pnd, abtRx, ret))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// When the answer should be ignored, just return a succesful result
|
// When the answer should be ignored, just return a succesful result
|
||||||
if(pbtRx == NULL || pszRxLen == NULL) return true;
|
if (pbtRx == NULL || pszRxLen == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
||||||
if(ret < 9)
|
if (ret < 9) {
|
||||||
{
|
DBG ("%s", "No data");
|
||||||
DBG("%s","No data");
|
|
||||||
pnd->iLastError = DEINVAL;
|
pnd->iLastError = DEINVAL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
// Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
||||||
*pszRxLen = ret - 7 - 2;
|
*pszRxLen = ret - 7 - 2;
|
||||||
|
|
||||||
// Get register: nuke extra byte (awful hack)
|
// Get register: nuke extra byte (awful hack)
|
||||||
if ((abtRx[5]==0xd5) && (abtRx[6]==0x07) && (*pszRxLen==2)) {
|
if ((abtRx[5] == 0xd5) && (abtRx[6] == 0x07) && (*pszRxLen == 2)) {
|
||||||
// DBG("awful hack: abtRx[7]=%02x, abtRx[8]=%02x, we only keep abtRx[8]=%02x", abtRx[7], abtRx[8], abtRx[8]);
|
// DBG("awful hack: abtRx[7]=%02x, abtRx[8]=%02x, we only keep abtRx[8]=%02x", abtRx[7], abtRx[8], abtRx[8]);
|
||||||
*pszRxLen = (*pszRxLen) - 1;
|
*pszRxLen = (*pszRxLen) - 1;
|
||||||
memcpy( pbtRx, abtRx + 8, *pszRxLen);
|
memcpy (pbtRx, abtRx + 8, *pszRxLen);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( pbtRx, abtRx + 7, *pszRxLen);
|
memcpy (pbtRx, abtRx + 7, *pszRxLen);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
usb_dev_handle* pudh;
|
usb_dev_handle *pudh;
|
||||||
uint32_t uiEndPointIn;
|
uint32_t uiEndPointIn;
|
||||||
uint32_t uiEndPointOut;
|
uint32_t uiEndPointOut;
|
||||||
} usb_spec_t;
|
} usb_spec_t;
|
||||||
|
@ -34,8 +34,10 @@ typedef struct {
|
||||||
uint16_t idProduct;
|
uint16_t idProduct;
|
||||||
} usb_candidate_t;
|
} usb_candidate_t;
|
||||||
|
|
||||||
nfc_device_t* pn53x_usb_connect(const nfc_device_desc_t* pndd,const char * target_name, int target_chip);
|
nfc_device_t *pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip);
|
||||||
void get_end_points(struct usb_device *dev, usb_spec_t* pus);
|
void get_end_points (struct usb_device *dev, usb_spec_t * pus);
|
||||||
void pn53x_usb_disconnect(nfc_device_t* pnd);
|
void pn53x_usb_disconnect (nfc_device_t * pnd);
|
||||||
bool pn53x_usb_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen);
|
bool pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
bool pn53x_usb_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound,usb_candidate_t candidates[], int num_candidates, char * target_name);
|
size_t * pszRxLen);
|
||||||
|
bool pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound,
|
||||||
|
usb_candidate_t candidates[], int num_candidates, char *target_name);
|
||||||
|
|
|
@ -23,30 +23,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
void iso14443a_crc(byte_t* pbtData, size_t szLen, byte_t* pbtCrc)
|
void
|
||||||
|
iso14443a_crc (byte_t * pbtData, size_t szLen, byte_t * pbtCrc)
|
||||||
{
|
{
|
||||||
byte_t bt;
|
byte_t bt;
|
||||||
uint32_t wCrc = 0x6363;
|
uint32_t wCrc = 0x6363;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bt = *pbtData++;
|
bt = *pbtData++;
|
||||||
bt = (bt^(byte_t)(wCrc & 0x00FF));
|
bt = (bt ^ (byte_t) (wCrc & 0x00FF));
|
||||||
bt = (bt^(bt<<4));
|
bt = (bt ^ (bt << 4));
|
||||||
wCrc = (wCrc >> 8)^((uint32_t)bt << 8)^((uint32_t)bt<<3)^((uint32_t)bt>>4);
|
wCrc = (wCrc >> 8) ^ ((uint32_t) bt << 8) ^ ((uint32_t) bt << 3) ^ ((uint32_t) bt >> 4);
|
||||||
} while (--szLen);
|
} while (--szLen);
|
||||||
|
|
||||||
*pbtCrc++ = (byte_t) (wCrc & 0xFF);
|
*pbtCrc++ = (byte_t) (wCrc & 0xFF);
|
||||||
*pbtCrc = (byte_t) ((wCrc >> 8) & 0xFF);
|
*pbtCrc = (byte_t) ((wCrc >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_iso14443a_crc(byte_t* pbtData, size_t szLen)
|
void
|
||||||
|
append_iso14443a_crc (byte_t * pbtData, size_t szLen)
|
||||||
{
|
{
|
||||||
iso14443a_crc(pbtData, szLen, pbtData + szLen);
|
iso14443a_crc (pbtData, szLen, pbtData + szLen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -53,30 +53,33 @@ static const byte_t ByteMirror[256] = {
|
||||||
0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
byte_t mirror(byte_t bt)
|
byte_t
|
||||||
|
mirror (byte_t bt)
|
||||||
{
|
{
|
||||||
return ByteMirror[bt];
|
return ByteMirror[bt];
|
||||||
}
|
}
|
||||||
|
|
||||||
void mirror_bytes(byte_t *pbts, size_t szLen)
|
void
|
||||||
|
mirror_bytes (byte_t * pbts, size_t szLen)
|
||||||
{
|
{
|
||||||
size_t szByteNr;
|
size_t szByteNr;
|
||||||
|
|
||||||
for (szByteNr=0; szByteNr<szLen; szByteNr++)
|
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
||||||
{
|
|
||||||
*pbts = ByteMirror[*pbts];
|
*pbts = ByteMirror[*pbts];
|
||||||
pbts++;
|
pbts++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mirror32(uint32_t ui32Bits)
|
uint32_t
|
||||||
|
mirror32 (uint32_t ui32Bits)
|
||||||
{
|
{
|
||||||
mirror_bytes((byte_t*)&ui32Bits,4);
|
mirror_bytes ((byte_t *) & ui32Bits, 4);
|
||||||
return ui32Bits;
|
return ui32Bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t mirror64(uint64_t ui64Bits)
|
uint64_t
|
||||||
|
mirror64 (uint64_t ui64Bits)
|
||||||
{
|
{
|
||||||
mirror_bytes((byte_t*)&ui64Bits,8);
|
mirror_bytes ((byte_t *) & ui64Bits, 8);
|
||||||
return ui64Bits;
|
return ui64Bits;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LIBNFC_MIRROR_SUBR_H_
|
#ifndef _LIBNFC_MIRROR_SUBR_H_
|
||||||
#define _LIBNFC_MIRROR_SUBR_H_
|
# define _LIBNFC_MIRROR_SUBR_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
# include <stdint.h>
|
||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
|
||||||
byte_t mirror(byte_t bt);
|
byte_t mirror (byte_t bt);
|
||||||
uint32_t mirror32(uint32_t ui32Bits);
|
uint32_t mirror32 (uint32_t ui32Bits);
|
||||||
uint64_t mirror64(uint64_t ui64Bits);
|
uint64_t mirror64 (uint64_t ui64Bits);
|
||||||
void mirror_byte_ts(byte_t *pbts, size_t szLen);
|
void mirror_byte_ts (byte_t * pbts, size_t szLen);
|
||||||
|
|
||||||
#endif // _LIBNFC_MIRROR_SUBR_H_
|
#endif // _LIBNFC_MIRROR_SUBR_H_
|
||||||
|
|
359
libnfc/nfc.c
359
libnfc/nfc.c
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -34,9 +34,9 @@
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
|
|
||||||
#define snprintf sprintf_s
|
# define snprintf sprintf_s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "chips.h"
|
#include "chips.h"
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
nfc_device_desc_t * nfc_pick_device (void);
|
nfc_device_desc_t *nfc_pick_device (void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Probe for the first discoverable supported devices (ie. only available for some drivers)
|
* @brief Probe for the first discoverable supported devices (ie. only available for some drivers)
|
||||||
|
@ -56,12 +56,11 @@ nfc_pick_device (void)
|
||||||
uint32_t uiDriver;
|
uint32_t uiDriver;
|
||||||
nfc_device_desc_t *nddRes;
|
nfc_device_desc_t *nddRes;
|
||||||
|
|
||||||
for (uiDriver=0; uiDriver<sizeof(drivers_callbacks_list)/sizeof(drivers_callbacks_list[0]); uiDriver++)
|
for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
|
||||||
{
|
if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
|
||||||
if (drivers_callbacks_list[uiDriver].pick_device != NULL)
|
|
||||||
{
|
|
||||||
nddRes = drivers_callbacks_list[uiDriver].pick_device ();
|
nddRes = drivers_callbacks_list[uiDriver].pick_device ();
|
||||||
if (nddRes != NULL) return nddRes;
|
if (nddRes != NULL)
|
||||||
|
return nddRes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,27 +74,23 @@ nfc_pick_device (void)
|
||||||
* @param pszDeviceFound number of devices found.
|
* @param pszDeviceFound number of devices found.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
|
nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
uint32_t uiDriver;
|
uint32_t uiDriver;
|
||||||
size_t szN;
|
size_t szN;
|
||||||
|
|
||||||
*pszDeviceFound = 0;
|
*pszDeviceFound = 0;
|
||||||
|
|
||||||
for (uiDriver=0; uiDriver<sizeof(drivers_callbacks_list)/sizeof(drivers_callbacks_list[0]); uiDriver++)
|
for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
|
||||||
{
|
if (drivers_callbacks_list[uiDriver].list_devices != NULL) {
|
||||||
if (drivers_callbacks_list[uiDriver].list_devices != NULL)
|
|
||||||
{
|
|
||||||
szN = 0;
|
szN = 0;
|
||||||
if (drivers_callbacks_list[uiDriver].list_devices (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN))
|
if (drivers_callbacks_list[uiDriver].
|
||||||
{
|
list_devices (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) {
|
||||||
*pszDeviceFound += szN;
|
*pszDeviceFound += szN;
|
||||||
DBG("%ld device(s) found using %s driver", (unsigned long) szN, drivers_callbacks_list[uiDriver].acDriver);
|
DBG ("%ld device(s) found using %s driver", (unsigned long) szN, drivers_callbacks_list[uiDriver].acDriver);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
DBG ("No listing function avaible for %s driver", drivers_callbacks_list[uiDriver].acDriver);
|
||||||
{
|
|
||||||
DBG("No listing function avaible for %s driver",drivers_callbacks_list[uiDriver].acDriver);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,77 +108,83 @@ nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszD
|
||||||
* When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a nfc_device_t struct.
|
* When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a nfc_device_t struct.
|
||||||
* This pointer should be supplied by every next function of libnfc that should perform an action with this device.
|
* This pointer should be supplied by every next function of libnfc that should perform an action with this device.
|
||||||
*/
|
*/
|
||||||
nfc_device_t* nfc_connect(nfc_device_desc_t* pndd)
|
nfc_device_t *
|
||||||
|
nfc_connect (nfc_device_desc_t * pndd)
|
||||||
{
|
{
|
||||||
nfc_device_t* pnd = NULL;
|
nfc_device_t *pnd = NULL;
|
||||||
uint32_t uiDriver;
|
uint32_t uiDriver;
|
||||||
|
|
||||||
// Search through the device list for an available device
|
// Search through the device list for an available device
|
||||||
for (uiDriver=0; uiDriver<sizeof(drivers_callbacks_list)/sizeof(drivers_callbacks_list[0]); uiDriver++)
|
for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
|
||||||
{
|
if (pndd == NULL) {
|
||||||
if(pndd == NULL) {
|
|
||||||
// No device description specified: try to automatically claim a device
|
// No device description specified: try to automatically claim a device
|
||||||
if(drivers_callbacks_list[uiDriver].pick_device != NULL) {
|
if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
|
||||||
DBG("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
|
DBG ("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
|
||||||
pndd = drivers_callbacks_list[uiDriver].pick_device ();
|
pndd = drivers_callbacks_list[uiDriver].pick_device ();
|
||||||
|
|
||||||
if(pndd != NULL) {
|
if (pndd != NULL) {
|
||||||
DBG("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
|
DBG ("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
|
||||||
pnd = drivers_callbacks_list[uiDriver].connect(pndd);
|
pnd = drivers_callbacks_list[uiDriver].connect (pndd);
|
||||||
if(pnd == NULL) {
|
if (pnd == NULL) {
|
||||||
DBG("No device available using %s driver",drivers_callbacks_list[uiDriver].acDriver);
|
DBG ("No device available using %s driver", drivers_callbacks_list[uiDriver].acDriver);
|
||||||
pndd = NULL;
|
pndd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pndd);
|
free (pndd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Specific device is requested: using device description pndd
|
// Specific device is requested: using device description pndd
|
||||||
if( 0 != strcmp(drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver ) )
|
if (0 != strcmp (drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver)) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
pnd = drivers_callbacks_list[uiDriver].connect(pndd);
|
pnd = drivers_callbacks_list[uiDriver].connect (pndd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the connection was successful
|
// Test if the connection was successful
|
||||||
if (pnd != NULL)
|
if (pnd != NULL) {
|
||||||
{
|
DBG ("[%s] has been claimed.", pnd->acName);
|
||||||
DBG("[%s] has been claimed.", pnd->acName);
|
|
||||||
// Great we have claimed a device
|
// Great we have claimed a device
|
||||||
pnd->pdc = &(drivers_callbacks_list[uiDriver]);
|
pnd->pdc = &(drivers_callbacks_list[uiDriver]);
|
||||||
|
|
||||||
if (!pn53x_get_firmware_version(pnd))
|
if (!pn53x_get_firmware_version (pnd))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Reset the ending transmission bits register, it is unknown what the last tranmission used there
|
// Reset the ending transmission bits register, it is unknown what the last tranmission used there
|
||||||
if (!pn53x_set_reg(pnd,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,0x00)) return NULL;
|
if (!pn53x_set_reg (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, 0x00))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Set default configuration options
|
// Set default configuration options
|
||||||
// Make sure we reset the CRC and parity to chip handling.
|
// Make sure we reset the CRC and parity to chip handling.
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_CRC,true)) return NULL;
|
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true))
|
||||||
if (!nfc_configure(pnd,NDO_HANDLE_PARITY,true)) return NULL;
|
return NULL;
|
||||||
|
if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Deactivate the CRYPTO1 chiper, it may could cause problems when still active
|
// Deactivate the CRYPTO1 chiper, it may could cause problems when still active
|
||||||
if (!nfc_configure(pnd,NDO_ACTIVATE_CRYPTO1,false)) return NULL;
|
if (!nfc_configure (pnd, NDO_ACTIVATE_CRYPTO1, false))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Activate "easy framing" feature by default
|
// Activate "easy framing" feature by default
|
||||||
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) return NULL;
|
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Activate auto ISO14443-4 switching by default
|
// Activate auto ISO14443-4 switching by default
|
||||||
if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true)) return NULL;
|
if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Disallow invalid frame
|
// Disallow invalid frame
|
||||||
if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false)) return NULL;
|
if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Disallow multiple frames
|
// Disallow multiple frames
|
||||||
if (!nfc_configure (pnd, NDO_ACCEPT_MULTIPLE_FRAMES, false)) return NULL;
|
if (!nfc_configure (pnd, NDO_ACCEPT_MULTIPLE_FRAMES, false))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return pnd;
|
return pnd;
|
||||||
} else {
|
} else {
|
||||||
DBG("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
|
DBG ("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Too bad, no reader is ready to be claimed
|
// Too bad, no reader is ready to be claimed
|
||||||
|
@ -196,15 +197,16 @@ nfc_device_t* nfc_connect(nfc_device_desc_t* pndd)
|
||||||
*
|
*
|
||||||
* Initiator is disconnected and the device, including allocated \a nfc_device_t struct, is released.
|
* Initiator is disconnected and the device, including allocated \a nfc_device_t struct, is released.
|
||||||
*/
|
*/
|
||||||
void nfc_disconnect(nfc_device_t* pnd)
|
void
|
||||||
|
nfc_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
if(pnd) {
|
if (pnd) {
|
||||||
// Release and deselect all active communications
|
// Release and deselect all active communications
|
||||||
nfc_initiator_deselect_target(pnd);
|
nfc_initiator_deselect_target (pnd);
|
||||||
// Disable RF field to avoid heating
|
// Disable RF field to avoid heating
|
||||||
nfc_configure(pnd,NDO_ACTIVATE_FIELD,false);
|
nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
|
||||||
// Disconnect, clean up and release the device
|
// Disconnect, clean up and release the device
|
||||||
pnd->pdc->disconnect(pnd);
|
pnd->pdc->disconnect (pnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,11 +221,12 @@ void nfc_disconnect(nfc_device_t* pnd)
|
||||||
* There are different categories for configuring the PN53X chip features (handle, activate, infinite and accept).
|
* There are different categories for configuring the PN53X chip features (handle, activate, infinite and accept).
|
||||||
* These are defined to organize future settings that will become available when they are needed.
|
* These are defined to organize future settings that will become available when they are needed.
|
||||||
*/
|
*/
|
||||||
bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool bEnable)
|
bool
|
||||||
|
nfc_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_configure(pnd, ndo, bEnable);
|
return pn53x_configure (pnd, ndo, bEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,18 +239,22 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool
|
||||||
* After initialization it can be used to communicate to passive RFID tags and active NFC devices.
|
* After initialization it can be used to communicate to passive RFID tags and active NFC devices.
|
||||||
* The reader will act as initiator to communicate peer 2 peer (NFCIP) to other active NFC devices.
|
* The reader will act as initiator to communicate peer 2 peer (NFCIP) to other active NFC devices.
|
||||||
*/
|
*/
|
||||||
bool nfc_initiator_init(nfc_device_t* pnd)
|
bool
|
||||||
|
nfc_initiator_init (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
// Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
|
// Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
|
||||||
if (!pn53x_set_reg(pnd,REG_CIU_TX_AUTO,SYMBOL_FORCE_100_ASK,0x40)) return false;
|
if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_FORCE_100_ASK, 0x40))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Configure the PN53X to be an Initiator or Reader/Writer
|
// Configure the PN53X to be an Initiator or Reader/Writer
|
||||||
if (!pn53x_set_reg(pnd,REG_CIU_CONTROL,SYMBOL_INITIATOR,0x10)) return false;
|
if (!pn53x_set_reg (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -268,11 +275,15 @@ bool nfc_initiator_init(nfc_device_t* pnd)
|
||||||
* The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications.
|
* The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications.
|
||||||
* @note nfc_dep_info_t will be returned when the target was acquired successfully.
|
* @note nfc_dep_info_t will be returned when the target was acquired successfully.
|
||||||
*/
|
*/
|
||||||
bool nfc_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, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pnti)
|
bool
|
||||||
|
nfc_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,
|
||||||
|
const byte_t * pbtGbData, const size_t szGbDataLen, nfc_target_info_t * pnti)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_initiator_select_dep_target(pnd, nmInitModulation, pbtPidData, szPidDataLen, pbtNFCID3i, szNFCID3iDataLen, pbtGbData, szGbDataLen, pnti);
|
return pn53x_initiator_select_dep_target (pnd, nmInitModulation, pbtPidData, szPidDataLen, pbtNFCID3i,
|
||||||
|
szNFCID3iDataLen, pbtGbData, szGbDataLen, pnti);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -290,97 +301,95 @@ bool nfc_initiator_select_dep_target(nfc_device_t* pnd, const nfc_modulation_t n
|
||||||
* @note For every initial modulation type there is a different collection of information returned (in nfc_target_info_t pointer pti) They all fit in the data-type which is called nfc_target_info_t. This is a union which contains the tag information that belongs to the according initial modulation type.
|
* @note For every initial modulation type there is a different collection of information returned (in nfc_target_info_t pointer pti) They all fit in the data-type which is called nfc_target_info_t. This is a union which contains the tag information that belongs to the according initial modulation type.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
nfc_initiator_select_passive_target(nfc_device_t* pnd,
|
nfc_initiator_select_passive_target (nfc_device_t * pnd,
|
||||||
const nfc_modulation_t nmInitModulation,
|
const nfc_modulation_t nmInitModulation,
|
||||||
const byte_t* pbtInitData, const size_t szInitDataLen,
|
const byte_t * pbtInitData, const size_t szInitDataLen, nfc_target_info_t * pnti)
|
||||||
nfc_target_info_t* pnti)
|
|
||||||
{
|
{
|
||||||
byte_t abtInit[MAX_FRAME_LEN];
|
byte_t abtInit[MAX_FRAME_LEN];
|
||||||
size_t szInitLen;
|
size_t szInitLen;
|
||||||
|
|
||||||
size_t szTargetsData;
|
size_t szTargetsData;
|
||||||
byte_t abtTargetsData[MAX_FRAME_LEN];
|
byte_t abtTargetsData[MAX_FRAME_LEN];
|
||||||
|
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
// 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
|
// TODO Put this in a function
|
||||||
switch(nmInitModulation)
|
switch (nmInitModulation) {
|
||||||
{
|
case NM_ISO14443A_106:
|
||||||
case NM_ISO14443A_106:
|
switch (szInitDataLen) {
|
||||||
switch (szInitDataLen)
|
case 7:
|
||||||
{
|
abtInit[0] = 0x88;
|
||||||
case 7:
|
memcpy (abtInit + 1, pbtInitData, 7);
|
||||||
abtInit[0] = 0x88;
|
szInitLen = 8;
|
||||||
memcpy(abtInit+1,pbtInitData,7);
|
break;
|
||||||
szInitLen = 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
abtInit[0] = 0x88;
|
abtInit[0] = 0x88;
|
||||||
memcpy(abtInit+1,pbtInitData,3);
|
memcpy (abtInit + 1, pbtInitData, 3);
|
||||||
abtInit[4] = 0x88;
|
abtInit[4] = 0x88;
|
||||||
memcpy(abtInit+5,pbtInitData+3,7);
|
memcpy (abtInit + 5, pbtInitData + 3, 7);
|
||||||
szInitLen = 12;
|
szInitLen = 12;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
default:
|
default:
|
||||||
memcpy(abtInit,pbtInitData,szInitDataLen);
|
memcpy (abtInit, pbtInitData, szInitDataLen);
|
||||||
szInitLen = szInitDataLen;
|
szInitLen = szInitDataLen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
memcpy(abtInit,pbtInitData,szInitDataLen);
|
memcpy (abtInit, pbtInitData, szInitDataLen);
|
||||||
szInitLen = szInitDataLen;
|
szInitLen = szInitDataLen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!pn53x_InListPassiveTarget(pnd, nmInitModulation, 1, abtInit, szInitLen, abtTargetsData, &szTargetsData)) return false;
|
if (!pn53x_InListPassiveTarget (pnd, nmInitModulation, 1, abtInit, szInitLen, abtTargetsData, &szTargetsData))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Make sure one tag has been found, the PN53X returns 0x00 if none was available
|
// Make sure one tag has been found, the PN53X returns 0x00 if none was available
|
||||||
if (abtTargetsData[0] == 0) return false;
|
if (abtTargetsData[0] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Is a tag info struct available
|
// Is a tag info struct available
|
||||||
if (pnti)
|
if (pnti) {
|
||||||
{
|
|
||||||
// Fill the tag info struct with the values corresponding to this init modulation
|
// Fill the tag info struct with the values corresponding to this init modulation
|
||||||
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)) {
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_GENERIC_PASSIVE_106, pnti)) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_FELICA_212:
|
case NM_FELICA_212:
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_212, pnti)) {
|
if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_FELICA_212, pnti)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NM_FELICA_424:
|
case NM_FELICA_424:
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_FELICA_424, pnti)) {
|
if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_FELICA_424, pnti)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_ISO14443B_106:
|
case NM_ISO14443B_106:
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_ISO14443B_106, pnti)) {
|
if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_ISO14443B_106, pnti)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NM_JEWEL_106:
|
case NM_JEWEL_106:
|
||||||
if(!pn53x_decode_target_data(abtTargetsData+1, szTargetsData-1, pnd->nc, NTT_JEWEL_106, pnti)) {
|
if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_JEWEL_106, pnti)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Should not be possible, so whatever...
|
// Should not be possible, so whatever...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,28 +397,29 @@ nfc_initiator_select_passive_target(nfc_device_t* pnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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_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;
|
||||||
size_t szTargetFound = 0;
|
size_t szTargetFound = 0;
|
||||||
byte_t* pbtInitData = NULL;
|
byte_t *pbtInitData = NULL;
|
||||||
size_t szInitDataLen = 0;
|
size_t szInitDataLen = 0;
|
||||||
|
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
if(nmInitModulation == NM_ISO14443B_106) {
|
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)
|
// Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
|
||||||
pbtInitData = (byte_t*)"\x00";
|
pbtInitData = (byte_t *) "\x00";
|
||||||
szInitDataLen = 1;
|
szInitDataLen = 1;
|
||||||
}
|
}
|
||||||
while (nfc_initiator_select_passive_target (pnd, nmInitModulation, pbtInitData, szInitDataLen, &nti)) {
|
while (nfc_initiator_select_passive_target (pnd, nmInitModulation, pbtInitData, szInitDataLen, &nti)) {
|
||||||
nfc_initiator_deselect_target(pnd);
|
nfc_initiator_deselect_target (pnd);
|
||||||
|
|
||||||
if(szTargets > szTargetFound) {
|
if (szTargets > szTargetFound) {
|
||||||
memcpy( &(anti[szTargetFound]), &nti, sizeof(nfc_target_info_t) );
|
memcpy (&(anti[szTargetFound]), &nti, sizeof (nfc_target_info_t));
|
||||||
}
|
}
|
||||||
szTargetFound++;
|
szTargetFound++;
|
||||||
}
|
}
|
||||||
|
@ -425,11 +435,12 @@ nfc_initiator_list_passive_targets(nfc_device_t* pnd, const nfc_modulation_t nmI
|
||||||
*
|
*
|
||||||
* After selecting and communicating with a passive tag, this function could be used to deactivate and release the tag. This is very useful when there are multiple tags available in the field. It is possible to use the nfc_initiator_select_passive_target() function to select the first available tag, test it for the available features and support, deselect it and skip to the next tag until the correct tag is found.
|
* After selecting and communicating with a passive tag, this function could be used to deactivate and release the tag. This is very useful when there are multiple tags available in the field. It is possible to use the nfc_initiator_select_passive_target() function to select the first available tag, test it for the available features and support, deselect it and skip to the next tag until the correct tag is found.
|
||||||
*/
|
*/
|
||||||
bool nfc_initiator_deselect_target(nfc_device_t* pnd)
|
bool
|
||||||
|
nfc_initiator_deselect_target (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return (pn53x_InDeselect(pnd, 0)); // 0 mean deselect all selected targets
|
return (pn53x_InDeselect (pnd, 0)); // 0 mean deselect all selected targets
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -444,14 +455,14 @@ bool nfc_initiator_deselect_target(nfc_device_t* pnd)
|
||||||
* @param pszTargetFound found targets count
|
* @param pszTargetFound found targets count
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
nfc_initiator_poll_targets(nfc_device_t* pnd,
|
nfc_initiator_poll_targets (nfc_device_t * pnd,
|
||||||
const nfc_target_type_t* pnttTargetTypes, const size_t szTargetTypes,
|
const nfc_target_type_t * pnttTargetTypes, const size_t szTargetTypes,
|
||||||
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)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_InAutoPoll(pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
|
return pn53x_InAutoPoll (pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -466,7 +477,9 @@ nfc_initiator_poll_targets(nfc_device_t* pnd,
|
||||||
*
|
*
|
||||||
* The NFC reader will transmit low-level messages where only the modulation is handled by the PN53X chip. Construction of the frame (data, CRC and parity) is completely done by libnfc. This can be very useful for testing purposes. Some protocols (e.g. MIFARE Classic) require to violate the ISO14443-A standard by sending incorrect parity and CRC bytes. Using this feature you are able to simulate these frames.
|
* The NFC reader will transmit low-level messages where only the modulation is handled by the PN53X chip. Construction of the frame (data, CRC and parity) is completely done by libnfc. This can be very useful for testing purposes. Some protocols (e.g. MIFARE Classic) require to violate the ISO14443-A standard by sending incorrect parity and CRC bytes. Using this feature you are able to simulate these frames.
|
||||||
*/
|
*/
|
||||||
bool nfc_initiator_transceive_bits(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)
|
bool
|
||||||
|
nfc_initiator_transceive_bits (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)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
|
@ -486,7 +499,9 @@ bool nfc_initiator_transceive_bits(nfc_device_t* pnd, const byte_t* pbtTx, const
|
||||||
*
|
*
|
||||||
* @warning The configuration option NDO_HANDLE_PARITY must be set to true (the default value).
|
* @warning The configuration option NDO_HANDLE_PARITY must be set to true (the default value).
|
||||||
*/
|
*/
|
||||||
bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
nfc_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
|
||||||
|
size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
|
@ -501,11 +516,12 @@ bool nfc_initiator_transceive_bytes(nfc_device_t* pnd, const byte_t* pbtTx, cons
|
||||||
*
|
*
|
||||||
* @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used.
|
* @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used.
|
||||||
*/
|
*/
|
||||||
bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits)
|
bool
|
||||||
|
nfc_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_target_init(pnd, pbtRx, pszRxBits);
|
return pn53x_target_init (pnd, pbtRx, pszRxBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -514,7 +530,8 @@ bool nfc_target_init(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits)
|
||||||
*
|
*
|
||||||
* This function makes it possible to receive (raw) bit-frames. It returns all the messages that are stored in the FIFO buffer of the PN53X chip. It does not require to send any frame and thereby could be used to snoop frames that are transmitted by a nearby reader. Check out the NDO_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted frames.
|
* This function makes it possible to receive (raw) bit-frames. It returns all the messages that are stored in the FIFO buffer of the PN53X chip. It does not require to send any frame and thereby could be used to snoop frames that are transmitted by a nearby reader. Check out the NDO_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted frames.
|
||||||
*/
|
*/
|
||||||
bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar)
|
bool
|
||||||
|
nfc_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
|
@ -527,11 +544,12 @@ bool nfc_target_receive_bits(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits
|
||||||
*
|
*
|
||||||
* The main receive function that returns the received frames from a nearby reader.
|
* The main receive function that returns the received frames from a nearby reader.
|
||||||
*/
|
*/
|
||||||
bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen)
|
bool
|
||||||
|
nfc_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_target_receive_bytes(pnd, pbtRx, pszRxLen);
|
return pn53x_target_receive_bytes (pnd, pbtRx, pszRxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -540,11 +558,12 @@ bool nfc_target_receive_bytes(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen
|
||||||
*
|
*
|
||||||
* This function can be used to transmit (raw) bit-frames to the reader.
|
* This function can be used to transmit (raw) bit-frames to the reader.
|
||||||
*/
|
*/
|
||||||
bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar)
|
bool
|
||||||
|
nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
return pn53x_target_send_bits(pnd, pbtTx, szTxBits, pbtTxPar);
|
return pn53x_target_send_bits (pnd, pbtTx, szTxBits, pbtTxPar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -554,7 +573,8 @@ bool nfc_target_send_bits(nfc_device_t* pnd, const byte_t* pbtTx, const size_t s
|
||||||
*
|
*
|
||||||
* To communicate byte frames and APDU responses to the reader, this function could be used.
|
* To communicate byte frames and APDU responses to the reader, this function could be used.
|
||||||
*/
|
*/
|
||||||
bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen)
|
bool
|
||||||
|
nfc_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen)
|
||||||
{
|
{
|
||||||
pnd->iLastError = 0;
|
pnd->iLastError = 0;
|
||||||
|
|
||||||
|
@ -565,7 +585,8 @@ bool nfc_target_send_bytes(nfc_device_t* pnd, const byte_t* pbtTx, const size_t
|
||||||
* @brief Return the PCD error string
|
* @brief Return the PCD error string
|
||||||
* @return Returns a string
|
* @return Returns a string
|
||||||
*/
|
*/
|
||||||
const char *nfc_strerror (const nfc_device_t *pnd)
|
const char *
|
||||||
|
nfc_strerror (const nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
return pnd->pdc->pcc->strerror (pnd);
|
return pnd->pdc->pcc->strerror (pnd);
|
||||||
}
|
}
|
||||||
|
@ -574,7 +595,8 @@ const char *nfc_strerror (const nfc_device_t *pnd)
|
||||||
* @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen chars
|
* @brief Renders the PCD error in pcStrErrBuf for a maximum size of szBufLen chars
|
||||||
* @return Returns 0 upon success
|
* @return Returns 0 upon success
|
||||||
*/
|
*/
|
||||||
int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen)
|
int
|
||||||
|
nfc_strerror_r (const nfc_device_t * pnd, char *pcStrErrBuf, size_t szBufLen)
|
||||||
{
|
{
|
||||||
return (snprintf (pcStrErrBuf, szBufLen, "%s", nfc_strerror (pnd)) < 0) ? -1 : 0;
|
return (snprintf (pcStrErrBuf, szBufLen, "%s", nfc_strerror (pnd)) < 0) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +604,8 @@ int nfc_strerror_r (const nfc_device_t *pnd, char *pcStrErrBuf, size_t szBufLen)
|
||||||
/**
|
/**
|
||||||
* @brief Display the PCD error a-la perror
|
* @brief Display the PCD error a-la perror
|
||||||
*/
|
*/
|
||||||
void nfc_perror (const nfc_device_t *pnd, const char *pcString)
|
void
|
||||||
|
nfc_perror (const nfc_device_t * pnd, const char *pcString)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s: %s\n", pcString, nfc_strerror (pnd));
|
fprintf (stderr, "%s: %s\n", pcString, nfc_strerror (pnd));
|
||||||
}
|
}
|
||||||
|
@ -593,7 +616,8 @@ 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
|
* @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)
|
||||||
{
|
{
|
||||||
return pnd->acName;
|
return pnd->acName;
|
||||||
}
|
}
|
||||||
|
@ -604,11 +628,12 @@ const char* nfc_device_name(nfc_device_t* pnd)
|
||||||
* @brief Returns the library version
|
* @brief Returns the library version
|
||||||
* @return Returns a string with the library version
|
* @return Returns a string with the library version
|
||||||
*/
|
*/
|
||||||
const char* nfc_version(void)
|
const char *
|
||||||
|
nfc_version (void)
|
||||||
{
|
{
|
||||||
#ifdef SVN_REVISION
|
#ifdef SVN_REVISION
|
||||||
return PACKAGE_VERSION" (r"SVN_REVISION")";
|
return PACKAGE_VERSION " (r" SVN_REVISION ")";
|
||||||
#else
|
#else
|
||||||
return PACKAGE_VERSION;
|
return PACKAGE_VERSION;
|
||||||
#endif // SVN_REVISION
|
#endif // SVN_REVISION
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue