Add ISO/IEC 14443 B' aka Type B' modulation partial support
This commit is contained in:
parent
77e522aade
commit
cd6946e751
7 changed files with 172 additions and 1 deletions
|
@ -185,6 +185,20 @@ main (int argc, const char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
nm.nmt = NMT_ISO14443BI;
|
||||
nm.nbr = NBR_106;
|
||||
// List ISO14443B' targets
|
||||
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
|
||||
size_t n;
|
||||
if (verbose || (szTargetFound > 0)) {
|
||||
printf ("%d ISO14443B' passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
|
||||
}
|
||||
for (n = 0; n < szTargetFound; n++) {
|
||||
print_nfc_iso14443bi_info (ant[n].nti.nii, verbose);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
nm.nmt = NMT_JEWEL;
|
||||
nm.nbr = NBR_106;
|
||||
// List Jewel targets
|
||||
|
|
|
@ -607,6 +607,30 @@ print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose)
|
||||
{
|
||||
printf (" DIV: ");
|
||||
print_hex (nii.abtDIV, 4);
|
||||
if (verbose) {
|
||||
int version = (nii.btVerLog & 0x1e)>>1;
|
||||
printf (" Software Version: ");
|
||||
if (version == 15) {
|
||||
printf ("Undefined\n");
|
||||
} else {
|
||||
printf ("%i\n", version);
|
||||
}
|
||||
|
||||
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x80)){
|
||||
printf (" Wait Enable: yes");
|
||||
}
|
||||
}
|
||||
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) {
|
||||
printf (" ATS: ");
|
||||
print_hex (nii.abtAtr, nii.szAtrLen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
|
||||
{
|
||||
|
@ -712,6 +736,10 @@ print_nfc_target (const nfc_target_t nt, bool verbose)
|
|||
printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||
print_nfc_iso14443b_info (nt.nti.nbi, verbose);
|
||||
break;
|
||||
case NMT_ISO14443BI:
|
||||
printf ("ISO/IEC 14443-4B' (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||
print_nfc_iso14443bi_info (nt.nti.nii, verbose);
|
||||
break;
|
||||
case NMT_DEP:
|
||||
printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
||||
print_nfc_dep_info (nt.nti.ndi, verbose);
|
||||
|
|
|
@ -88,6 +88,7 @@ void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t
|
|||
|
||||
void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose);
|
||||
void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose);
|
||||
void print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose);
|
||||
void print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose);
|
||||
void print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose);
|
||||
void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose);
|
||||
|
|
|
@ -147,6 +147,10 @@ typedef enum {
|
|||
NDO_EASY_FRAMING = 0x41,
|
||||
/** Force the chip to switch in ISO14443-A */
|
||||
NDO_FORCE_ISO14443_A = 0x42,
|
||||
/** Force the chip to switch in ISO14443-B */
|
||||
NDO_FORCE_ISO14443_B = 0x43,
|
||||
/** Force the chip to run at 106 kbps */
|
||||
NDO_FORCE_SPEED_106 = 0x50,
|
||||
} nfc_device_option_t;
|
||||
|
||||
/**
|
||||
|
@ -223,6 +227,22 @@ typedef struct {
|
|||
uint8_t ui8CardIdentifier;
|
||||
} nfc_iso14443b_info_t;
|
||||
|
||||
/**
|
||||
* @struct nfc_iso14443bi_info_t
|
||||
* @brief NFC ISO14443B' tag information
|
||||
*/
|
||||
typedef struct {
|
||||
/** DIV: 4 LSBytes of tag serial number */
|
||||
byte_t abtDIV[4];
|
||||
/** Software version & type of REPGEN */
|
||||
byte_t btVerLog;
|
||||
/** Config Byte, present if long REPGEN */
|
||||
byte_t btConfig;
|
||||
/** ATR, if any */
|
||||
size_t szAtrLen;
|
||||
byte_t abtAtr[33];
|
||||
} nfc_iso14443bi_info_t;
|
||||
|
||||
/**
|
||||
* @struct nfc_jewel_info_t
|
||||
* @brief NFC Jewel tag information
|
||||
|
@ -240,6 +260,7 @@ typedef union {
|
|||
nfc_iso14443a_info_t nai;
|
||||
nfc_felica_info_t nfi;
|
||||
nfc_iso14443b_info_t nbi;
|
||||
nfc_iso14443bi_info_t nii;
|
||||
nfc_jewel_info_t nji;
|
||||
nfc_dep_info_t ndi;
|
||||
} nfc_target_info_t;
|
||||
|
@ -263,6 +284,7 @@ typedef enum {
|
|||
typedef enum {
|
||||
NMT_ISO14443A,
|
||||
NMT_ISO14443B,
|
||||
NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B'
|
||||
NMT_FELICA,
|
||||
NMT_JEWEL,
|
||||
NMT_DEP,
|
||||
|
|
|
@ -368,6 +368,27 @@ pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, pn53x_typ
|
|||
}
|
||||
break;
|
||||
|
||||
case NMT_ISO14443BI:
|
||||
// Skip V & T Addresses
|
||||
pbtRawData++;
|
||||
if (*pbtRawData != 0x07) { // 0x07 = REPGEN
|
||||
return false;
|
||||
}
|
||||
pbtRawData++;
|
||||
// Store the UID
|
||||
memcpy (pnti->nii.abtDIV, pbtRawData, 4);
|
||||
pbtRawData += 4;
|
||||
pnti->nii.btVerLog = *(pbtRawData++);
|
||||
if (pnti->nii.btVerLog & 0x80) { // Type = long?
|
||||
pnti->nii.btConfig = *(pbtRawData++);
|
||||
if (pnti->nii.btConfig & 0x40) {
|
||||
memcpy (pnti->nii.abtAtr, pbtRawData, szRawData - 8);
|
||||
pbtRawData += szRawData - 6;
|
||||
pnti->nii.szAtrLen = szRawData - 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NMT_FELICA:
|
||||
// We skip the first byte: its the target number (Tg)
|
||||
pbtRawData++;
|
||||
|
@ -588,6 +609,40 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
|
|||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case NDO_FORCE_ISO14443_B:
|
||||
if(!bEnable) {
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
// Force pn53x to be in ISO14443-B mode
|
||||
if (!pn53x_write_register (pnd, REG_CIU_TX_MODE, SYMBOL_TX_FRAMING, 0x03)) {
|
||||
return false;
|
||||
}
|
||||
if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_FRAMING, 0x03)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case NDO_FORCE_SPEED_106:
|
||||
if(!bEnable) {
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
// Force pn53x to be at 106 kbps
|
||||
if (!pn53x_write_register (pnd, REG_CIU_TX_MODE, SYMBOL_TX_SPEED, 0x00)) {
|
||||
return false;
|
||||
}
|
||||
if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_SPEED, 0x00)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO not yet sufficient to setup TypeB, some settings are missing here...
|
||||
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
// When we reach this, the configuration is completed and succesful
|
||||
|
@ -628,11 +683,44 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
|
|||
byte_t abtTargetsData[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
|
||||
size_t szTargetsData = sizeof(abtTargetsData);
|
||||
|
||||
if (nm.nmt == NMT_ISO14443BI) {
|
||||
// No native support in InListPassiveTarget so we do discovery by hand
|
||||
byte_t abtAttrib[6];
|
||||
size_t szAttrib = sizeof(abtAttrib);
|
||||
if (!nfc_configure (pnd, NDO_FORCE_ISO14443_B, true)) {
|
||||
return false;
|
||||
}
|
||||
if (!nfc_configure (pnd, NDO_FORCE_SPEED_106, true)) {
|
||||
return false;
|
||||
}
|
||||
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
|
||||
return false;
|
||||
}
|
||||
pnd->bEasyFraming = false;
|
||||
if (!pn53x_initiator_transceive_bytes (pnd, pbtInitData, szInitData, abtTargetsData, &szTargetsData)) {
|
||||
return false;
|
||||
}
|
||||
if (pnt) {
|
||||
pnt->nm = nm;
|
||||
// Fill the tag info struct with the values corresponding to this init modulation
|
||||
if (!pn53x_decode_target_data (abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(pnt->nti))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memcpy(abtAttrib, abtTargetsData, szAttrib);
|
||||
abtAttrib[1] = 0x0f; // ATTRIB
|
||||
if (!pn53x_initiator_transceive_bytes (pnd, abtAttrib, szAttrib, NULL, NULL)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // else:
|
||||
|
||||
const pn53x_modulation_t pm = pn53x_nm_to_pm(nm);
|
||||
if (PM_UNDEFINED == pm) {
|
||||
pnd->iLastError = DENOTSUP;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pn53x_InListPassiveTarget (pnd, pm, 1, pbtInitData, szInitData, abtTargetsData, &szTargetsData))
|
||||
return false;
|
||||
|
||||
|
@ -1048,6 +1136,7 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
|
|||
}
|
||||
break;
|
||||
case NMT_ISO14443B:
|
||||
case NMT_ISO14443BI:
|
||||
case NMT_JEWEL:
|
||||
pnd->iLastError = DENOTSUP;
|
||||
return false;
|
||||
|
@ -1147,6 +1236,7 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
|
|||
pbtFeliCaParams = abtFeliCaParams;
|
||||
break;
|
||||
case NMT_ISO14443B:
|
||||
case NMT_ISO14443BI:
|
||||
case NMT_JEWEL:
|
||||
pnd->iLastError = DENOTSUP;
|
||||
return false;
|
||||
|
@ -1925,6 +2015,8 @@ pn53x_nm_to_pm(const nfc_modulation_t nm)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NMT_ISO14443BI:
|
||||
case NMT_DEP:
|
||||
// Nothing to do...
|
||||
break;
|
||||
|
@ -2024,6 +2116,7 @@ pn53x_nm_to_ptt(const nfc_modulation_t nm)
|
|||
}
|
||||
break;
|
||||
|
||||
case NMT_ISO14443BI:
|
||||
case NMT_DEP:
|
||||
// Nothing to do...
|
||||
break;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
// Registers and symbols masks used to covers parts within a register
|
||||
# define REG_CIU_TX_MODE 0x6302
|
||||
# define SYMBOL_TX_CRC_ENABLE 0x80
|
||||
# define SYMBOL_TX_SPEED 0x70
|
||||
// TX_FRAMING bits explanation:
|
||||
// 00 : ISO/IEC 14443A/MIFARE and Passive Communication mode 106 kbit/s
|
||||
// 01 : Active Communication mode
|
||||
|
@ -46,6 +47,7 @@
|
|||
|
||||
# define REG_CIU_RX_MODE 0x6303
|
||||
# define SYMBOL_RX_CRC_ENABLE 0x80
|
||||
# define SYMBOL_RX_SPEED 0x70
|
||||
# define SYMBOL_RX_NO_ERROR 0x08
|
||||
# define SYMBOL_RX_MULTIPLE 0x04
|
||||
// RX_FRAMING follow same scheme than TX_FRAMING
|
||||
|
|
13
libnfc/nfc.c
13
libnfc/nfc.c
|
@ -83,6 +83,7 @@ const struct nfc_driver_t *nfc_drivers[] = {
|
|||
* - Invalid frames are not accepted (NDO_ACCEPT_INVALID_FRAMES = false)
|
||||
* - Multiple frames are not accepted (NDO_ACCEPT_MULTIPLE_FRAMES = false)
|
||||
* - 14443-A mode is activated (NDO_FORCE_ISO14443_A = true)
|
||||
* - speed is set to 106 kbps (NDO_FORCE_SPEED_106 = true)
|
||||
* - Let the device try forever to find a target (NDO_INFINITE_SELECT = true)
|
||||
* - RF field is shortly dropped (if it was enabled) then activated again
|
||||
*/
|
||||
|
@ -241,6 +242,9 @@ nfc_initiator_init (nfc_device_t * pnd)
|
|||
// Force 14443-A mode
|
||||
if (!nfc_configure (pnd, NDO_FORCE_ISO14443_A, true))
|
||||
return false;
|
||||
// Force speed at 106kbps
|
||||
if (!nfc_configure (pnd, NDO_FORCE_SPEED_106, true))
|
||||
return false;
|
||||
// Disallow invalid frame
|
||||
if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false))
|
||||
return false;
|
||||
|
@ -376,6 +380,12 @@ nfc_initiator_list_passive_targets (nfc_device_t * pnd,
|
|||
szInitDataLen = 1;
|
||||
}
|
||||
break;
|
||||
case NMT_ISO14443BI: {
|
||||
// APGEN
|
||||
pbtInitData = (byte_t *) "\x01\x0b\x3f\x80";
|
||||
szInitDataLen = 4;
|
||||
}
|
||||
break;
|
||||
case NMT_FELICA: {
|
||||
// polling payload must be present (see ISO/IEC 18092 11.2.2.5)
|
||||
pbtInitData = (byte_t *) "\x00\xff\xff\x01\x00";
|
||||
|
@ -396,7 +406,8 @@ nfc_initiator_list_passive_targets (nfc_device_t * pnd,
|
|||
}
|
||||
szTargetFound++;
|
||||
// deselect has no effect on FeliCa and Jewel cards so we'll stop after one...
|
||||
if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL)) {
|
||||
// ISO/IEC 14443 B' cards are polled at 100% probability so it's not possible to detect correctly two cards at the same time
|
||||
if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL) || (nm.nmt == NMT_ISO14443BI)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue