Add software polling for non-PN532 equipped device (Fixes Issue 136)

This commit is contained in:
Romuald Conty 2011-10-03 11:19:08 +00:00
parent 66e3ea6146
commit dccfd65c80
14 changed files with 215 additions and 118 deletions

View file

@ -15,7 +15,9 @@ libnfc_la_SOURCES = \
mirror-subr.c \
nfc.c \
nfc-device.c \
nfc-emulation.c
nfc-emulation.c \
nfc-internal.c
libnfc_la_LDFLAGS = -no-undefined -version-info 2:0:0
libnfc_la_CFLAGS = @DRIVERS_CFLAGS@
libnfc_la_LIBADD = \

View file

@ -61,8 +61,6 @@ pn53x_target_type_t pn53x_nm_to_ptt (const nfc_modulation_t nm);
bool
pn53x_init(nfc_device_t * pnd)
{
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "pn53x_init");
// GetFirmwareVersion command is used to set PN53x chips type (PN531, PN532 or PN533)
char abtFirmwareText[22];
if (!pn53x_get_firmware_version (pnd, abtFirmwareText)) {
@ -111,6 +109,9 @@ pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, b
}
PNCMD_TRACE (pbtTx[0]);
if (timeout)
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Timeout values: %li s, %li us", timeout->tv_sec, timeout->tv_usec);
byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
size_t szRx = sizeof(abtRx);
@ -855,10 +856,11 @@ pn53x_initiator_init (nfc_device_t * pnd)
}
bool
pn53x_initiator_select_passive_target (nfc_device_t * pnd,
pn53x_initiator_select_passive_target_ext (nfc_device_t * pnd,
const nfc_modulation_t nm,
const byte_t * pbtInitData, const size_t szInitData,
nfc_target_t * pnt)
nfc_target_t * pnt,
struct timeval* timeout)
{
byte_t abtTargetsData[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
size_t szTargetsData = sizeof(abtTargetsData);
@ -889,11 +891,11 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
byte_t abtRx[1];
size_t szRxLen = 1;
// Getting random Chip_ID
if (!pn53x_initiator_transceive_bytes (pnd, abtInitiate, szInitiateLen, abtRx, &szRxLen, NULL)) {
if (!pn53x_initiator_transceive_bytes (pnd, abtInitiate, szInitiateLen, abtRx, &szRxLen, timeout)) {
return false;
}
abtSelect[1] = abtRx[0];
if (!pn53x_initiator_transceive_bytes (pnd, abtSelect, szSelectLen, abtRx, &szRxLen, NULL)) {
if (!pn53x_initiator_transceive_bytes (pnd, abtSelect, szSelectLen, abtRx, &szRxLen, timeout)) {
return false;
}
}
@ -902,11 +904,11 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
byte_t abtReqt[]="\x10";
size_t szReqtLen = 1;
// Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later
if (!pn53x_initiator_transceive_bytes (pnd, abtReqt, szReqtLen, abtTargetsData+2, &szTargetsData, NULL) || szTargetsData != 2) {
if (!pn53x_initiator_transceive_bytes (pnd, abtReqt, szReqtLen, abtTargetsData+2, &szTargetsData, timeout) || szTargetsData != 2) {
return false;
}
}
if (!pn53x_initiator_transceive_bytes (pnd, pbtInitData, szInitData, abtTargetsData, &szTargetsData, NULL)) {
if (!pn53x_initiator_transceive_bytes (pnd, pbtInitData, szInitData, abtTargetsData, &szTargetsData, timeout)) {
return false;
}
if (nm.nmt == NMT_ISO14443B2CT) {
@ -914,7 +916,7 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
return false;
byte_t abtRead[]="\xC4"; // Reading UID_MSB (Read address 4)
size_t szReadLen = 1;
if (!pn53x_initiator_transceive_bytes (pnd, abtRead, szReadLen, abtTargetsData+4, &szTargetsData, NULL) || szTargetsData != 2) {
if (!pn53x_initiator_transceive_bytes (pnd, abtRead, szReadLen, abtTargetsData+4, &szTargetsData, timeout) || szTargetsData != 2) {
return false;
}
szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB
@ -932,7 +934,7 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
size_t szAttribLen = sizeof(abtAttrib);
memcpy(abtAttrib, abtTargetsData, szAttribLen);
abtAttrib[1] = 0x0f; // ATTRIB
if (!pn53x_initiator_transceive_bytes (pnd, abtAttrib, szAttribLen, NULL, NULL, NULL)) {
if (!pn53x_initiator_transceive_bytes (pnd, abtAttrib, szAttribLen, NULL, NULL, timeout)) {
return false;
}
}
@ -945,7 +947,7 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
return false;
}
if (!pn53x_InListPassiveTarget (pnd, pm, 1, pbtInitData, szInitData, abtTargetsData, &szTargetsData))
if (!pn53x_InListPassiveTarget (pnd, pm, 1, pbtInitData, szInitData, abtTargetsData, &szTargetsData, timeout))
return false;
// Make sure one tag has been found, the PN53X returns 0x00 if none was available
@ -964,29 +966,76 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
}
bool
pn53x_initiator_poll_targets (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const byte_t btPollNr, const byte_t btPeriod,
nfc_target_t * pntTargets, size_t * pszTargetFound)
pn53x_initiator_select_passive_target (nfc_device_t * pnd,
const nfc_modulation_t nm,
const byte_t * pbtInitData, const size_t szInitData,
nfc_target_t * pnt)
{
size_t szTargetTypes = 0;
pn53x_target_type_t apttTargetTypes[32];
for (size_t n=0; n<szModulations; n++) {
const pn53x_target_type_t ptt = pn53x_nm_to_ptt(pnmModulations[n]);
if (PTT_UNDEFINED == ptt) {
pnd->iLastError = EINVALARG;
return false;
}
apttTargetTypes[szTargetTypes] = ptt;
if ((pnd->bAutoIso14443_4) && (ptt == PTT_MIFARE)) { // Hack to have ATS
apttTargetTypes[szTargetTypes] = PTT_ISO14443_4A_106;
szTargetTypes++;
apttTargetTypes[szTargetTypes] = PTT_MIFARE;
}
szTargetTypes++;
}
return pn53x_initiator_select_passive_target_ext (pnd, nm, pbtInitData, szInitData, pnt, NULL);
}
return pn53x_InAutoPoll (pnd, apttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
bool
pn53x_initiator_poll_target (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const uint8_t uiPollNr, const uint8_t uiPeriod,
nfc_target_t * pnt)
{
if (CHIP_DATA(pnd)->type == PN532) {
size_t szTargetTypes = 0;
pn53x_target_type_t apttTargetTypes[32];
for (size_t n=0; n<szModulations; n++) {
const pn53x_target_type_t ptt = pn53x_nm_to_ptt(pnmModulations[n]);
if (PTT_UNDEFINED == ptt) {
pnd->iLastError = EINVALARG;
return false;
}
apttTargetTypes[szTargetTypes] = ptt;
if ((pnd->bAutoIso14443_4) && (ptt == PTT_MIFARE)) { // Hack to have ATS
apttTargetTypes[szTargetTypes] = PTT_ISO14443_4A_106;
szTargetTypes++;
apttTargetTypes[szTargetTypes] = PTT_MIFARE;
}
szTargetTypes++;
}
size_t szTargetFound = 0;
nfc_target_t ntTargets[2];
if (!pn53x_InAutoPoll (pnd, apttTargetTypes, szTargetTypes, uiPollNr, uiPeriod, ntTargets, &szTargetFound))
return false;
switch (szTargetFound) {
case 1:
*pnt = ntTargets[0];
return true;
break;
case 2:
*pnt = ntTargets[1]; // We keep the selected one
return true;
break;
default:
return false;
break;
}
} else {
pn53x_configure (pnd, NDO_INFINITE_SELECT, true);
for (size_t p=0; p<uiPollNr; p++) {
for (size_t n=0; n<szModulations; n++) {
byte_t *pbtInitiatorData;
size_t szInitiatorData;
prepare_initiator_data (pnmModulations[n], &pbtInitiatorData, &szInitiatorData);
const int timeout_ms = uiPeriod * 150;
struct timeval timeout;
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms - (timeout.tv_sec * 1000)) * 1000;
if (!pn53x_initiator_select_passive_target_ext (pnd, pnmModulations[n], pbtInitiatorData, szInitiatorData, pnt, &timeout)) {
if (pnd->iLastError != ECOMTIMEOUT)
return false;
} else {
return true;
}
}
}
}
return false;
}
bool
@ -1992,7 +2041,8 @@ bool
pn53x_InListPassiveTarget (nfc_device_t * pnd,
const pn53x_modulation_t pmInitModulation, const byte_t szMaxTargets,
const byte_t * pbtInitiatorData, const size_t szInitiatorData,
byte_t * pbtTargetsData, size_t * pszTargetsData)
byte_t * pbtTargetsData, size_t * pszTargetsData,
struct timeval* timeout)
{
byte_t abtCmd[15] = { InListPassiveTarget };
@ -2037,7 +2087,7 @@ pn53x_InListPassiveTarget (nfc_device_t * pnd,
if (pbtInitiatorData)
memcpy (abtCmd + 3, pbtInitiatorData, szInitiatorData);
return pn53x_transceive (pnd, abtCmd, 3 + szInitiatorData, pbtTargetsData, pszTargetsData, NULL);
return pn53x_transceive (pnd, abtCmd, 3 + szInitiatorData, pbtTargetsData, pszTargetsData, timeout);
}
bool

View file

@ -280,10 +280,10 @@ bool pn53x_initiator_select_passive_target (nfc_device_t * pnd,
const nfc_modulation_t nm,
const byte_t * pbtInitData, const size_t szInitData,
nfc_target_t * pnt);
bool pn53x_initiator_poll_targets (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const byte_t btPollNr, const byte_t btPeriod,
nfc_target_t * pntTargets, size_t * pszTargetFound);
bool pn53x_initiator_poll_target (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const uint8_t uiPollNr, const uint8_t uiPeriod,
nfc_target_t * pnt);
bool pn53x_initiator_select_dep_target (nfc_device_t * pnd,
const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr,
const nfc_dep_info_t * pndiInitiator,
@ -304,8 +304,7 @@ bool pn53x_initiator_deselect_target (nfc_device_t * pnd);
bool pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx);
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 * pszRx, struct timeval *timeout);
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, const byte_t * pbtTxPar);
bool pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout);
// Error handling functions
@ -317,7 +316,8 @@ bool pn53x_SAMConfiguration (nfc_device_t * pnd, const pn532_sam_mode mode, s
bool pn53x_PowerDown (nfc_device_t * pnd);
bool pn53x_InListPassiveTarget (nfc_device_t * pnd, const pn53x_modulation_t pmInitModulation,
const byte_t szMaxTargets, const byte_t * pbtInitiatorData,
const size_t szInitiatorDataLen, byte_t * pbtTargetsData, size_t * pszTargetsData);
const size_t szInitiatorDataLen, byte_t * pbtTargetsData, size_t * pszTargetsData,
struct timeval *timeout);
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 pn53x_target_type_t * ppttTargetTypes, const size_t szTargetTypes,

View file

@ -415,7 +415,7 @@ const struct nfc_driver_t acr122_driver = {
.initiator_init = pn53x_initiator_init,
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
.initiator_poll_targets = pn53x_initiator_poll_targets,
.initiator_poll_target = pn53x_initiator_poll_target,
.initiator_select_dep_target = pn53x_initiator_select_dep_target,
.initiator_deselect_target = pn53x_initiator_deselect_target,
.initiator_transceive_bytes = pn53x_initiator_transceive_bytes,

View file

@ -508,7 +508,7 @@ const struct nfc_driver_t arygon_driver = {
.initiator_init = pn53x_initiator_init,
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
.initiator_poll_targets = pn53x_initiator_poll_targets,
.initiator_poll_target = pn53x_initiator_poll_target,
.initiator_select_dep_target = pn53x_initiator_select_dep_target,
.initiator_deselect_target = pn53x_initiator_deselect_target,
.initiator_transceive_bytes = pn53x_initiator_transceive_bytes,

View file

@ -454,7 +454,7 @@ const struct nfc_driver_t pn532_uart_driver = {
.initiator_init = pn53x_initiator_init,
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
.initiator_poll_targets = pn53x_initiator_poll_targets,
.initiator_poll_target = pn53x_initiator_poll_target,
.initiator_select_dep_target = pn53x_initiator_select_dep_target,
.initiator_deselect_target = pn53x_initiator_deselect_target,
.initiator_transceive_bytes = pn53x_initiator_transceive_bytes,

View file

@ -751,7 +751,7 @@ const struct nfc_driver_t pn53x_usb_driver = {
.initiator_init = pn53x_initiator_init,
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
.initiator_poll_targets = pn53x_initiator_poll_targets,
.initiator_poll_target = pn53x_initiator_poll_target,
.initiator_select_dep_target = pn53x_initiator_select_dep_target,
.initiator_deselect_target = pn53x_initiator_deselect_target,
.initiator_transceive_bytes = pn53x_initiator_transceive_bytes,

67
libnfc/nfc-internal.c Normal file
View file

@ -0,0 +1,67 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2011, Romuald Conty
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file nfc-internal.c
* @brief Provide some useful internal functions
*/
#include <nfc/nfc.h>
#include <nfc/nfc-emulation.h>
void
prepare_initiator_data (const nfc_modulation_t nm, byte_t **ppbtInitiatorData, size_t * pszInitiatorData)
{
switch (nm.nmt) {
case NMT_ISO14443B: {
// Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
*ppbtInitiatorData = (byte_t *) "\x00";
*pszInitiatorData = 1;
}
break;
case NMT_ISO14443BI: {
// APGEN
*ppbtInitiatorData = (byte_t *) "\x01\x0b\x3f\x80";
*pszInitiatorData = 4;
}
break;
case NMT_ISO14443B2SR: {
// Get_UID
*ppbtInitiatorData = (byte_t *) "\x0b";
*pszInitiatorData = 1;
}
break;
case NMT_ISO14443B2CT: {
// SELECT-ALL
*ppbtInitiatorData = (byte_t *) "\x9F\xFF\xFF";
*pszInitiatorData = 3;
}
break;
case NMT_FELICA: {
// polling payload must be present (see ISO/IEC 18092 11.2.2.5)
*ppbtInitiatorData = (byte_t *) "\x00\xff\xff\x01\x00";
*pszInitiatorData = 5;
}
break;
default:
*ppbtInitiatorData = NULL;
*pszInitiatorData = 0;
break;
}
}

View file

@ -133,7 +133,7 @@ struct nfc_driver_t {
bool (*initiator_init) (nfc_device_t * pnd);
bool (*initiator_select_passive_target) (nfc_device_t * pnd, const nfc_modulation_t nm, const byte_t * pbtInitData, const size_t szInitData, nfc_target_t * pnt);
bool (*initiator_poll_targets) (nfc_device_t * pnd, const nfc_modulation_t * pnmModulations, const size_t szModulations, const byte_t btPollNr, const byte_t btPeriod, nfc_target_t * pntTargets, size_t * pszTargetFound);
bool (*initiator_poll_target) (nfc_device_t * pnd, const nfc_modulation_t * pnmModulations, const size_t szModulations, const uint8_t uiPollNr, const uint8_t btPeriod, nfc_target_t * pnt);
bool (*initiator_select_dep_target) (nfc_device_t * pnd, const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr, const nfc_dep_info_t * pndiInitiator, nfc_target_t * pnt);
bool (*initiator_deselect_target) (nfc_device_t * pnd);
bool (*initiator_transceive_bytes) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx, struct timeval *timeout);
@ -158,4 +158,6 @@ void nfc_device_free (nfc_device_t *nfc_device);
void iso14443_cascade_uid (const byte_t abtUID[], const size_t szUID, byte_t * pbtCascadedUID, size_t * pszCascadedUID);
void prepare_initiator_data (const nfc_modulation_t nm, byte_t **ppbtInitiatorData, size_t * pszInitiatorData);
#endif // __NFC_INTERNAL_H__

View file

@ -325,41 +325,7 @@ nfc_initiator_list_passive_targets (nfc_device_t * pnd,
return false;
}
switch (nm.nmt) {
case NMT_ISO14443B: {
// Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
pbtInitData = (byte_t *) "\x00";
szInitDataLen = 1;
}
break;
case NMT_ISO14443BI: {
// APGEN
pbtInitData = (byte_t *) "\x01\x0b\x3f\x80";
szInitDataLen = 4;
}
break;
case NMT_ISO14443B2SR: {
// Get_UID
pbtInitData = (byte_t *) "\x0b";
szInitDataLen = 1;
}
break;
case NMT_ISO14443B2CT: {
// SELECT-ALL
pbtInitData = (byte_t *) "\x9F\xFF\xFF";
szInitDataLen = 3;
}
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";
szInitDataLen = 5;
}
break;
default:
// nothing to do
break;
}
prepare_initiator_data (nm, &pbtInitData, &szInitDataLen);
while (nfc_initiator_select_passive_target (pnd, nm, pbtInitData, szInitDataLen, &nt)) {
nfc_initiator_deselect_target (pnd);
@ -397,19 +363,19 @@ nfc_initiator_list_passive_targets (nfc_device_t * pnd,
* @param pnd \a nfc_device_t struct pointer that represent currently used device
* @param ppttTargetTypes array of desired target types
* @param szTargetTypes \e ppttTargetTypes count
* @param btPollNr specifies the number of polling
* @param uiPollNr specifies the number of polling (0x01 0xFE: 1 up to 254 polling, 0xFF: Endless polling)
* @note one polling is a polling for each desired target type
* @param btPeriod indicates the polling period in units of 150 ms
* @param[out] pntTargets pointer on array of 2 \a nfc_target_t (over)writables struct
* @param[out] pszTargetFound found targets count
* @param uiPeriod indicates the polling period in units of 150 ms (0x01 0x0F: 150ms 2.25s)
* @note e.g. if uiPeriod=10, it will poll each desired target type during 1.5s
* @param[out] pnt pointer on \a nfc_target_t (over)writable struct
*/
bool
nfc_initiator_poll_targets (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const byte_t btPollNr, const byte_t btPeriod,
nfc_target_t * pntTargets, size_t * pszTargetFound)
nfc_initiator_poll_target (nfc_device_t * pnd,
const nfc_modulation_t * pnmModulations, const size_t szModulations,
const uint8_t uiPollNr, const uint8_t uiPeriod,
nfc_target_t * pnt)
{
HAL (initiator_poll_targets, pnd, pnmModulations, szModulations, btPollNr, btPeriod, pntTargets, pszTargetFound);
HAL (initiator_poll_target, pnd, pnmModulations, szModulations, uiPollNr, uiPeriod, pnt);
}