New function nfc_idle() to set the NFC device in idle mode.
nfc_disconnect() now switch NFC device into idle before disconnecting; pn53x_data now have a operating_mode enum to know the current running mode (initiator, target or idle); new pn53x_PowerDown wrapper for PowerDown (PN532) command; Note: ARYGON idle mode now to be implemented and ACR122 does not support this mode.
This commit is contained in:
parent
a2a93e7224
commit
be0f0b0828
9 changed files with 96 additions and 7 deletions
|
@ -66,6 +66,7 @@ extern "C" {
|
||||||
NFC_EXPORT bool nfc_abort_command (nfc_device_t * pnd);
|
NFC_EXPORT bool nfc_abort_command (nfc_device_t * pnd);
|
||||||
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 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_EXPORT bool nfc_idle (nfc_device_t * pnd);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
|
@ -67,6 +67,9 @@ pn53x_init(nfc_device_t * pnd)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PN53x starts in initiator mode
|
||||||
|
CHIP_DATA (pnd)->operating_mode = INITIATOR;
|
||||||
|
|
||||||
// Set current target to NULL
|
// Set current target to NULL
|
||||||
CHIP_DATA (pnd)->current_target = NULL;
|
CHIP_DATA (pnd)->current_target = NULL;
|
||||||
|
|
||||||
|
@ -660,6 +663,43 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pn53x_idle (nfc_device_t *pnd)
|
||||||
|
{
|
||||||
|
switch (CHIP_DATA (pnd)->operating_mode) {
|
||||||
|
case TARGET:
|
||||||
|
return pn53x_InRelease (pnd, 0);
|
||||||
|
break;
|
||||||
|
case INITIATOR:
|
||||||
|
// Deselect all active communications
|
||||||
|
if (!pn53x_InDeselect (pnd, 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Disable RF field to avoid heating
|
||||||
|
if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (CHIP_DATA (pnd)->type == PN532) {
|
||||||
|
// Use InPowerDown to go in "Low VBat"
|
||||||
|
if (!pn53x_PowerDown (pnd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CHIP_DATA (pnd)->power_mode = LOWVBAT;
|
||||||
|
} else {
|
||||||
|
// Use InRelease to go in "Standby mode"
|
||||||
|
if (!pn53x_InRelease (pnd, 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Nothing to do
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
CHIP_DATA (pnd)->operating_mode = IDLE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn53x_check_communication (nfc_device_t *pnd)
|
pn53x_check_communication (nfc_device_t *pnd)
|
||||||
{
|
{
|
||||||
|
@ -682,6 +722,8 @@ pn53x_initiator_init (nfc_device_t * pnd)
|
||||||
// Configure the PN53X to be an Initiator or Reader/Writer
|
// Configure the PN53X to be an Initiator or Reader/Writer
|
||||||
if (!pn53x_write_register (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
|
if (!pn53x_write_register (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
CHIP_DATA (pnd)->operating_mode = INITIATOR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1137,7 +1179,11 @@ bool
|
||||||
pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx)
|
pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx)
|
||||||
{
|
{
|
||||||
pn53x_reset_settings(pnd);
|
pn53x_reset_settings(pnd);
|
||||||
|
|
||||||
|
CHIP_DATA (pnd)->operating_mode = TARGET;
|
||||||
|
|
||||||
pn53x_target_mode_t ptm = PTM_NORMAL;
|
pn53x_target_mode_t ptm = PTM_NORMAL;
|
||||||
|
|
||||||
switch (pnt->nm.nmt) {
|
switch (pnt->nm.nmt) {
|
||||||
case NMT_ISO14443A:
|
case NMT_ISO14443A:
|
||||||
ptm = PTM_PASSIVE_ONLY;
|
ptm = PTM_PASSIVE_ONLY;
|
||||||
|
@ -1600,6 +1646,13 @@ pn53x_SAMConfiguration (nfc_device_t * pnd, const uint8_t ui8Mode)
|
||||||
pnd->iLastError = DENOTSUP;
|
pnd->iLastError = DENOTSUP;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return (pn53x_transceive (pnd, abtCmd, szCmd, NULL, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pn53x_PowerDown (nfc_device_t * pnd)
|
||||||
|
{
|
||||||
|
byte_t abtCmd[] = { PowerDown, 0xf0 };
|
||||||
return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL));
|
return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
# include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
// TODO Remove double register address defines
|
||||||
// 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
|
||||||
|
@ -144,15 +145,27 @@ typedef enum {
|
||||||
LOWVBAT // Only on PN532, need to be wake up to process commands with a long preamble and SAMConfiguration command
|
LOWVBAT // Only on PN532, need to be wake up to process commands with a long preamble and SAMConfiguration command
|
||||||
} pn53x_power_mode;
|
} pn53x_power_mode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IDLE,
|
||||||
|
INITIATOR,
|
||||||
|
TARGET,
|
||||||
|
} pn53x_operating_mode;
|
||||||
|
|
||||||
struct pn53x_io {
|
struct pn53x_io {
|
||||||
bool (*send)(nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
|
bool (*send)(nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
|
||||||
int (*receive)(nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen);
|
int (*receive)(nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pn53x_data {
|
struct pn53x_data {
|
||||||
|
/** Chip type (PN531, PN532 or PN533)*/
|
||||||
pn53x_type type;
|
pn53x_type type;
|
||||||
|
/** Current power mode */
|
||||||
pn53x_power_mode power_mode;
|
pn53x_power_mode power_mode;
|
||||||
|
/** Current operating mode */
|
||||||
|
pn53x_operating_mode operating_mode;
|
||||||
|
/** Current emulated target */
|
||||||
nfc_target_t* current_target;
|
nfc_target_t* current_target;
|
||||||
|
/** PN53x I/O functions stored in struct */
|
||||||
const struct pn53x_io * io;
|
const struct pn53x_io * io;
|
||||||
/** Register cache for REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS: The last TX bits setting, we need to reset this if it does not apply anymore */
|
/** Register cache for REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS: The last TX bits setting, we need to reset this if it does not apply anymore */
|
||||||
uint8_t ui8TxBits;
|
uint8_t ui8TxBits;
|
||||||
|
@ -166,7 +179,6 @@ struct pn53x_data {
|
||||||
|
|
||||||
#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))
|
#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))
|
||||||
|
|
||||||
/* PN53x specific types */
|
|
||||||
/**
|
/**
|
||||||
* @enum pn53x_modulation_t
|
* @enum pn53x_modulation_t
|
||||||
* @brief NFC modulation
|
* @brief NFC modulation
|
||||||
|
@ -265,6 +277,7 @@ bool pn53x_write_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8S
|
||||||
bool pn53x_get_firmware_version (nfc_device_t * pnd, char abtFirmwareText[18]);
|
bool pn53x_get_firmware_version (nfc_device_t * pnd, char abtFirmwareText[18]);
|
||||||
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_check_communication (nfc_device_t *pnd);
|
bool pn53x_check_communication (nfc_device_t *pnd);
|
||||||
|
bool pn53x_idle (nfc_device_t * pnd);
|
||||||
|
|
||||||
// NFC device as Initiator functions
|
// NFC device as Initiator functions
|
||||||
bool pn53x_initiator_init (nfc_device_t * pnd);
|
bool pn53x_initiator_init (nfc_device_t * pnd);
|
||||||
|
@ -305,6 +318,7 @@ const char *pn53x_strerror (const nfc_device_t * pnd);
|
||||||
// C wrappers for PN53x commands
|
// C wrappers for PN53x commands
|
||||||
bool pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value);
|
bool pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value);
|
||||||
bool pn53x_SAMConfiguration (nfc_device_t * pnd, const uint8_t ui8Mode);
|
bool pn53x_SAMConfiguration (nfc_device_t * pnd, const uint8_t ui8Mode);
|
||||||
|
bool pn53x_PowerDown (nfc_device_t * pnd);
|
||||||
bool pn53x_InListPassiveTarget (nfc_device_t * pnd, const pn53x_modulation_t pmInitModulation,
|
bool pn53x_InListPassiveTarget (nfc_device_t * pnd, const pn53x_modulation_t pmInitModulation,
|
||||||
const byte_t szMaxTargets, const byte_t * pbtInitiatorData,
|
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);
|
||||||
|
|
|
@ -427,5 +427,6 @@ const struct nfc_driver_t acr122_driver = {
|
||||||
.configure = pn53x_configure,
|
.configure = pn53x_configure,
|
||||||
|
|
||||||
.abort_command = NULL,
|
.abort_command = NULL,
|
||||||
|
.idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -494,5 +494,7 @@ const struct nfc_driver_t arygon_driver = {
|
||||||
.configure = pn53x_configure,
|
.configure = pn53x_configure,
|
||||||
|
|
||||||
.abort_command = arygon_abort_command,
|
.abort_command = arygon_abort_command,
|
||||||
|
// FIXME Implement me
|
||||||
|
.idle = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -444,5 +444,6 @@ const struct nfc_driver_t pn532_uart_driver = {
|
||||||
.configure = pn53x_configure,
|
.configure = pn53x_configure,
|
||||||
|
|
||||||
.abort_command = pn532_uart_abort_command,
|
.abort_command = pn532_uart_abort_command,
|
||||||
|
.idle = pn53x_idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -341,16 +341,17 @@ error:
|
||||||
void
|
void
|
||||||
pn53x_usb_disconnect (nfc_device_t * pnd)
|
pn53x_usb_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
|
|
||||||
pn53x_usb_ack (pnd);
|
pn53x_usb_ack (pnd);
|
||||||
|
|
||||||
|
pn53x_idle (pnd);
|
||||||
|
|
||||||
if (DRIVER_DATA (pnd)->model == ASK_LOGO) {
|
if (DRIVER_DATA (pnd)->model == ASK_LOGO) {
|
||||||
/* Set P30, P31, P32, P33, P35 to logic 1 and P34 to 0 logic */
|
/* Set P30, P31, P32, P33, P35 to logic 1 and P34 to 0 logic */
|
||||||
/* ie. Switch all LEDs off and turn off progressive field */
|
/* ie. Switch all LEDs off and turn off progressive field */
|
||||||
pn53x_write_register (pnd, SFR_P3, 0xFF, _BV (P30) | _BV (P31) | _BV (P32) | _BV (P33) | _BV (P35));
|
pn53x_write_register (pnd, SFR_P3, 0xFF, _BV (P30) | _BV (P31) | _BV (P32) | _BV (P33) | _BV (P35));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
if ((res = usb_release_interface (DRIVER_DATA (pnd)->pudh, 0)) < 0) {
|
if ((res = usb_release_interface (DRIVER_DATA (pnd)->pudh, 0)) < 0) {
|
||||||
ERR ("usb_release_interface failed (%i)", res);
|
ERR ("usb_release_interface failed (%i)", res);
|
||||||
}
|
}
|
||||||
|
@ -654,4 +655,5 @@ const struct nfc_driver_t pn53x_usb_driver = {
|
||||||
.configure = pn53x_usb_configure,
|
.configure = pn53x_usb_configure,
|
||||||
|
|
||||||
.abort_command = pn53x_usb_abort_command,
|
.abort_command = pn53x_usb_abort_command,
|
||||||
|
.idle = pn53x_idle,
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,6 +126,7 @@ struct nfc_driver_t {
|
||||||
bool (*configure) (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
bool (*configure) (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
||||||
|
|
||||||
bool (*abort_command) (nfc_device_t * pnd);
|
bool (*abort_command) (nfc_device_t * pnd);
|
||||||
|
bool (*idle) (nfc_device_t * pnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
nfc_device_t *nfc_device_new (void);
|
nfc_device_t *nfc_device_new (void);
|
||||||
|
|
22
libnfc/nfc.c
22
libnfc/nfc.c
|
@ -138,10 +138,8 @@ void
|
||||||
nfc_disconnect (nfc_device_t * pnd)
|
nfc_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
if (pnd) {
|
if (pnd) {
|
||||||
// Release and deselect all active communications
|
// Go in idle mode
|
||||||
nfc_initiator_deselect_target (pnd);
|
nfc_idle (pnd);
|
||||||
// Disable RF field to avoid heating
|
|
||||||
nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
|
|
||||||
// Disconnect, clean up and release the device
|
// Disconnect, clean up and release the device
|
||||||
pnd->driver->disconnect (pnd);
|
pnd->driver->disconnect (pnd);
|
||||||
}
|
}
|
||||||
|
@ -645,6 +643,22 @@ nfc_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t
|
||||||
HAL (target_init, pnd, pnt, pbtRx, pszRx);
|
HAL (target_init, pnd, pnt, pbtRx, pszRx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Turn NFC device in idle mode
|
||||||
|
* @return Returns \c true if action was successfully performed; otherwise returns \c false.
|
||||||
|
*
|
||||||
|
* @param pnd \a nfc_device_t struct pointer that represent currently used device
|
||||||
|
*
|
||||||
|
* This function switch the device in idle mode.
|
||||||
|
* In initiator mode, the RF field is turned off and the device is set to low power mode (if avaible);
|
||||||
|
* In target mode, the emulation is stoped (no target available from external initiator) and the device is set to low power mode (if avaible).
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
nfc_idle (nfc_device_t * pnd)
|
||||||
|
{
|
||||||
|
HAL (idle, pnd);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Abort current running command
|
* @brief Abort current running command
|
||||||
* @return Returns \c true if action was successfully performed; otherwise returns \c false.
|
* @return Returns \c true if action was successfully performed; otherwise returns \c false.
|
||||||
|
|
Loading…
Add table
Reference in a new issue