2021-10-18 01:54:19 +03:00
/******************************************************************************
* \ attention
*
* < h2 > < center > & copy ; COPYRIGHT 2020 STMicroelectronics < / center > < / h2 >
*
* 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.c
*
* \ 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
*
*/
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* INCLUDES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# include "rfal_nfca.h"
# include "utils.h"
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENABLE SWITCH
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# ifndef RFAL_FEATURE_NFCA
2022-01-05 19:10:18 +03:00
# define RFAL_FEATURE_NFCA false /* NFC-A module configuration missing. Disabled by default */
2021-10-18 01:54:19 +03:00
# endif
# if RFAL_FEATURE_NFCA
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL DEFINES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_SLP_FWT \
rfalConvMsTo1fc ( 1 ) /*!< Check 1ms for any modulation ISO14443-3 6.4.3 */
# define RFAL_NFCA_SLP_CMD 0x50U /*!< SLP cmd (byte1) Digital 1.1 6.9.1 & Table 20 */
# define RFAL_NFCA_SLP_BYTE2 0x00U /*!< SLP byte2 Digital 1.1 6.9.1 & Table 20 */
# define RFAL_NFCA_SLP_CMD_POS 0U /*!< SLP cmd position Digital 1.1 6.9.1 & Table 20 */
# define RFAL_NFCA_SLP_BYTE2_POS 1U /*!< SLP byte2 position Digital 1.1 6.9.1 & Table 20 */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_SDD_CT 0x88U /*!< Cascade Tag value Digital 1.1 6.7.2 */
# define RFAL_NFCA_SDD_CT_LEN 1U /*!< Cascade Tag length */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_SLP_REQ_LEN 2U /*!< SLP_REQ length */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_SEL_CMD_LEN 1U /*!< SEL_CMD length */
# define RFAL_NFCA_SEL_PAR_LEN 1U /*!< SEL_PAR length */
# define RFAL_NFCA_SEL_SELPAR \
rfalNfcaSelPar ( 7U , 0U ) /*!< SEL_PAR on Select is always with 4 data/nfcid */
# define RFAL_NFCA_BCC_LEN 1U /*!< BCC length */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_SDD_REQ_LEN \
( RFAL_NFCA_SEL_CMD_LEN + RFAL_NFCA_SEL_PAR_LEN ) /*!< SDD_REQ length */
# define RFAL_NFCA_SDD_RES_LEN \
( RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_BCC_LEN ) /*!< SDD_RES length */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
# define RFAL_NFCA_T_RETRANS 5U /*!< t RETRANSMISSION [3, 33]ms EMVCo 2.6 A.5 */
# define RFAL_NFCA_N_RETRANS 2U /*!< Number of retries EMVCo 2.6 9.6.1.3 */
2021-10-18 01:54:19 +03:00
/*! SDD_REQ (Select) Cascade Levels */
2022-01-05 19:10:18 +03:00
enum {
RFAL_NFCA_SEL_CASCADE_L1 = 0 , /*!< SDD_REQ Cascade Level 1 */
RFAL_NFCA_SEL_CASCADE_L2 = 1 , /*!< SDD_REQ Cascade Level 2 */
RFAL_NFCA_SEL_CASCADE_L3 = 2 /*!< SDD_REQ Cascade Level 3 */
2021-10-18 01:54:19 +03:00
} ;
/*! SDD_REQ (Select) request Cascade Level command Digital 1.1 Table 15 */
2022-01-05 19:10:18 +03:00
enum {
2021-10-18 01:54:19 +03:00
RFAL_NFCA_CMD_SEL_CL1 = 0x93 , /*!< SDD_REQ command Cascade Level 1 */
RFAL_NFCA_CMD_SEL_CL2 = 0x95 , /*!< SDD_REQ command Cascade Level 2 */
RFAL_NFCA_CMD_SEL_CL3 = 0x97 , /*!< SDD_REQ command Cascade Level 3 */
} ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL MACROS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
# define rfalNfcaSelPar(nBy, nbi) \
( uint8_t ) ( \
( ( ( nBy ) < < 4U ) & 0xF0U ) | \
( ( nbi ) & 0x0FU ) ) /*!< Calculates SEL_PAR with the bytes/bits to be sent */
# define rfalNfcaCLn2SELCMD(cl) \
( uint8_t ) ( \
( uint8_t ) ( RFAL_NFCA_CMD_SEL_CL1 ) + \
( 2U * ( cl ) ) ) /*!< Calculates SEL_CMD with the given cascade level */
# define rfalNfcaNfcidLen2CL(len) \
( ( len ) / 5U ) /*!< Calculates cascade level by the NFCID length */
# define rfalNfcaRunBlocking(e, fn) \
do { \
( e ) = ( fn ) ; \
rfalWorker ( ) ; \
} while ( ( e ) = = ERR_BUSY ) /*!< Macro used for the blocking methods */
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL TYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! Colission Resolution states */
2022-01-05 19:10:18 +03:00
typedef enum {
RFAL_NFCA_CR_IDLE , /*!< IDLE state */
RFAL_NFCA_CR_CL , /*!< New Cascading Level state */
RFAL_NFCA_CR_SDD , /*!< Perform anticollsion state */
RFAL_NFCA_CR_SEL , /*!< Perform CL Selection state */
RFAL_NFCA_CR_DONE /*!< Collision Resolution done state */
} colResState ;
2021-10-18 01:54:19 +03:00
/*! Colission Resolution context */
2022-01-05 19:10:18 +03:00
typedef struct {
uint8_t devLimit ; /*!< Device limit to be used */
rfalComplianceMode compMode ; /*!< Compliancy mode to be used */
rfalNfcaListenDevice *
nfcaDevList ; /*!< Location of the device list */
uint8_t * devCnt ; /*!< Location of the device counter */
bool collPending ; /*!< Collision pending flag */
bool * collPend ; /*!< Location of collision pending flag (Single CR) */
rfalNfcaSelReq selReq ; /*!< SelReqused during anticollision (Single CR) */
rfalNfcaSelRes * selRes ; /*!< Location to place of the SEL_RES(SAK) (Single CR) */
uint8_t * nfcId1 ; /*!< Location to place the NFCID1 (Single CR) */
uint8_t * nfcId1Len ; /*!< Location to place the NFCID1 length (Single CR) */
uint8_t cascadeLv ; /*!< Current Cascading Level (Single CR) */
colResState state ; /*!< Single Collision Resolution state (Single CR) */
uint8_t bytesTxRx ; /*!< TxRx bytes used during anticollision loop (Single CR) */
uint8_t bitsTxRx ; /*!< TxRx bits used during anticollision loop (Single CR) */
uint16_t rxLen ;
uint32_t tmrFDT ; /*!< FDT timer used between SED_REQs (Single CR) */
uint8_t retries ; /*!< Retries to be performed upon a timeout error (Single CR)*/
uint8_t backtrackCnt ; /*!< Backtrack retries (Single CR) */
bool doBacktrack ; /*!< Backtrack flag (Single CR) */
} colResParams ;
2021-10-18 01:54:19 +03:00
/*! RFAL NFC-A instance */
2022-01-05 19:10:18 +03:00
typedef struct {
colResParams CR ; /*!< Collision Resolution context */
2021-10-18 01:54:19 +03:00
} rfalNfca ;
/*! SLP_REQ (HLTA) format Digital 1.1 6.9.1 & Table 20 */
2022-01-05 19:10:18 +03:00
typedef struct {
uint8_t frame [ RFAL_NFCA_SLP_REQ_LEN ] ; /*!< SLP: 0x50 0x00 */
2021-10-18 01:54:19 +03:00
} rfalNfcaSlpReq ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL VARIABLES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
static rfalNfca gNfca ; /*!< RFAL NFC-A instance */
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTION PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
static uint8_t rfalNfcaCalculateBcc ( const uint8_t * buf , uint8_t bufLen ) ;
static ReturnCode rfalNfcaPollerStartSingleCollisionResolution (
uint8_t devLimit ,
bool * collPending ,
rfalNfcaSelRes * selRes ,
uint8_t * nfcId1 ,
uint8_t * nfcId1Len ) ;
static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus ( void ) ;
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
static uint8_t rfalNfcaCalculateBcc ( const uint8_t * buf , uint8_t bufLen ) {
2021-10-18 01:54:19 +03:00
uint8_t i ;
uint8_t BCC ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
BCC = 0 ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* BCC is XOR over first 4 bytes of the SDD_RES Digital 1.1 6.7.2 */
2022-01-05 19:10:18 +03:00
for ( i = 0 ; i < bufLen ; i + + ) {
2021-10-18 01:54:19 +03:00
BCC ^ = buf [ i ] ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return BCC ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
static ReturnCode rfalNfcaPollerStartSingleCollisionResolution (
uint8_t devLimit ,
bool * collPending ,
rfalNfcaSelRes * selRes ,
uint8_t * nfcId1 ,
uint8_t * nfcId1Len ) {
2021-10-18 01:54:19 +03:00
/* Check parameters */
2022-01-05 19:10:18 +03:00
if ( ( collPending = = NULL ) | | ( selRes = = NULL ) | | ( nfcId1 = = NULL ) | | ( nfcId1Len = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Initialize output parameters */
2022-01-05 19:10:18 +03:00
* collPending = false ; /* Activity 1.1 9.3.4.6 */
* nfcId1Len = 0 ;
ST_MEMSET ( nfcId1 , 0x00 , RFAL_NFCA_CASCADE_3_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
/* Save parameters */
2022-01-05 19:10:18 +03:00
gNfca . CR . devLimit = devLimit ;
gNfca . CR . collPend = collPending ;
gNfca . CR . selRes = selRes ;
gNfca . CR . nfcId1 = nfcId1 ;
gNfca . CR . nfcId1Len = nfcId1Len ;
platformTimerDestroy ( gNfca . CR . tmrFDT ) ;
gNfca . CR . tmrFDT = 0U ;
gNfca . CR . retries = RFAL_NFCA_N_RETRANS ;
gNfca . CR . cascadeLv = ( uint8_t ) RFAL_NFCA_SEL_CASCADE_L1 ;
gNfca . CR . state = RFAL_NFCA_CR_CL ;
gNfca . CR . doBacktrack = false ;
2021-10-18 01:54:19 +03:00
gNfca . CR . backtrackCnt = 3U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus ( void ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
uint8_t collBit = 1U ; /* standards mandate or recommend collision bit to be set to One. */
2021-10-18 01:54:19 +03:00
/* Check if FDT timer is still running */
2022-01-05 19:10:18 +03:00
if ( ! platformTimerIsExpired ( gNfca . CR . tmrFDT ) & & ( gNfca . CR . tmrFDT ! = 0U ) ) {
2021-10-18 01:54:19 +03:00
return ERR_BUSY ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
/* Go through all Cascade Levels Activity 1.1 9.3.4 */
if ( gNfca . CR . cascadeLv > ( uint8_t ) RFAL_NFCA_SEL_CASCADE_L3 ) {
2021-10-18 01:54:19 +03:00
return ERR_INTERNAL ;
}
2022-01-05 19:10:18 +03:00
switch ( gNfca . CR . state ) {
/*******************************************************************************/
case RFAL_NFCA_CR_CL :
/* Initialize the SDD_REQ to send for the new cascade level */
ST_MEMSET ( ( uint8_t * ) & gNfca . CR . selReq , 0x00 , sizeof ( rfalNfcaSelReq ) ) ;
gNfca . CR . bytesTxRx = RFAL_NFCA_SDD_REQ_LEN ;
gNfca . CR . bitsTxRx = 0U ;
gNfca . CR . state = RFAL_NFCA_CR_SDD ;
/* fall through */
/*******************************************************************************/
case RFAL_NFCA_CR_SDD : /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */
/* Calculate SEL_CMD and SEL_PAR with the bytes/bits to be sent */
gNfca . CR . selReq . selCmd = rfalNfcaCLn2SELCMD ( gNfca . CR . cascadeLv ) ;
gNfca . CR . selReq . selPar = rfalNfcaSelPar ( gNfca . CR . bytesTxRx , gNfca . CR . bitsTxRx ) ;
/* Send SDD_REQ (Anticollision frame) */
ret = rfalISO14443ATransceiveAnticollisionFrame (
( uint8_t * ) & gNfca . CR . selReq ,
& gNfca . CR . bytesTxRx ,
& gNfca . CR . bitsTxRx ,
& gNfca . CR . rxLen ,
RFAL_NFCA_FDTMIN ) ;
/* Retry upon timeout EMVCo 2.6 9.6.1.3 */
if ( ( ret = = ERR_TIMEOUT ) & & ( gNfca . CR . devLimit = = 0U ) & & ( gNfca . CR . retries ! = 0U ) ) {
gNfca . CR . retries - - ;
platformTimerDestroy ( gNfca . CR . tmrFDT ) ;
gNfca . CR . tmrFDT = platformTimerCreate ( RFAL_NFCA_T_RETRANS ) ;
break ;
}
/* Covert rxLen into bytes */
gNfca . CR . rxLen = rfalConvBitsToBytes ( gNfca . CR . rxLen ) ;
if ( ( ret = = ERR_TIMEOUT ) & & ( gNfca . CR . backtrackCnt ! = 0U ) & & ( ! gNfca . CR . doBacktrack ) & &
! ( ( RFAL_NFCA_SDD_REQ_LEN = = gNfca . CR . bytesTxRx ) & & ( 0U = = gNfca . CR . bitsTxRx ) ) ) {
/* In multiple card scenarios it may always happen that some
2021-10-18 01:54:19 +03:00
* collisions of a weaker tag go unnoticed . If then a later
* collision is recognized and the strong tag has a 0 at the
* collision position then no tag will respond . Catch this
* corner case and then try with the bit being sent as zero . */
2022-01-05 19:10:18 +03:00
rfalNfcaSensRes sensRes ;
ret = ERR_RF_COLLISION ;
rfalNfcaPollerCheckPresence ( RFAL_14443A_SHORTFRAME_CMD_REQA , & sensRes ) ;
/* Algorithm below does a post-increment, decrement to go back to current position */
if ( 0U = = gNfca . CR . bitsTxRx ) {
gNfca . CR . bitsTxRx = 7 ;
gNfca . CR . bytesTxRx - - ;
} else {
gNfca . CR . bitsTxRx - - ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
collBit =
( uint8_t ) ( ( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] & ( 1U < < gNfca . CR . bitsTxRx ) ) ;
collBit = ( uint8_t ) ( ( 0U = = collBit ) ? 1U : 0U ) ; // invert the collision bit
gNfca . CR . doBacktrack = true ;
gNfca . CR . backtrackCnt - - ;
} else {
gNfca . CR . doBacktrack = false ;
}
if ( ret = = ERR_RF_COLLISION ) {
/* Check received length */
if ( ( gNfca . CR . bytesTxRx + ( ( gNfca . CR . bitsTxRx ! = 0U ) ? 1U : 0U ) ) >
( RFAL_NFCA_SDD_RES_LEN + RFAL_NFCA_SDD_REQ_LEN ) ) {
return ERR_PROTO ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
if ( ( ( gNfca . CR . bytesTxRx + ( ( gNfca . CR . bitsTxRx ! = 0U ) ? 1U : 0U ) ) >
( RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN ) ) & &
( gNfca . CR . backtrackCnt ! = 0U ) ) { /* Collision in BCC: Anticollide only UID part */
gNfca . CR . backtrackCnt - - ;
gNfca . CR . bytesTxRx = RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN - 1U ;
gNfca . CR . bitsTxRx = 7 ;
collBit =
( uint8_t ) ( ( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] & ( 1U < < gNfca . CR . bitsTxRx ) ) ; /* Not a real collision, extract the actual bit for the subsequent code */
}
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( ( gNfca . CR . devLimit = = 0U ) & & ! ( * gNfca . CR . collPend ) ) {
/* Activity 1.0 & 1.1 9.3.4.12: If CON_DEVICES_LIMIT has a value of 0, then
2021-10-18 01:54:19 +03:00
* NFC Forum Device is configured to perform collision detection only */
* gNfca . CR . collPend = true ;
2022-01-05 19:10:18 +03:00
return ERR_IGNORE ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
* gNfca . CR . collPend = true ;
/* Set and select the collision bit, with the number of bytes/bits successfully TxRx */
if ( collBit ! = 0U ) {
( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] =
( uint8_t ) ( ( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] | ( 1U < < gNfca . CR . bitsTxRx ) ) ; /* MISRA 10.3 */
} else {
( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] =
( uint8_t ) ( ( ( uint8_t * ) & gNfca . CR . selReq ) [ gNfca . CR . bytesTxRx ] & ~ ( 1U < < gNfca . CR . bitsTxRx ) ) ; /* MISRA 10.3 */
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
gNfca . CR . bitsTxRx + + ;
/* Check if number of bits form a byte */
if ( gNfca . CR . bitsTxRx = = RFAL_BITS_IN_BYTE ) {
gNfca . CR . bitsTxRx = 0 ;
gNfca . CR . bytesTxRx + + ;
2021-10-18 01:54:19 +03:00
}
break ;
2022-01-05 19:10:18 +03:00
}
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
/* Check if Collision loop has failed */
if ( ret ! = ERR_NONE ) {
return ret ;
}
/* If collisions are to be reported check whether the response is complete */
if ( ( gNfca . CR . devLimit = = 0U ) & & ( gNfca . CR . rxLen ! = sizeof ( rfalNfcaSddRes ) ) ) {
return ERR_PROTO ;
}
/* Check if the received BCC match */
if ( gNfca . CR . selReq . bcc ! =
rfalNfcaCalculateBcc ( gNfca . CR . selReq . nfcid1 , RFAL_NFCA_CASCADE_1_UID_LEN ) ) {
return ERR_PROTO ;
}
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
/* Anticollision OK, Select this Cascade Level */
gNfca . CR . selReq . selPar = RFAL_NFCA_SEL_SELPAR ;
gNfca . CR . retries = RFAL_NFCA_N_RETRANS ;
gNfca . CR . state = RFAL_NFCA_CR_SEL ;
break ;
/*******************************************************************************/
case RFAL_NFCA_CR_SEL :
/* Send SEL_REQ (Select command) - Retry upon timeout EMVCo 2.6 9.6.1.3 */
ret = rfalTransceiveBlockingTxRx (
( uint8_t * ) & gNfca . CR . selReq ,
sizeof ( rfalNfcaSelReq ) ,
( uint8_t * ) gNfca . CR . selRes ,
sizeof ( rfalNfcaSelRes ) ,
& gNfca . CR . rxLen ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCA_FDTMIN ) ;
/* Retry upon timeout EMVCo 2.6 9.6.1.3 */
if ( ( ret = = ERR_TIMEOUT ) & & ( gNfca . CR . devLimit = = 0U ) & & ( gNfca . CR . retries ! = 0U ) ) {
gNfca . CR . retries - - ;
platformTimerDestroy ( gNfca . CR . tmrFDT ) ;
gNfca . CR . tmrFDT = platformTimerCreate ( RFAL_NFCA_T_RETRANS ) ;
break ;
}
if ( ret ! = ERR_NONE ) {
return ret ;
}
/* Ensure proper response length */
if ( gNfca . CR . rxLen ! = sizeof ( rfalNfcaSelRes ) ) {
return ERR_PROTO ;
}
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
/* Check cascade byte, if cascade tag then go next cascade level */
if ( * gNfca . CR . selReq . nfcid1 = = RFAL_NFCA_SDD_CT ) {
/* Cascade Tag present, store nfcid1 bytes (excluding cascade tag) and continue for next CL */
ST_MEMCPY (
& gNfca . CR . nfcId1 [ * gNfca . CR . nfcId1Len ] ,
& ( ( uint8_t * ) & gNfca . CR . selReq . nfcid1 ) [ RFAL_NFCA_SDD_CT_LEN ] ,
( RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN ) ) ;
* gNfca . CR . nfcId1Len + = ( RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN ) ;
/* Go to next cascade level */
gNfca . CR . state = RFAL_NFCA_CR_CL ;
gNfca . CR . cascadeLv + + ;
} else {
/* UID Selection complete, Stop Cascade Level loop */
ST_MEMCPY (
& gNfca . CR . nfcId1 [ * gNfca . CR . nfcId1Len ] ,
( uint8_t * ) & gNfca . CR . selReq . nfcid1 ,
RFAL_NFCA_CASCADE_1_UID_LEN ) ;
* gNfca . CR . nfcId1Len + = RFAL_NFCA_CASCADE_1_UID_LEN ;
gNfca . CR . state = RFAL_NFCA_CR_DONE ;
break ; /* Only flag operation complete on the next execution */
}
break ;
/*******************************************************************************/
case RFAL_NFCA_CR_DONE :
return ERR_NONE ;
/*******************************************************************************/
default :
return ERR_WRONG_STATE ;
2021-10-18 01:54:19 +03:00
}
return ERR_BUSY ;
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerInitialize ( void ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR ( ret , rfalSetMode ( RFAL_MODE_POLL_NFCA , RFAL_BR_106 , RFAL_BR_106 ) ) ;
rfalSetErrorHandling ( RFAL_ERRORHANDLING_NFC ) ;
rfalSetGT ( RFAL_GT_NFCA ) ;
rfalSetFDTListen ( RFAL_FDT_LISTEN_NFCA_POLLER ) ;
rfalSetFDTPoll ( RFAL_FDT_POLL_NFCA_POLLER ) ;
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerCheckPresence ( rfal14443AShortFrameCmd cmd , rfalNfcaSensRes * sensRes ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
uint16_t rcvLen ;
2021-10-18 01:54:19 +03:00
/* Digital 1.1 6.10.1.3 For Commands ALL_REQ, SENS_REQ, SDD_REQ, and SEL_REQ, the NFC Forum Device *
* MUST treat receipt of a Listen Frame at a time after FDT ( Listen , min ) as a Timeour Error */
2022-01-05 19:10:18 +03:00
ret = rfalISO14443ATransceiveShortFrame (
cmd ,
( uint8_t * ) sensRes ,
( uint8_t ) rfalConvBytesToBits ( sizeof ( rfalNfcaSensRes ) ) ,
& rcvLen ,
RFAL_NFCA_FDTMIN ) ;
if ( ( ret = = ERR_RF_COLLISION ) | | ( ret = = ERR_CRC ) | | ( ret = = ERR_NOMEM ) | |
( ret = = ERR_FRAMING ) | | ( ret = = ERR_PAR ) ) {
ret = ERR_NONE ;
2021-10-18 01:54:19 +03:00
}
return ret ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode
rfalNfcaPollerTechnologyDetection ( rfalComplianceMode compMode , rfalNfcaSensRes * sensRes ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR (
ret ,
rfalNfcaPollerCheckPresence (
( ( compMode = = RFAL_COMPLIANCE_MODE_EMV ) ? RFAL_14443A_SHORTFRAME_CMD_WUPA :
RFAL_14443A_SHORTFRAME_CMD_REQA ) ,
sensRes ) ) ;
2021-10-18 01:54:19 +03:00
/* Send SLP_REQ as Activity 1.1 9.2.3.6 and EMVCo 2.6 9.2.1.3 */
2022-01-05 19:10:18 +03:00
if ( compMode ! = RFAL_COMPLIANCE_MODE_ISO ) {
2021-10-18 01:54:19 +03:00
rfalNfcaPollerSleep ( ) ;
}
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerSingleCollisionResolution (
uint8_t devLimit ,
bool * collPending ,
rfalNfcaSelRes * selRes ,
uint8_t * nfcId1 ,
uint8_t * nfcId1Len ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR (
ret ,
rfalNfcaPollerStartSingleCollisionResolution (
devLimit , collPending , selRes , nfcId1 , nfcId1Len ) ) ;
rfalNfcaRunBlocking ( ret , rfalNfcaPollerGetSingleCollisionResolutionStatus ( ) ) ;
2021-10-18 01:54:19 +03:00
return ret ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerStartFullCollisionResolution (
rfalComplianceMode compMode ,
uint8_t devLimit ,
rfalNfcaListenDevice * nfcaDevList ,
uint8_t * devCnt ) {
ReturnCode ret ;
2021-10-18 01:54:19 +03:00
rfalNfcaSensRes sensRes ;
2022-01-05 19:10:18 +03:00
uint16_t rcvLen ;
if ( ( nfcaDevList = = NULL ) | | ( devCnt = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
* devCnt = 0 ;
2022-01-05 19:10:18 +03:00
ret = ERR_NONE ;
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Send ALL_REQ before Anticollision if a Sleep was sent before Activity 1.1 9.3.4.1 and EMVco 2.6 9.3.2.1 */
2022-01-05 19:10:18 +03:00
if ( compMode ! = RFAL_COMPLIANCE_MODE_ISO ) {
ret = rfalISO14443ATransceiveShortFrame (
RFAL_14443A_SHORTFRAME_CMD_WUPA ,
( uint8_t * ) & nfcaDevList - > sensRes ,
( uint8_t ) rfalConvBytesToBits ( sizeof ( rfalNfcaSensRes ) ) ,
& rcvLen ,
RFAL_NFCA_FDTMIN ) ;
if ( ret ! = ERR_NONE ) {
if ( ( compMode = = RFAL_COMPLIANCE_MODE_EMV ) | |
( ( ret ! = ERR_RF_COLLISION ) & & ( ret ! = ERR_CRC ) & & ( ret ! = ERR_FRAMING ) & &
( ret ! = ERR_PAR ) ) ) {
2021-10-18 01:54:19 +03:00
return ret ;
}
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check proper SENS_RES/ATQA size */
2022-01-05 19:10:18 +03:00
if ( ( ret = = ERR_NONE ) & & ( rfalConvBytesToBits ( sizeof ( rfalNfcaSensRes ) ) ! = rcvLen ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
/* Store the SENS_RES from Technology Detection or from WUPA */
2021-10-18 01:54:19 +03:00
sensRes = nfcaDevList - > sensRes ;
2022-01-05 19:10:18 +03:00
if ( devLimit > 0U ) /* MISRA 21.18 */
2021-10-18 01:54:19 +03:00
{
2022-01-05 19:10:18 +03:00
ST_MEMSET ( nfcaDevList , 0x00 , ( sizeof ( rfalNfcaListenDevice ) * devLimit ) ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Restore the prev SENS_RES, assuming that the SENS_RES received is from first device
* When only one device is detected it ' s not woken up then we ' ll have no SENS_RES ( ATQA ) */
nfcaDevList - > sensRes = sensRes ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Save parameters */
2022-01-05 19:10:18 +03:00
gNfca . CR . devCnt = devCnt ;
gNfca . CR . devLimit = devLimit ;
2021-10-18 01:54:19 +03:00
gNfca . CR . nfcaDevList = nfcaDevList ;
2022-01-05 19:10:18 +03:00
gNfca . CR . compMode = compMode ;
# if RFAL_FEATURE_T1T
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Only check for T1T if previous SENS_RES was received without a transmission *
* error . When collisions occur bits in the SENS_RES may look like a T1T */
/* If T1T Anticollision is not supported Activity 1.1 9.3.4.3 */
2022-01-05 19:10:18 +03:00
if ( rfalNfcaIsSensResT1T ( & nfcaDevList - > sensRes ) & & ( devLimit ! = 0U ) & & ( ret = = ERR_NONE ) & &
( compMode ! = RFAL_COMPLIANCE_MODE_EMV ) ) {
2021-10-18 01:54:19 +03:00
/* RID_REQ shall be performed Activity 1.1 9.3.4.24 */
rfalT1TPollerInitialize ( ) ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR ( ret , rfalT1TPollerRid ( & nfcaDevList - > ridRes ) ) ;
2021-10-18 01:54:19 +03:00
* devCnt = 1U ;
2022-01-05 19:10:18 +03:00
nfcaDevList - > isSleep = false ;
nfcaDevList - > type = RFAL_NFCA_T1T ;
2021-10-18 01:54:19 +03:00
nfcaDevList - > nfcId1Len = RFAL_NFCA_CASCADE_1_UID_LEN ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & nfcaDevList - > nfcId1 , & nfcaDevList - > ridRes . uid , RFAL_NFCA_CASCADE_1_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
2022-01-05 19:10:18 +03:00
# endif /* RFAL_FEATURE_T1T */
return rfalNfcaPollerStartSingleCollisionResolution (
devLimit ,
& gNfca . CR . collPending ,
& nfcaDevList - > selRes ,
( uint8_t * ) & nfcaDevList - > nfcId1 ,
& nfcaDevList - > nfcId1Len ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus ( void ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
uint8_t newDevType ;
if ( ( gNfca . CR . nfcaDevList = = NULL ) | | ( gNfca . CR . devCnt = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_WRONG_STATE ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Check whether a T1T has already been detected */
2022-01-05 19:10:18 +03:00
if ( rfalNfcaIsSensResT1T ( & gNfca . CR . nfcaDevList - > sensRes ) & &
( gNfca . CR . nfcaDevList - > type = = RFAL_NFCA_T1T ) ) {
2021-10-18 01:54:19 +03:00
/* T1T doesn't support Anticollision */
return ERR_NONE ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR ( ret , rfalNfcaPollerGetSingleCollisionResolutionStatus ( ) ) ;
2021-10-18 01:54:19 +03:00
/* Assign Listen Device */
2022-01-05 19:10:18 +03:00
newDevType = ( ( uint8_t ) gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . selRes . sak ) &
RFAL_NFCA_SEL_RES_CONF_MASK ; /* MISRA 10.8 */
2021-10-18 01:54:19 +03:00
/* PRQA S 4342 1 # MISRA 10.5 - Guaranteed that no invalid enum values are created: see guard_eq_RFAL_NFCA_T2T, .... */
2022-01-05 19:10:18 +03:00
gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . type = ( rfalNfcaListenDeviceType ) newDevType ;
2021-10-18 01:54:19 +03:00
gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . isSleep = false ;
( * gNfca . CR . devCnt ) + + ;
/* If a collision was detected and device counter is lower than limit Activity 1.1 9.3.4.21 */
2022-01-05 19:10:18 +03:00
if ( ( * gNfca . CR . devCnt < gNfca . CR . devLimit ) & & ( gNfca . CR . collPending ) ) {
2021-10-18 01:54:19 +03:00
/* Put this device to Sleep Activity 1.1 9.3.4.22 */
rfalNfcaPollerSleep ( ) ;
gNfca . CR . nfcaDevList [ ( * gNfca . CR . devCnt - 1U ) ] . isSleep = true ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Send a new SENS_REQ to check for other cards Activity 1.1 9.3.4.23 */
2022-01-05 19:10:18 +03:00
ret = rfalNfcaPollerCheckPresence (
RFAL_14443A_SHORTFRAME_CMD_REQA , & gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . sensRes ) ;
if ( ret = = ERR_TIMEOUT ) {
2021-10-18 01:54:19 +03:00
/* No more devices found, exit */
gNfca . CR . collPending = false ;
2022-01-05 19:10:18 +03:00
} else {
2021-10-18 01:54:19 +03:00
/* Another device found, continue loop */
gNfca . CR . collPending = true ;
}
2022-01-05 19:10:18 +03:00
} else {
2021-10-18 01:54:19 +03:00
/* Exit loop */
gNfca . CR . collPending = false ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Check if collision resolution shall continue */
2022-01-05 19:10:18 +03:00
if ( ( * gNfca . CR . devCnt < gNfca . CR . devLimit ) & & ( gNfca . CR . collPending ) ) {
EXIT_ON_ERR (
ret ,
rfalNfcaPollerStartSingleCollisionResolution (
gNfca . CR . devLimit ,
& gNfca . CR . collPending ,
& gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . selRes ,
( uint8_t * ) & gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . nfcId1 ,
& gNfca . CR . nfcaDevList [ * gNfca . CR . devCnt ] . nfcId1Len ) ) ;
2021-10-18 01:54:19 +03:00
return ERR_BUSY ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerFullCollisionResolution (
rfalComplianceMode compMode ,
uint8_t devLimit ,
rfalNfcaListenDevice * nfcaDevList ,
uint8_t * devCnt ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR (
ret , rfalNfcaPollerStartFullCollisionResolution ( compMode , devLimit , nfcaDevList , devCnt ) ) ;
rfalNfcaRunBlocking ( ret , rfalNfcaPollerGetFullCollisionResolutionStatus ( ) ) ;
2021-10-18 01:54:19 +03:00
return ret ;
}
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerSleepFullCollisionResolution (
uint8_t devLimit ,
rfalNfcaListenDevice * nfcaDevList ,
uint8_t * devCnt ) {
bool firstRound ;
uint8_t tmpDevCnt ;
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
if ( ( nfcaDevList = = NULL ) | | ( devCnt = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
/* Only use ALL_REQ (WUPA) on the first round */
2022-01-05 19:10:18 +03:00
firstRound = true ;
* devCnt = 0 ;
2021-10-18 01:54:19 +03:00
/* Perform collision resolution until no new device is found */
2022-01-05 19:10:18 +03:00
do {
2021-10-18 01:54:19 +03:00
tmpDevCnt = 0 ;
2022-01-05 19:10:18 +03:00
ret = rfalNfcaPollerFullCollisionResolution (
( firstRound ? RFAL_COMPLIANCE_MODE_NFC : RFAL_COMPLIANCE_MODE_ISO ) ,
( devLimit - * devCnt ) ,
& nfcaDevList [ * devCnt ] ,
& tmpDevCnt ) ;
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( ( ret = = ERR_NONE ) & & ( tmpDevCnt > 0U ) ) {
2021-10-18 01:54:19 +03:00
* devCnt + = tmpDevCnt ;
/* Check whether to seacrh for more devices */
2022-01-05 19:10:18 +03:00
if ( * devCnt < devLimit ) {
2021-10-18 01:54:19 +03:00
/* Set last found device to sleep (all others are slept already) */
rfalNfcaPollerSleep ( ) ;
2022-01-05 19:10:18 +03:00
nfcaDevList [ ( ( * devCnt ) - 1U ) ] . isSleep = true ;
2021-10-18 01:54:19 +03:00
/* Check if any other device is present */
2022-01-05 19:10:18 +03:00
ret = rfalNfcaPollerCheckPresence (
RFAL_14443A_SHORTFRAME_CMD_REQA , & nfcaDevList [ * devCnt ] . sensRes ) ;
if ( ret = = ERR_NONE ) {
2021-10-18 01:54:19 +03:00
firstRound = false ;
continue ;
}
}
}
break ;
2022-01-05 19:10:18 +03:00
} while ( true ) ;
2021-10-18 01:54:19 +03:00
return ( ( * devCnt > 0U ) ? ERR_NONE : ret ) ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerSelect ( const uint8_t * nfcid1 , uint8_t nfcidLen , rfalNfcaSelRes * selRes ) {
uint8_t i ;
uint8_t cl ;
uint8_t nfcidOffset ;
uint16_t rxLen ;
ReturnCode ret ;
2021-10-18 01:54:19 +03:00
rfalNfcaSelReq selReq ;
2022-01-05 19:10:18 +03:00
if ( ( nfcid1 = = NULL ) | | ( nfcidLen > RFAL_NFCA_CASCADE_3_UID_LEN ) | | ( selRes = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Calculate Cascate Level */
2022-01-05 19:10:18 +03:00
cl = rfalNfcaNfcidLen2CL ( nfcidLen ) ;
2021-10-18 01:54:19 +03:00
nfcidOffset = 0 ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Go through all Cascade Levels Activity 1.1 9.4.4 */
2022-01-05 19:10:18 +03:00
for ( i = RFAL_NFCA_SEL_CASCADE_L1 ; i < = cl ; i + + ) {
2021-10-18 01:54:19 +03:00
/* Assign SEL_CMD according to the CLn and SEL_PAR*/
selReq . selCmd = rfalNfcaCLn2SELCMD ( i ) ;
selReq . selPar = RFAL_NFCA_SEL_SELPAR ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute NFCID/Data on the SEL_REQ command Digital 1.1 Table 18 */
2022-01-05 19:10:18 +03:00
if ( cl ! = i ) {
2021-10-18 01:54:19 +03:00
* selReq . nfcid1 = RFAL_NFCA_SDD_CT ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY (
& selReq . nfcid1 [ RFAL_NFCA_SDD_CT_LEN ] ,
& nfcid1 [ nfcidOffset ] ,
( RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN ) ) ;
2021-10-18 01:54:19 +03:00
nfcidOffset + = ( RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN ) ;
2022-01-05 19:10:18 +03:00
} else {
ST_MEMCPY ( selReq . nfcid1 , & nfcid1 [ nfcidOffset ] , RFAL_NFCA_CASCADE_1_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Calculate nfcid's BCC */
2022-01-05 19:10:18 +03:00
selReq . bcc = rfalNfcaCalculateBcc ( ( uint8_t * ) & selReq . nfcid1 , sizeof ( selReq . nfcid1 ) ) ;
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
/* Send SEL_REQ */
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR (
ret ,
rfalTransceiveBlockingTxRx (
( uint8_t * ) & selReq ,
sizeof ( rfalNfcaSelReq ) ,
( uint8_t * ) selRes ,
sizeof ( rfalNfcaSelRes ) ,
& rxLen ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCA_FDTMIN ) ) ;
2021-10-18 01:54:19 +03:00
/* Ensure proper response length */
2022-01-05 19:10:18 +03:00
if ( rxLen ! = sizeof ( rfalNfcaSelRes ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* REMARK: Could check if NFCID1 is complete */
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcaPollerSleep ( void ) {
2021-10-18 01:54:19 +03:00
rfalNfcaSlpReq slpReq ;
2022-01-05 19:10:18 +03:00
uint8_t rxBuf ; /* dummy buffer, just to perform Rx */
slpReq . frame [ RFAL_NFCA_SLP_CMD_POS ] = RFAL_NFCA_SLP_CMD ;
2021-10-18 01:54:19 +03:00
slpReq . frame [ RFAL_NFCA_SLP_BYTE2_POS ] = RFAL_NFCA_SLP_BYTE2 ;
2022-01-05 19:10:18 +03:00
rfalTransceiveBlockingTxRx (
( uint8_t * ) & slpReq ,
sizeof ( rfalNfcaSlpReq ) ,
& rxBuf ,
sizeof ( rxBuf ) ,
NULL ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCA_SLP_FWT ) ;
2021-10-18 01:54:19 +03:00
/* ISO14443-3 6.4.3 HLTA - If PICC responds with any modulation during 1 ms this response shall be interpreted as not acknowledge
Digital 2.0 6.9 .2 .1 & EMVCo 3.0 5.6 .2 .1 - consider the HLTA command always acknowledged
No check to be compliant with NFC and EMVCo , and to improve interoprability ( Kovio RFID Tag )
*/
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
bool rfalNfcaListenerIsSleepReq ( const uint8_t * buf , uint16_t bufLen ) {
2021-10-18 01:54:19 +03:00
/* Check if length and payload match */
2022-01-05 19:10:18 +03:00
if ( ( bufLen ! = sizeof ( rfalNfcaSlpReq ) ) | | ( buf [ RFAL_NFCA_SLP_CMD_POS ] ! = RFAL_NFCA_SLP_CMD ) | |
( buf [ RFAL_NFCA_SLP_BYTE2_POS ] ! = RFAL_NFCA_SLP_BYTE2 ) ) {
2021-10-18 01:54:19 +03:00
return false ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return true ;
}
/* If the guards here don't compile then the code above cannot work anymore. */
2022-01-05 19:10:18 +03:00
extern uint8_t guard_eq_RFAL_NFCA_T2T
[ ( ( RFAL_NFCA_SEL_RES_CONF_MASK & ( uint8_t ) RFAL_NFCA_T2T ) = = ( uint8_t ) RFAL_NFCA_T2T ) ? 1 : ( - 1 ) ] ;
extern uint8_t guard_eq_RFAL_NFCA_T4T
[ ( ( RFAL_NFCA_SEL_RES_CONF_MASK & ( uint8_t ) RFAL_NFCA_T4T ) = = ( uint8_t ) RFAL_NFCA_T4T ) ? 1 : ( - 1 ) ] ;
extern uint8_t guard_eq_RFAL_NFCA_NFCDEP
[ ( ( RFAL_NFCA_SEL_RES_CONF_MASK & ( uint8_t ) RFAL_NFCA_NFCDEP ) = = ( uint8_t ) RFAL_NFCA_NFCDEP ) ?
1 :
( - 1 ) ] ;
extern uint8_t guard_eq_RFAL_NFCA_T4T_NFCDEP
[ ( ( RFAL_NFCA_SEL_RES_CONF_MASK & ( uint8_t ) RFAL_NFCA_T4T_NFCDEP ) = =
( uint8_t ) RFAL_NFCA_T4T_NFCDEP ) ?
1 :
( - 1 ) ] ;
2021-10-18 01:54:19 +03:00
# endif /* RFAL_FEATURE_NFCA */