/****************************************************************************** * \attention * *

© COPYRIGHT 2020 STMicroelectronics

* * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * www.st.com/myliberty * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /* * PROJECT: ST25R391x firmware * Revision: * LANGUAGE: ISO C99 */ /*! \file rfal_nfca.h * * \author Gustavo Patricio * * \brief Provides several NFC-A convenience methods and definitions * * It provides a Poller (ISO14443A PCD) interface and as well as * some NFC-A Listener (ISO14443A PICC) helpers. * * The definitions and helpers methods provided by this module are only * up to ISO14443-3 layer * * * An usage example is provided here: \ref exampleRfalNfca.c * \example exampleRfalNfca.c * * * \addtogroup RFAL * @{ * * \addtogroup RFAL-AL * \brief RFAL Abstraction Layer * @{ * * \addtogroup NFC-A * \brief RFAL NFC-A Module * @{ * */ #ifndef RFAL_NFCA_H #define RFAL_NFCA_H /* ****************************************************************************** * INCLUDES ****************************************************************************** */ #include "platform.h" #include "st_errno.h" #include "rfal_rf.h" #include "rfal_t1t.h" /* ****************************************************************************** * GLOBAL DEFINES ****************************************************************************** */ #define RFAL_NFCA_CASCADE_1_UID_LEN 4U /*!< UID length of cascade level 1 only tag */ #define RFAL_NFCA_CASCADE_2_UID_LEN 7U /*!< UID length of cascade level 2 only tag */ #define RFAL_NFCA_CASCADE_3_UID_LEN 10U /*!< UID length of cascade level 3 only tag */ #define RFAL_NFCA_SENS_RES_PLATFORM_MASK 0x0FU /*!< SENS_RES (ATQA) platform configuration mask Digital 1.1 Table 10 */ #define RFAL_NFCA_SENS_RES_PLATFORM_T1T 0x0CU /*!< SENS_RES (ATQA) T1T platform configuration Digital 1.1 Table 10 */ #define RFAL_NFCA_SEL_RES_CONF_MASK 0x60U /*!< SEL_RES (SAK) platform configuration mask Digital 1.1 Table 19 */ #define RFAL_NFCA_SEL_RES_CONF_T2T 0x00U /*!< SEL_RES (SAK) T2T configuration Digital 1.1 Table 19 */ #define RFAL_NFCA_SEL_RES_CONF_T4T 0x20U /*!< SEL_RES (SAK) T4T configuration Digital 1.1 Table 19 */ #define RFAL_NFCA_SEL_RES_CONF_NFCDEP 0x40U /*!< SEL_RES (SAK) NFC-DEP configuration Digital 1.1 Table 19 */ #define RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP 0x60U /*!< SEL_RES (SAK) T4T and NFC-DEP configuration Digital 1.1 Table 19 */ /*! NFC-A minimum FDT(listen) = ((n * 128 + (84)) / fc) with n_min = 9 Digital 1.1 6.10.1 * = (1236)/fc * Relax with 3etu: (3*128)/fc as with multiple NFC-A cards, response may take longer (JCOP cards) * = (1236 + 384)/fc = 1620 / fc */ #define RFAL_NFCA_FDTMIN 1620U /* ****************************************************************************** * GLOBAL MACROS ****************************************************************************** */ /*! Checks if device is a T1T given its SENS_RES */ #define rfalNfcaIsSensResT1T( sensRes ) ((((rfalNfcaSensRes*)(sensRes))->platformInfo & RFAL_NFCA_SENS_RES_PLATFORM_MASK) == RFAL_NFCA_SENS_RES_PLATFORM_T1T ) /*! Checks if device is a T2T given its SENS_RES */ #define rfalNfcaIsSelResT2T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T2T ) /*! Checks if device is a T4T given its SENS_RES */ #define rfalNfcaIsSelResT4T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T ) /*! Checks if device supports NFC-DEP protocol given its SENS_RES */ #define rfalNfcaIsSelResNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_NFCDEP ) /*! Checks if device supports ISO-DEP and NFC-DEP protocol given its SENS_RES */ #define rfalNfcaIsSelResT4TNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP ) /*! Checks if a NFC-A listener device supports multiple protocols (ISO-DEP and NFC-DEP) */ #define rfalNfcaLisDevIsMultiProto( lisDev ) (((rfalNfcaListenDevice*)(lisDev))->type == RFAL_NFCA_T4T_NFCDEP ) /* ****************************************************************************** * GLOBAL TYPES ****************************************************************************** */ /*! NFC-A Listen device types */ typedef enum { RFAL_NFCA_T1T = 0x01, /* Device configured for T1T Digital 1.1 Table 9 */ RFAL_NFCA_T2T = 0x00, /* Device configured for T2T Digital 1.1 Table 19 */ RFAL_NFCA_T4T = 0x20, /* Device configured for T4T Digital 1.1 Table 19 */ RFAL_NFCA_NFCDEP = 0x40, /* Device configured for NFC-DEP Digital 1.1 Table 19 */ RFAL_NFCA_T4T_NFCDEP = 0x60 /* Device configured for NFC-DEP and T4T Digital 1.1 Table 19 */ } rfalNfcaListenDeviceType; /*! SENS_RES (ATQA) format Digital 1.1 6.6.3 & Table 7 */ typedef struct { uint8_t anticollisionInfo; /*!< SENS_RES Anticollision Information */ uint8_t platformInfo; /*!< SENS_RES Platform Information */ } rfalNfcaSensRes; /*! SDD_REQ (Anticollision) format Digital 1.1 6.7.1 & Table 11 */ typedef struct { uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ } rfalNfcaSddReq; /*! SDD_RES (UID CLn) format Digital 1.1 6.7.2 & Table 15 */ typedef struct { uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 cascade level NFCID */ uint8_t bcc; /*!< BCC Exclusive-OR over first 4 bytes of SDD_RES */ } rfalNfcaSddRes; /*! SEL_REQ (Select) format Digital 1.1 6.8.1 & Table 17 */ typedef struct { uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 data */ uint8_t bcc; /*!< Checksum calculated as exclusive-OR over the 4 bytes of NFCID1 CLn */ } rfalNfcaSelReq; /*! SEL_RES (SAK) format Digital 1.1 6.8.2 & Table 19 */ typedef struct { uint8_t sak; /*!< Select Acknowledge */ } rfalNfcaSelRes; /*! NFC-A listener device (PICC) struct */ typedef struct { rfalNfcaListenDeviceType type; /*!< NFC-A Listen device type */ rfalNfcaSensRes sensRes; /*!< SENS_RES (ATQA) */ rfalNfcaSelRes selRes; /*!< SEL_RES (SAK) */ uint8_t nfcId1Len; /*!< NFCID1 Length */ uint8_t nfcId1[RFAL_NFCA_CASCADE_3_UID_LEN]; /*!< NFCID1 (UID) */ #ifdef RFAL_FEATURE_T1T rfalT1TRidRes ridRes; /*!< RID_RES */ #endif /* RFAL_FEATURE_T1T */ bool isSleep; /*!< Device sleeping flag */ } rfalNfcaListenDevice; /* ****************************************************************************** * GLOBAL FUNCTION PROTOTYPES ****************************************************************************** */ /*! ***************************************************************************** * \brief Initialize NFC-A Poller mode * * This methods configures RFAL RF layer to perform as a * NFC-A Poller/RW (ISO14443A PCD) including all default timings and bit rate * to 106 kbps * * \return ERR_WRONG_STATE : RFAL not initialized or mode not set * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerInitialize( void ); /*! ***************************************************************************** * \brief NFC-A Poller Check Presence * * This method checks if a NFC-A Listen device (PICC) is present on the field * by sending an ALL_REQ (WUPA) or SENS_REQ (REQA) * * \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ * \param[out] sensRes : If received, the SENS_RES * * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_RF_COLLISION : Collision detected one or more device in the field * \return ERR_PAR : Parity error detected, one or more device in the field * \return ERR_CRC : CRC error detected, one or more device in the field * \return ERR_FRAMING : Framing error detected, one or more device in the field * \return ERR_PROTO : Protocol error detected, one or more device in the field * \return ERR_TIMEOUT : Timeout error, no listener device detected * \return ERR_NONE : No error, one or more device in the field ***************************************************************************** */ ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes ); /*! ***************************************************************************** * \brief NFC-A Poller Select * * This method selects a NFC-A Listener device (PICC) * * \param[in] nfcid1 : Listener device NFCID1 to be selected * \param[in] nfcidLen : Length of the NFCID1 to be selected * \param[out] selRes : pointer to place the SEL_RES * * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_TIMEOUT : Timeout error * \return ERR_PAR : Parity error detected * \return ERR_CRC : CRC error detected * \return ERR_FRAMING : Framing error detected * \return ERR_PROTO : Protocol error detected * \return ERR_NONE : No error, SEL_RES received ***************************************************************************** */ ReturnCode rfalNfcaPollerSelect( const uint8_t *nfcid1, uint8_t nfcidLen, rfalNfcaSelRes *selRes ); /*! ***************************************************************************** * \brief NFC-A Poller Sleep * * This method sends a SLP_REQ (HLTA) * No response is expected afterwards Digital 1.1 6.9.2.1 * * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerSleep( void ); /*! ***************************************************************************** * \brief NFC-A Technology Detection * * This method performs NFC-A Technology Detection as defined in the spec * given in the compliance mode * * \param[in] compMode : compliance mode to be performed * \param[out] sensRes : location to store the SENS_RES, if received * * When compMode is set to ISO compliance a SLP_REQ (HLTA) is not sent * after detection. When set to EMV a ALL_REQ (WUPA) is sent instead of * a SENS_REQ (REQA) * * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_NONE : No error, one or more device in the field ***************************************************************************** */ ReturnCode rfalNfcaPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcaSensRes *sensRes ); /*! ***************************************************************************** * \brief NFC-A Poller Collision Resolution * * Collision resolution for one NFC-A Listener device/card (PICC) as * defined in Activity 2.1 9.3.4 * * This method executes anti collision loop and select the device with higher NFCID1 * * When devLimit = 0 it is configured to perform collision detection only. Once a collision * is detected the collision resolution is aborted immidiatly. If only one device is found * with no collisions, it will properly resolved. * * \param[in] devLimit : device limit value (CON_DEVICES_LIMIT) * \param[out] collPending : pointer to collision pending flag (INT_COLL_PEND) * \param[out] selRes : location to store the last Select Response from listener device (PICC) * \param[out] nfcId1 : location to store the NFCID1 (UID), ensure RFAL_NFCA_CASCADE_3_UID_LEN * \param[out] nfcId1Len : pointer to length of NFCID1 (UID) * * \return ERR_WRONG_STATE : RFAL not initialized or mode not set * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_PROTO : Card length invalid * \return ERR_IGNORE : conDevLimit is 0 and there is a collision * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len ); /*! ***************************************************************************** * \brief NFC-A Poller Full Collision Resolution * * Performs a full Collision resolution as defined in Activity 2.1 9.3.4 * * \param[in] compMode : compliance mode to be performed * \param[in] devLimit : device limit value, and size nfcaDevList * \param[out] nfcaDevList : NFC-A listener device info * \param[out] devCnt : Devices found counter * * When compMode is set to ISO compliance it assumes that the device is * not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning. * When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent * at the beginning. * * * When devLimit = 0 it is configured to perform collision detection only. Once a collision * is detected the collision resolution is aborted immidiatly. If only one device is found * with no collisions, it will properly resolved. * * * \return ERR_WRONG_STATE : RFAL not initialized or mode not set * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt ); /*! ***************************************************************************** * \brief NFC-A Poller Full Collision Resolution with Sleep * * Performs a full Collision resolution similar to rfalNfcaPollerFullCollisionResolution * but an additional SLP_REQ (HLTA) -> SENS_RES (REQA) is sent regardless if there * was a collision. * This proprietary behaviour ensures proper activation of certain devices that suffer * from influence of Type B commands as foreseen in ISO14443-3 5.2.3 or were somehow * not detected by the first round of collision resolution * * \param[in] devLimit : device limit value, and size nfcaDevList * \param[out] nfcaDevList : NFC-A listener device info * \param[out] devCnt : Devices found counter * * * \return ERR_WRONG_STATE : RFAL not initialized or mode not set * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerSleepFullCollisionResolution( uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt ); /*! ***************************************************************************** * \brief NFC-A Poller Start Full Collision Resolution * * This method starts the full Collision resolution as defined * in Activity 1.0 or 1.1 9.3.4 * * \param[in] compMode : compliance mode to be performed * \param[in] devLimit : device limit value, and size nfcaDevList * \param[out] nfcaDevList : NFC-A listener device info * \param[out] devCnt : Devices found counter * * When compMode is set to ISO compliance it assumes that the device is * not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning. * When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent at * the beginning. * * * When devLimit = 0 it is configured to perform collision detection only. Once a collision * is detected the collision resolution is aborted immidiatly. If only one device is found * with no collisions, it will properly resolved. * * * \return ERR_WRONG_STATE : RFAL not initialized or mode not set * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_NONE : No error ***************************************************************************** */ ReturnCode rfalNfcaPollerStartFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt ); /*! ***************************************************************************** * \brief NFC-A Get Full Collision Resolution Status * * Returns the Collision Resolution status * * \return ERR_BUSY : Operation is ongoing * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode * \return ERR_PARAM : Invalid parameters * \return ERR_IO : Generic internal error * \return ERR_TIMEOUT : Timeout error * \return ERR_PAR : Parity error detected * \return ERR_CRC : CRC error detected * \return ERR_FRAMING : Framing error detected * \return ERR_PROTO : Protocol error detected * \return ERR_NONE : No error, activation successful ***************************************************************************** */ ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus( void ); /*! ***************************************************************************** * \brief NFC-A Listener is SLP_REQ * * Checks if the given buffer contains valid NFC-A SLP_REQ (HALT) * * \param[in] buf: buffer containing data * \param[in] bufLen: length of the data in buffer to be checked * * \return true if data in buf contains a SLP_REQ ; false otherwise ***************************************************************************** */ bool rfalNfcaListenerIsSleepReq( const uint8_t *buf, uint16_t bufLen ); #endif /* RFAL_NFCA_H */ /** * @} * * @} * * @} */