2021-10-17 22:54:19 +00:00
/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* COPYRIGHT ( c ) 2020 STMicroelectronics
*
* Redistribution and use in source and binary forms , with or without modification ,
* are permitted provided that the following conditions are met :
* 1. Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution .
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY ,
* OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! \file rfal_nfc.c
*
* \ author Gustavo Patricio
*
* \ brief RFAL NFC device
*
* This module provides the required features to behave as an NFC Poller
* or Listener device . It grants an easy to use interface for the following
* activities : Technology Detection , Collision Resollution , Activation ,
* Data Exchange , and Deactivation
*
* This layer is influenced by ( but not fully aligned with ) the NFC Forum
* specifications , in particular : Activity 2.0 and NCI 2.0
*
*/
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* INCLUDES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# include "rfal_nfc.h"
# include "utils.h"
# include "rfal_analogConfig.h"
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL DEFINES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# define RFAL_NFC_MAX_DEVICES 5U /* Max number of devices supported */
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL MACROS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# define rfalNfcNfcNotify( st ) if( gNfcDev.disc.notifyCb != NULL ) gNfcDev.disc.notifyCb( st )
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL TYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! Buffer union, only one interface is used at a time */
typedef union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one interface at a time */
rfalIsoDepBufFormat isoDepBuf ; /*!< ISO-DEP buffer format (with header/prologue) */
rfalNfcDepBufFormat nfcDepBuf ; /*!< NFC-DEP buffer format (with header/prologue) */
} rfalNfcTmpBuffer ;
typedef struct {
rfalNfcState state ; /* Main state */
uint16_t techsFound ; /* Technologies found bitmask */
uint16_t techs2do ; /* Technologies still to be performed */
rfalBitRate ap2pBR ; /* Bit rate to poll for AP2P */
uint8_t selDevIdx ; /* Selected device index */
rfalNfcDevice * activeDev ; /* Active device pointer */
rfalNfcDiscoverParam disc ; /* Discovery parameters */
rfalNfcDevice devList [ RFAL_NFC_MAX_DEVICES ] ; /*!< Location of device list */
uint8_t devCnt ; /* Decices found counter */
uint32_t discTmr ; /* Discovery Total duration timer */
ReturnCode dataExErr ; /* Last Data Exchange error */
bool discRestart ; /* Restart discover after deactivation flag */
bool isRxChaining ; /* Flag indicating Other device is chaining */
uint32_t lmMask ; /* Listen Mode mask */
bool isTechInit ; /* Flag indicating technology has been set */
bool isOperOngoing ; /* Flag indicating opration is ongoing */
rfalNfcBuffer txBuf ; /* Tx buffer for Data Exchange */
rfalNfcBuffer rxBuf ; /* Rx buffer for Data Exchange */
uint16_t rxLen ; /* Length of received data on Data Exchange */
# if RFAL_FEATURE_NFC_DEP || RFAL_FEATURE_ISO_DEP
rfalNfcTmpBuffer tmpBuf ; /* Tmp buffer for Data Exchange */
# endif /* RFAL_FEATURE_NFC_DEP || RFAL_FEATURE_ISO_DEP */
} rfalNfc ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL VARIABLES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# ifdef RFAL_TEST_MODE
rfalNfc gNfcDev ;
# else /* RFAL_TEST_MODE */
static rfalNfc gNfcDev ;
# endif /* RFAL_TEST_MODE */
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTION PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcPollTechDetetection ( void ) ;
static ReturnCode rfalNfcPollCollResolution ( void ) ;
static ReturnCode rfalNfcPollActivation ( uint8_t devIt ) ;
static ReturnCode rfalNfcDeactivation ( void ) ;
# if RFAL_FEATURE_NFC_DEP
static ReturnCode rfalNfcNfcDepActivate ( rfalNfcDevice * device , rfalNfcDepCommMode commMode , const uint8_t * atrReq , uint16_t atrReqLen ) ;
# endif /* RFAL_FEATURE_NFC_DEP */
# if RFAL_FEATURE_LISTEN_MODE
static ReturnCode rfalNfcListenActivation ( void ) ;
# endif /* RFAL_FEATURE_LISTEN_MODE*/
/*******************************************************************************/
ReturnCode rfalNfcInitialize ( void )
{
ReturnCode err ;
gNfcDev . state = RFAL_NFC_STATE_NOTINIT ;
rfalAnalogConfigInitialize ( ) ; /* Initialize RFAL's Analog Configs */
EXIT_ON_ERR ( err , rfalInitialize ( ) ) ; /* Initialize RFAL */
gNfcDev . state = RFAL_NFC_STATE_IDLE ; /* Go to initialized */
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcDiscover ( const rfalNfcDiscoverParam * disParams )
{
/* Check if initialization has been performed */
if ( gNfcDev . state ! = RFAL_NFC_STATE_IDLE )
{
return ERR_WRONG_STATE ;
}
/* Check valid parameters */
if ( ( disParams = = NULL ) | | ( disParams - > devLimit > RFAL_NFC_MAX_DEVICES ) | | ( disParams - > devLimit = = 0U ) | |
( ( disParams - > maxBR > RFAL_BR_1695 ) & & ( disParams - > maxBR ! = RFAL_BR_KEEP ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_F ) ! = 0U ) & & ( disParams - > nfcfBR ! = RFAL_BR_212 ) & & ( disParams - > nfcfBR ! = RFAL_BR_424 ) ) | |
( ( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_AP2P ) ! = 0U ) & & ( disParams - > ap2pBR > RFAL_BR_424 ) ) | | ( disParams - > GBLen > RFAL_NFCDEP_GB_MAX_LEN ) ) )
{
return ERR_PARAM ;
}
if ( ( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_A ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCA ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_B ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCB ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_F ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCF ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_V ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCV ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_ST25TB ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_ST25TB ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_POLL_TECH_AP2P ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFC_DEP ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_LISTEN_TECH_A ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCA ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_LISTEN_TECH_B ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCB ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_LISTEN_TECH_F ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFCF ) ) | |
( ( ( disParams - > techs2Find & RFAL_NFC_LISTEN_TECH_AP2P ) ! = 0U ) & & ! ( ( bool ) RFAL_FEATURE_NFC_DEP ) ) )
{
return ERR_DISABLED ; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */
}
/* Initialize context for discovery */
gNfcDev . activeDev = NULL ;
gNfcDev . techsFound = RFAL_NFC_TECH_NONE ;
gNfcDev . devCnt = 0 ;
gNfcDev . discRestart = true ;
gNfcDev . isTechInit = false ;
gNfcDev . disc = * disParams ;
/* Calculate Listen Mask */
gNfcDev . lmMask = 0U ;
gNfcDev . lmMask | = ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_LISTEN_TECH_A ) ! = 0U ) ? RFAL_LM_MASK_NFCA : 0U ) ;
gNfcDev . lmMask | = ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_LISTEN_TECH_B ) ! = 0U ) ? RFAL_LM_MASK_NFCB : 0U ) ;
gNfcDev . lmMask | = ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_LISTEN_TECH_F ) ! = 0U ) ? RFAL_LM_MASK_NFCF : 0U ) ;
gNfcDev . lmMask | = ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_LISTEN_TECH_AP2P ) ! = 0U ) ? RFAL_LM_MASK_ACTIVE_P2P : 0U ) ;
# if !RFAL_FEATURE_LISTEN_MODE
/* Check if Listen Mode is supported/Enabled */
if ( gNfcDev . lmMask ! = 0U )
{
return ERR_DISABLED ;
}
# endif
gNfcDev . state = RFAL_NFC_STATE_START_DISCOVERY ;
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcDeactivate ( bool discovery )
{
/* Check for valid state */
if ( gNfcDev . state < = RFAL_NFC_STATE_IDLE )
{
return ERR_WRONG_STATE ;
}
/* Check if discovery is to continue afterwards */
if ( ( discovery = = true ) & & ( gNfcDev . disc . techs2Find ! = RFAL_NFC_TECH_NONE ) )
{
/* If so let the state machine continue*/
gNfcDev . discRestart = discovery ;
gNfcDev . state = RFAL_NFC_STATE_DEACTIVATION ;
}
else
{
/* Otherwise deactivate immediately and go to IDLE */
rfalNfcDeactivation ( ) ;
gNfcDev . state = RFAL_NFC_STATE_IDLE ;
}
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcSelect ( uint8_t devIdx )
{
/* Check for valid state */
if ( gNfcDev . state ! = RFAL_NFC_STATE_POLL_SELECT )
{
return ERR_WRONG_STATE ;
}
gNfcDev . selDevIdx = devIdx ;
gNfcDev . state = RFAL_NFC_STATE_POLL_ACTIVATION ;
return ERR_NONE ;
}
/*******************************************************************************/
rfalNfcState rfalNfcGetState ( void )
{
return gNfcDev . state ;
}
/*******************************************************************************/
ReturnCode rfalNfcGetDevicesFound ( rfalNfcDevice * * devList , uint8_t * devCnt )
{
/* Check for valid state */
if ( gNfcDev . state < RFAL_NFC_STATE_POLL_SELECT )
{
return ERR_WRONG_STATE ;
}
/* Check valid parameters */
if ( ( devList = = NULL ) | | ( devCnt = = NULL ) )
{
return ERR_PARAM ;
}
* devCnt = gNfcDev . devCnt ;
* devList = gNfcDev . devList ;
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcGetActiveDevice ( rfalNfcDevice * * dev )
{
/* Check for valid state */
if ( gNfcDev . state < RFAL_NFC_STATE_ACTIVATED )
{
return ERR_WRONG_STATE ;
}
/* Check valid parameter */
if ( dev = = NULL )
{
return ERR_PARAM ;
}
/* Check for valid state */
if ( ( gNfcDev . devCnt = = 0U ) | | ( gNfcDev . activeDev = = NULL ) )
{
return ERR_REQUEST ;
}
* dev = gNfcDev . activeDev ;
return ERR_NONE ;
}
/*******************************************************************************/
void rfalNfcWorker ( void )
{
ReturnCode err ;
rfalWorker ( ) ; /* Execute RFAL process */
switch ( gNfcDev . state )
{
/*******************************************************************************/
case RFAL_NFC_STATE_NOTINIT :
case RFAL_NFC_STATE_IDLE :
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_START_DISCOVERY :
/* Initialize context for discovery cycle */
gNfcDev . devCnt = 0 ;
gNfcDev . selDevIdx = 0 ;
gNfcDev . techsFound = RFAL_NFC_TECH_NONE ;
gNfcDev . techs2do = gNfcDev . disc . techs2Find ;
gNfcDev . state = RFAL_NFC_STATE_POLL_TECHDETECT ;
# if RFAL_FEATURE_WAKEUP_MODE
/* Check if Low power Wake-Up is to be performed */
if ( gNfcDev . disc . wakeupEnabled )
{
/* Initialize Low power Wake-up mode and wait */
err = rfalWakeUpModeStart ( ( gNfcDev . disc . wakeupConfigDefault ? NULL : & gNfcDev . disc . wakeupConfig ) ) ;
if ( err = = ERR_NONE )
{
gNfcDev . state = RFAL_NFC_STATE_WAKEUP_MODE ;
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller that WU was started */
}
}
# endif /* RFAL_FEATURE_WAKEUP_MODE */
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_WAKEUP_MODE :
# if RFAL_FEATURE_WAKEUP_MODE
/* Check if the Wake-up mode has woke */
if ( rfalWakeUpModeHasWoke ( ) )
{
rfalWakeUpModeStop ( ) ; /* Disable Wake-up mode */
gNfcDev . state = RFAL_NFC_STATE_POLL_TECHDETECT ; /* Go to Technology detection */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller that WU has woke */
}
# endif /* RFAL_FEATURE_WAKEUP_MODE */
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_POLL_TECHDETECT :
/* Start total duration timer */
platformTimerDestroy ( gNfcDev . discTmr ) ;
gNfcDev . discTmr = ( uint32_t ) platformTimerCreate ( gNfcDev . disc . totalDuration ) ;
err = rfalNfcPollTechDetetection ( ) ; /* Perform Technology Detection */
if ( err ! = ERR_BUSY ) /* Wait until all technologies are performed */
{
if ( ( err ! = ERR_NONE ) | | ( gNfcDev . techsFound = = RFAL_NFC_TECH_NONE ) ) /* Check if any error occurred or no techs were found */
{
rfalFieldOff ( ) ;
gNfcDev . state = RFAL_NFC_STATE_LISTEN_TECHDETECT ; /* Nothing found as poller, go to listener */
break ;
}
gNfcDev . techs2do = gNfcDev . techsFound ; /* Store the found technologies for collision resolution */
gNfcDev . state = RFAL_NFC_STATE_POLL_COLAVOIDANCE ; /* One or more devices found, go to Collision Avoidance */
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_POLL_COLAVOIDANCE :
err = rfalNfcPollCollResolution ( ) ; /* Resolve any eventual collision */
if ( err ! = ERR_BUSY ) /* Wait until all technologies are performed */
{
if ( ( err ! = ERR_NONE ) | | ( gNfcDev . devCnt = = 0U ) ) /* Check if any error occurred or no devices were found */
{
gNfcDev . state = RFAL_NFC_STATE_DEACTIVATION ;
break ; /* Unable to retrieve any device, restart loop */
}
/* Check if more than one device has been found */
if ( gNfcDev . devCnt > 1U )
{
/* If more than one device was found inform upper layer to choose which one to activate */
if ( gNfcDev . disc . notifyCb ! = NULL )
{
gNfcDev . state = RFAL_NFC_STATE_POLL_SELECT ;
gNfcDev . disc . notifyCb ( gNfcDev . state ) ;
break ;
}
}
/* If only one device or no callback has been set, activate the first device found */
gNfcDev . selDevIdx = 0U ;
gNfcDev . state = RFAL_NFC_STATE_POLL_ACTIVATION ;
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_POLL_ACTIVATION :
err = rfalNfcPollActivation ( gNfcDev . selDevIdx ) ;
if ( err ! = ERR_BUSY ) /* Wait until all Activation is complete */
{
if ( err ! = ERR_NONE ) /* Activation failed selected device */
{
gNfcDev . state = RFAL_NFC_STATE_DEACTIVATION ; /* If Activation failed, restart loop */
break ;
}
gNfcDev . state = RFAL_NFC_STATE_ACTIVATED ; /* Device has been properly activated */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Inform upper layer that a device has been activated */
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_DATAEXCHANGE :
rfalNfcDataExchangeGetStatus ( ) ; /* Run the internal state machine */
if ( gNfcDev . dataExErr ! = ERR_BUSY ) /* If Dataexchange has terminated */
{
gNfcDev . state = RFAL_NFC_STATE_DATAEXCHANGE_DONE ; /* Go to done state */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* And notify caller */
}
if ( gNfcDev . dataExErr = = ERR_SLEEP_REQ ) /* Check if Listen mode has to go to Sleep */
{
gNfcDev . state = RFAL_NFC_STATE_LISTEN_SLEEP ; /* Go to Listen Sleep state */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* And notify caller */
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_DEACTIVATION :
rfalNfcDeactivation ( ) ; /* Deactivate current device */
gNfcDev . state = ( ( gNfcDev . discRestart ) ? RFAL_NFC_STATE_START_DISCOVERY : RFAL_NFC_STATE_IDLE ) ;
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller */
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_LISTEN_TECHDETECT :
if ( platformTimerIsExpired ( gNfcDev . discTmr ) )
{
# if RFAL_FEATURE_LISTEN_MODE
rfalListenStop ( ) ;
# else
rfalFieldOff ( ) ;
# endif /* RFAL_FEATURE_LISTEN_MODE */
gNfcDev . state = RFAL_NFC_STATE_START_DISCOVERY ; /* Restart the discovery loop */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller */
break ;
}
# if RFAL_FEATURE_LISTEN_MODE
if ( gNfcDev . lmMask ! = 0U ) /* Check if configured to perform Listen mode */
{
err = rfalListenStart ( gNfcDev . lmMask , & gNfcDev . disc . lmConfigPA , NULL , & gNfcDev . disc . lmConfigPF , ( uint8_t * ) & gNfcDev . rxBuf . rfBuf , ( uint16_t ) rfalConvBytesToBits ( sizeof ( gNfcDev . rxBuf . rfBuf ) ) , & gNfcDev . rxLen ) ;
if ( err = = ERR_NONE )
{
gNfcDev . state = RFAL_NFC_STATE_LISTEN_COLAVOIDANCE ; /* Wait for listen mode to be activated */
}
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_LISTEN_COLAVOIDANCE :
if ( platformTimerIsExpired ( gNfcDev . discTmr ) ) /* Check if the total duration has been reached */
{
rfalListenStop ( ) ;
gNfcDev . state = RFAL_NFC_STATE_START_DISCOVERY ; /* Restart the discovery loop */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller */
break ;
}
/* Check for external field */
if ( rfalListenGetState ( NULL , NULL ) > = RFAL_LM_STATE_IDLE )
{
gNfcDev . state = RFAL_NFC_STATE_LISTEN_ACTIVATION ; /* Wait for listen mode to be activated */
}
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_LISTEN_ACTIVATION :
case RFAL_NFC_STATE_LISTEN_SLEEP :
err = rfalNfcListenActivation ( ) ;
if ( err ! = ERR_BUSY )
{
if ( err = = ERR_NONE )
{
gNfcDev . activeDev = gNfcDev . devList ; /* Assign the active device to be used further on */
gNfcDev . devCnt + + ;
gNfcDev . state = RFAL_NFC_STATE_ACTIVATED ; /* Device has been properly activated */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Inform upper layer that a device has been activated */
}
else
{
rfalListenStop ( ) ;
gNfcDev . state = RFAL_NFC_STATE_START_DISCOVERY ; /* Restart the discovery loop */
rfalNfcNfcNotify ( gNfcDev . state ) ; /* Notify caller */
}
}
# endif /* RFAL_FEATURE_LISTEN_MODE */
break ;
/*******************************************************************************/
case RFAL_NFC_STATE_ACTIVATED :
case RFAL_NFC_STATE_POLL_SELECT :
case RFAL_NFC_STATE_DATAEXCHANGE_DONE :
default :
return ;
}
}
/*******************************************************************************/
ReturnCode rfalNfcDataExchangeStart ( uint8_t * txData , uint16_t txDataLen , uint8_t * * rxData , uint16_t * * rvdLen , uint32_t fwt )
{
ReturnCode err ;
rfalTransceiveContext ctx ;
/*******************************************************************************/
/* The Data Exchange is divided in two different moments, the trigger/Start of *
* the transfer followed by the check until its completion */
if ( ( gNfcDev . state > = RFAL_NFC_STATE_ACTIVATED ) & & ( gNfcDev . activeDev ! = NULL ) )
{
/*******************************************************************************/
/* In Listen mode is the Poller that initiates the communicatation */
/* Assign output parameters and rfalNfcDataExchangeGetStatus will return */
/* incoming data from Poller/Initiator */
if ( ( gNfcDev . state = = RFAL_NFC_STATE_ACTIVATED ) & & rfalNfcIsRemDevPoller ( gNfcDev . activeDev - > type ) )
{
if ( txDataLen > 0U )
{
return ERR_WRONG_STATE ;
}
* rvdLen = ( uint16_t * ) & gNfcDev . rxLen ;
* rxData = ( uint8_t * ) ( ( gNfcDev . activeDev - > rfInterface = = RFAL_NFC_INTERFACE_ISODEP ) ? gNfcDev . rxBuf . isoDepBuf . apdu :
( ( gNfcDev . activeDev - > rfInterface = = RFAL_NFC_INTERFACE_NFCDEP ) ? gNfcDev . rxBuf . nfcDepBuf . pdu : gNfcDev . rxBuf . rfBuf ) ) ;
if ( gNfcDev . disc . activate_after_sak ) {
gNfcDev . state = RFAL_NFC_STATE_DATAEXCHANGE_DONE ;
}
return ERR_NONE ;
}
/*******************************************************************************/
switch ( gNfcDev . activeDev - > rfInterface ) /* Check which RF interface shall be used/has been activated */
{
/*******************************************************************************/
case RFAL_NFC_INTERFACE_RF :
rfalCreateByteFlagsTxRxContext ( ctx , ( uint8_t * ) txData , txDataLen , gNfcDev . rxBuf . rfBuf , sizeof ( gNfcDev . rxBuf . rfBuf ) , & gNfcDev . rxLen , RFAL_TXRX_FLAGS_DEFAULT , fwt ) ;
* rxData = ( uint8_t * ) gNfcDev . rxBuf . rfBuf ;
* rvdLen = ( uint16_t * ) & gNfcDev . rxLen ;
err = rfalStartTransceive ( & ctx ) ;
break ;
# if RFAL_FEATURE_ISO_DEP
/*******************************************************************************/
case RFAL_NFC_INTERFACE_ISODEP :
{
rfalIsoDepApduTxRxParam isoDepTxRx ;
if ( txDataLen > sizeof ( gNfcDev . txBuf . isoDepBuf . apdu ) )
{
return ERR_NOMEM ;
}
if ( txDataLen > 0U )
{
ST_MEMCPY ( ( uint8_t * ) gNfcDev . txBuf . isoDepBuf . apdu , txData , txDataLen ) ;
}
isoDepTxRx . DID = RFAL_ISODEP_NO_DID ;
isoDepTxRx . ourFSx = RFAL_ISODEP_FSX_KEEP ;
isoDepTxRx . FSx = gNfcDev . activeDev - > proto . isoDep . info . FSx ;
isoDepTxRx . dFWT = gNfcDev . activeDev - > proto . isoDep . info . dFWT ;
isoDepTxRx . FWT = gNfcDev . activeDev - > proto . isoDep . info . FWT ;
isoDepTxRx . txBuf = & gNfcDev . txBuf . isoDepBuf ;
isoDepTxRx . txBufLen = txDataLen ;
isoDepTxRx . rxBuf = & gNfcDev . rxBuf . isoDepBuf ;
isoDepTxRx . rxLen = & gNfcDev . rxLen ;
isoDepTxRx . tmpBuf = & gNfcDev . tmpBuf . isoDepBuf ;
* rxData = ( uint8_t * ) gNfcDev . rxBuf . isoDepBuf . apdu ;
* rvdLen = ( uint16_t * ) & gNfcDev . rxLen ;
/*******************************************************************************/
/* Trigger a RFAL ISO-DEP Transceive */
err = rfalIsoDepStartApduTransceive ( isoDepTxRx ) ;
break ;
}
# endif /* RFAL_FEATURE_ISO_DEP */
# if RFAL_FEATURE_NFC_DEP
/*******************************************************************************/
case RFAL_NFC_INTERFACE_NFCDEP :
{
rfalNfcDepPduTxRxParam nfcDepTxRx ;
if ( txDataLen > sizeof ( gNfcDev . txBuf . nfcDepBuf . pdu ) )
{
return ERR_NOMEM ;
}
if ( txDataLen > 0U )
{
ST_MEMCPY ( ( uint8_t * ) gNfcDev . txBuf . nfcDepBuf . pdu , txData , txDataLen ) ;
}
nfcDepTxRx . DID = RFAL_NFCDEP_DID_KEEP ;
nfcDepTxRx . FSx = rfalNfcIsRemDevListener ( gNfcDev . activeDev - > type ) ?
rfalNfcDepLR2FS ( ( uint8_t ) rfalNfcDepPP2LR ( gNfcDev . activeDev - > proto . nfcDep . activation . Target . ATR_RES . PPt ) ) :
rfalNfcDepLR2FS ( ( uint8_t ) rfalNfcDepPP2LR ( gNfcDev . activeDev - > proto . nfcDep . activation . Initiator . ATR_REQ . PPi ) ) ;
nfcDepTxRx . dFWT = gNfcDev . activeDev - > proto . nfcDep . info . dFWT ;
nfcDepTxRx . FWT = gNfcDev . activeDev - > proto . nfcDep . info . FWT ;
nfcDepTxRx . txBuf = & gNfcDev . txBuf . nfcDepBuf ;
nfcDepTxRx . txBufLen = txDataLen ;
nfcDepTxRx . rxBuf = & gNfcDev . rxBuf . nfcDepBuf ;
nfcDepTxRx . rxLen = & gNfcDev . rxLen ;
nfcDepTxRx . tmpBuf = & gNfcDev . tmpBuf . nfcDepBuf ;
* rxData = ( uint8_t * ) gNfcDev . rxBuf . nfcDepBuf . pdu ;
* rvdLen = ( uint16_t * ) & gNfcDev . rxLen ;
/*******************************************************************************/
/* Trigger a RFAL NFC-DEP Transceive */
err = rfalNfcDepStartPduTransceive ( nfcDepTxRx ) ;
break ;
}
# endif /* RFAL_FEATURE_NFC_DEP */
/*******************************************************************************/
default :
err = ERR_PARAM ;
break ;
}
/* If a transceive has succesfully started flag Data Exchange as ongoing */
if ( err = = ERR_NONE )
{
gNfcDev . dataExErr = ERR_BUSY ;
gNfcDev . state = RFAL_NFC_STATE_DATAEXCHANGE ;
}
return err ;
}
return ERR_WRONG_STATE ;
}
/*******************************************************************************/
ReturnCode rfalNfcDataExchangeGetStatus ( void )
{
/*******************************************************************************/
/* Check if it's the first frame received in Listen mode */
if ( gNfcDev . state = = RFAL_NFC_STATE_ACTIVATED )
{
/* Continue data exchange as normal */
gNfcDev . dataExErr = ERR_BUSY ;
gNfcDev . state = RFAL_NFC_STATE_DATAEXCHANGE ;
/* Check if we performing in T3T CE */
if ( ( gNfcDev . activeDev - > type = = RFAL_NFC_POLL_TYPE_NFCF ) & & ( gNfcDev . activeDev - > rfInterface = = RFAL_NFC_INTERFACE_RF ) )
{
/* The first frame has been retrieved by rfalListenMode, flag data immediately */
/* Can only call rfalGetTransceiveStatus() after starting a transceive with rfalStartTransceive */
gNfcDev . dataExErr = ERR_NONE ;
}
}
/*******************************************************************************/
/* Check if we are in we have been placed to sleep, and return last error */
if ( gNfcDev . state = = RFAL_NFC_STATE_LISTEN_SLEEP )
{
return gNfcDev . dataExErr ; /* ERR_SLEEP_REQ */
}
/*******************************************************************************/
/* Check if Data exchange has been started */
if ( ( gNfcDev . state ! = RFAL_NFC_STATE_DATAEXCHANGE ) & & ( gNfcDev . state ! = RFAL_NFC_STATE_DATAEXCHANGE_DONE ) )
{
return ERR_WRONG_STATE ;
}
/* Check if Data exchange is still ongoing */
if ( gNfcDev . dataExErr = = ERR_BUSY )
{
switch ( gNfcDev . activeDev - > rfInterface )
{
/*******************************************************************************/
case RFAL_NFC_INTERFACE_RF :
gNfcDev . dataExErr = rfalGetTransceiveStatus ( ) ;
break ;
# if RFAL_FEATURE_ISO_DEP
/*******************************************************************************/
case RFAL_NFC_INTERFACE_ISODEP :
gNfcDev . dataExErr = rfalIsoDepGetApduTransceiveStatus ( ) ;
break ;
# endif /* RFAL_FEATURE_ISO_DEP */
/*******************************************************************************/
# if RFAL_FEATURE_NFC_DEP
case RFAL_NFC_INTERFACE_NFCDEP :
gNfcDev . dataExErr = rfalNfcDepGetPduTransceiveStatus ( ) ;
break ;
# endif /* RFAL_FEATURE_NFC_DEP */
/*******************************************************************************/
default :
gNfcDev . dataExErr = ERR_PARAM ;
break ;
}
# if RFAL_FEATURE_LISTEN_MODE
/*******************************************************************************/
/* If a Sleep request has been received (Listen Mode) go to sleep immediately */
if ( gNfcDev . dataExErr = = ERR_SLEEP_REQ )
{
EXIT_ON_ERR ( gNfcDev . dataExErr , rfalListenSleepStart ( RFAL_LM_STATE_SLEEP_A , gNfcDev . rxBuf . rfBuf , sizeof ( gNfcDev . rxBuf . rfBuf ) , & gNfcDev . rxLen ) ) ;
/* If set Sleep was succesfull keep restore the Sleep request signal */
gNfcDev . dataExErr = ERR_SLEEP_REQ ;
}
# endif /* RFAL_FEATURE_LISTEN_MODE */
}
return gNfcDev . dataExErr ;
}
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Poller Technology Detection
*
* This method implements the Technology Detection / Poll for different
* device technologies .
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcPollTechDetetection ( void )
{
ReturnCode err ;
err = ERR_NONE ;
/* Supress warning when specific RFAL features have been disabled */
NO_WARNING ( err ) ;
/*******************************************************************************/
/* AP2P Technology Detection */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_AP2P ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_AP2P ) ! = 0U ) )
{
# if RFAL_FEATURE_NFC_DEP
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalSetMode ( RFAL_MODE_POLL_ACTIVE_P2P , gNfcDev . disc . ap2pBR , gNfcDev . disc . ap2pBR ) ) ;
rfalSetErrorHandling ( RFAL_ERRORHANDLING_NFC ) ;
rfalSetFDTListen ( RFAL_FDT_LISTEN_AP2P_POLLER ) ;
rfalSetFDTPoll ( RFAL_TIMING_NONE ) ;
rfalSetGT ( RFAL_GT_AP2P_ADJUSTED ) ;
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Turns the Field On and starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_AP2P ;
err = rfalNfcNfcDepActivate ( gNfcDev . devList , RFAL_NFCDEP_COMM_ACTIVE , NULL , 0 ) ; /* Poll for NFC-A devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_AP2P ;
gNfcDev . devList - > type = RFAL_NFC_LISTEN_TYPE_AP2P ;
gNfcDev . devList - > rfInterface = RFAL_NFC_INTERFACE_NFCDEP ;
gNfcDev . devCnt + + ;
return ERR_NONE ;
}
gNfcDev . isTechInit = false ;
rfalFieldOff ( ) ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFC_DEP */
}
/*******************************************************************************/
/* Passive NFC-A Technology Detection */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_A ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_A ) ! = 0U ) )
{
# if RFAL_FEATURE_NFCA
rfalNfcaSensRes sensRes ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcaPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-A */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Turns the Field On and starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
err = rfalNfcaPollerTechnologyDetection ( gNfcDev . disc . compMode , & sensRes ) ; /* Poll for NFC-A devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_A ;
}
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_A ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFCA */
}
/*******************************************************************************/
/* Passive NFC-B Technology Detection */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_B ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_B ) ! = 0U ) )
{
# if RFAL_FEATURE_NFCB
rfalNfcbSensbRes sensbRes ;
uint8_t sensbResLen ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcbPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-B */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* As field is already On only starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
err = rfalNfcbPollerTechnologyDetection ( gNfcDev . disc . compMode , & sensbRes , & sensbResLen ) ; /* Poll for NFC-B devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_B ;
}
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_B ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFCB */
}
/*******************************************************************************/
/* Passive NFC-F Technology Detection */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_F ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_F ) ! = 0U ) )
{
# if RFAL_FEATURE_NFCF
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcfPollerInitialize ( gNfcDev . disc . nfcfBR ) ) ; /* Initialize RFAL for NFC-F */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* As field is already On only starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
err = rfalNfcfPollerCheckPresence ( ) ; /* Poll for NFC-F devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_F ;
}
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_F ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFCF */
}
/*******************************************************************************/
/* Passive NFC-V Technology Detection */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_V ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_V ) ! = 0U ) )
{
# if RFAL_FEATURE_NFCV
rfalNfcvInventoryRes invRes ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcvPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-V */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* As field is already On only starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
err = rfalNfcvPollerCheckPresence ( & invRes ) ; /* Poll for NFC-V devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_V ;
}
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_V ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFCV */
}
/*******************************************************************************/
/* Passive Proprietary Technology ST25TB */
/*******************************************************************************/
if ( ( ( gNfcDev . disc . techs2Find & RFAL_NFC_POLL_TECH_ST25TB ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_ST25TB ) ! = 0U ) )
{
# if RFAL_FEATURE_ST25TB
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalSt25tbPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-V */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* As field is already On only starts GT timer */
gNfcDev . isTechInit = true ;
}
if ( rfalIsGTExpired ( ) ) /* Wait until Guard Time is fulfilled */
{
err = rfalSt25tbPollerCheckPresence ( NULL ) ; /* Poll for ST25TB devices */
if ( err = = ERR_NONE )
{
gNfcDev . techsFound | = RFAL_NFC_POLL_TECH_ST25TB ;
}
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_ST25TB ;
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_ST25TB */
}
return ERR_NONE ;
}
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Poller Collision Resolution
*
* This method implements the Collision Resolution on all technologies that
* have been detected before .
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcPollCollResolution ( void )
{
uint8_t i ;
static uint8_t devCnt ;
ReturnCode err ;
err = ERR_NONE ;
i = 0 ;
/* Supress warning when specific RFAL features have been disabled */
NO_WARNING ( err ) ;
NO_WARNING ( devCnt ) ;
NO_WARNING ( i ) ;
/* Check if device limit has been reached */
if ( gNfcDev . devCnt > = gNfcDev . disc . devLimit )
{
return ERR_NONE ;
}
/*******************************************************************************/
/* NFC-A Collision Resolution */
/*******************************************************************************/
# if RFAL_FEATURE_NFCA
if ( ( ( gNfcDev . techsFound & RFAL_NFC_POLL_TECH_A ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_A ) ! = 0U ) ) /* If a NFC-A device was found/detected, perform Collision Resolution */
{
static rfalNfcaListenDevice nfcaDevList [ RFAL_NFC_MAX_DEVICES ] ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcaPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-A */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Turns the Field On and starts GT timer */
gNfcDev . isTechInit = true ; /* Technology has been initialized */
gNfcDev . isOperOngoing = false ; /* No operation currently ongoing */
}
if ( ! rfalIsGTExpired ( ) )
{
return ERR_BUSY ;
}
if ( ! gNfcDev . isOperOngoing )
{
EXIT_ON_ERR ( err , rfalNfcaPollerStartFullCollisionResolution ( gNfcDev . disc . compMode , ( gNfcDev . disc . devLimit - gNfcDev . devCnt ) , nfcaDevList , & devCnt ) ) ;
gNfcDev . isOperOngoing = true ;
return ERR_BUSY ;
}
err = rfalNfcaPollerGetFullCollisionResolutionStatus ( ) ;
if ( err ! = ERR_BUSY )
{
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_A ;
if ( ( err = = ERR_NONE ) & & ( devCnt ! = 0U ) )
{
for ( i = 0 ; i < devCnt ; i + + ) /* Copy devices found form local Nfca list into global device list */
{
gNfcDev . devList [ gNfcDev . devCnt ] . type = RFAL_NFC_LISTEN_TYPE_NFCA ;
gNfcDev . devList [ gNfcDev . devCnt ] . dev . nfca = nfcaDevList [ i ] ;
gNfcDev . devCnt + + ;
}
}
}
return ERR_BUSY ;
}
# endif /* RFAL_FEATURE_NFCA */
/*******************************************************************************/
/* NFC-B Collision Resolution */
/*******************************************************************************/
# if RFAL_FEATURE_NFCB
if ( ( ( gNfcDev . techsFound & RFAL_NFC_POLL_TECH_B ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_B ) ! = 0U ) ) /* If a NFC-B device was found/detected, perform Collision Resolution */
{
rfalNfcbListenDevice nfcbDevList [ RFAL_NFC_MAX_DEVICES ] ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcbPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-B */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Ensure GT again as other technologies have also been polled */
gNfcDev . isTechInit = true ;
}
if ( ! rfalIsGTExpired ( ) )
{
return ERR_BUSY ;
}
devCnt = 0 ;
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_B ;
err = rfalNfcbPollerCollisionResolution ( gNfcDev . disc . compMode , ( gNfcDev . disc . devLimit - gNfcDev . devCnt ) , nfcbDevList , & devCnt ) ;
if ( ( err = = ERR_NONE ) & & ( devCnt ! = 0U ) )
{
for ( i = 0 ; i < devCnt ; i + + ) /* Copy devices found form local Nfcb list into global device list */
{
gNfcDev . devList [ gNfcDev . devCnt ] . type = RFAL_NFC_LISTEN_TYPE_NFCB ;
gNfcDev . devList [ gNfcDev . devCnt ] . dev . nfcb = nfcbDevList [ i ] ;
gNfcDev . devCnt + + ;
}
}
return ERR_BUSY ;
}
# endif /* RFAL_FEATURE_NFCB*/
/*******************************************************************************/
/* NFC-F Collision Resolution */
/*******************************************************************************/
# if RFAL_FEATURE_NFCF
if ( ( ( gNfcDev . techsFound & RFAL_NFC_POLL_TECH_F ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_F ) ! = 0U ) ) /* If a NFC-F device was found/detected, perform Collision Resolution */
{
rfalNfcfListenDevice nfcfDevList [ RFAL_NFC_MAX_DEVICES ] ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcfPollerInitialize ( gNfcDev . disc . nfcfBR ) ) ; /* Initialize RFAL for NFC-F */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Ensure GT again as other technologies have also been polled */
gNfcDev . isTechInit = true ;
}
if ( ! rfalIsGTExpired ( ) )
{
return ERR_BUSY ;
}
devCnt = 0 ;
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_F ;
err = rfalNfcfPollerCollisionResolution ( gNfcDev . disc . compMode , ( gNfcDev . disc . devLimit - gNfcDev . devCnt ) , nfcfDevList , & devCnt ) ;
if ( ( err = = ERR_NONE ) & & ( devCnt ! = 0U ) )
{
for ( i = 0 ; i < devCnt ; i + + ) /* Copy devices found form local Nfcf list into global device list */
{
gNfcDev . devList [ gNfcDev . devCnt ] . type = RFAL_NFC_LISTEN_TYPE_NFCF ;
gNfcDev . devList [ gNfcDev . devCnt ] . dev . nfcf = nfcfDevList [ i ] ;
gNfcDev . devCnt + + ;
}
}
return ERR_BUSY ;
}
# endif /* RFAL_FEATURE_NFCF */
/*******************************************************************************/
/* NFC-V Collision Resolution */
/*******************************************************************************/
# if RFAL_FEATURE_NFCV
if ( ( ( gNfcDev . techsFound & RFAL_NFC_POLL_TECH_V ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_V ) ! = 0U ) ) /* If a NFC-V device was found/detected, perform Collision Resolution */
{
rfalNfcvListenDevice nfcvDevList [ RFAL_NFC_MAX_DEVICES ] ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalNfcvPollerInitialize ( ) ) ; /* Initialize RFAL for NFC-V */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Ensure GT again as other technologies have also been polled */
gNfcDev . isTechInit = true ;
}
if ( ! rfalIsGTExpired ( ) )
{
return ERR_BUSY ;
}
devCnt = 0 ;
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_V ;
err = rfalNfcvPollerCollisionResolution ( RFAL_COMPLIANCE_MODE_NFC , ( gNfcDev . disc . devLimit - gNfcDev . devCnt ) , nfcvDevList , & devCnt ) ;
if ( ( err = = ERR_NONE ) & & ( devCnt ! = 0U ) )
{
for ( i = 0 ; i < devCnt ; i + + ) /* Copy devices found form local Nfcf list into global device list */
{
gNfcDev . devList [ gNfcDev . devCnt ] . type = RFAL_NFC_LISTEN_TYPE_NFCV ;
gNfcDev . devList [ gNfcDev . devCnt ] . dev . nfcv = nfcvDevList [ i ] ;
gNfcDev . devCnt + + ;
}
}
return ERR_BUSY ;
}
# endif /* RFAL_FEATURE_NFCV */
/*******************************************************************************/
/* ST25TB Collision Resolution */
/*******************************************************************************/
# if RFAL_FEATURE_ST25TB
if ( ( ( gNfcDev . techsFound & RFAL_NFC_POLL_TECH_ST25TB ) ! = 0U ) & & ( ( gNfcDev . techs2do & RFAL_NFC_POLL_TECH_ST25TB ) ! = 0U ) ) /* If a ST25TB device was found/detected, perform Collision Resolution */
{
rfalSt25tbListenDevice st25tbDevList [ RFAL_NFC_MAX_DEVICES ] ;
if ( ! gNfcDev . isTechInit )
{
EXIT_ON_ERR ( err , rfalSt25tbPollerInitialize ( ) ) ; /* Initialize RFAL for ST25TB */
EXIT_ON_ERR ( err , rfalFieldOnAndStartGT ( ) ) ; /* Ensure GT again as other technologies have also been polled */
gNfcDev . isTechInit = true ;
}
if ( ! rfalIsGTExpired ( ) )
{
return ERR_BUSY ;
}
devCnt = 0 ;
gNfcDev . isTechInit = false ;
gNfcDev . techs2do & = ~ RFAL_NFC_POLL_TECH_ST25TB ;
err = rfalSt25tbPollerCollisionResolution ( ( gNfcDev . disc . devLimit - gNfcDev . devCnt ) , st25tbDevList , & devCnt ) ;
if ( ( err = = ERR_NONE ) & & ( devCnt ! = 0U ) )
{
for ( i = 0 ; i < devCnt ; i + + ) /* Copy devices found form local Nfcf list into global device list */
{
gNfcDev . devList [ gNfcDev . devCnt ] . type = RFAL_NFC_LISTEN_TYPE_ST25TB ;
gNfcDev . devList [ gNfcDev . devCnt ] . dev . st25tb = st25tbDevList [ i ] ;
gNfcDev . devCnt + + ;
}
}
return ERR_BUSY ;
}
# endif /* RFAL_FEATURE_ST25TB */
return ERR_NONE ; /* All technologies have been performed */
}
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Poller Activation
*
* This method Activates a given device according to it ' s type and
* protocols supported
*
* \ param [ in ] devIt : device ' s position on the list to be activated
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcPollActivation ( uint8_t devIt )
{
ReturnCode err ;
err = ERR_NONE ;
/* Supress warning when specific RFAL features have been disabled */
NO_WARNING ( err ) ;
if ( devIt > gNfcDev . devCnt )
{
return ERR_WRONG_STATE ;
}
switch ( gNfcDev . devList [ devIt ] . type )
{
/*******************************************************************************/
/* AP2P Activation */
/*******************************************************************************/
# if RFAL_FEATURE_NFC_DEP
case RFAL_NFC_LISTEN_TYPE_AP2P :
/* Activation has already been perfomed (ATR_REQ) */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . proto . nfcDep . activation . Target . ATR_RES . NFCID3 ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCDEP_NFCID3_LEN ;
break ;
# endif /* RFAL_FEATURE_NFC_DEP */
/*******************************************************************************/
/* Passive NFC-A Activation */
/*******************************************************************************/
# if RFAL_FEATURE_NFCA
case RFAL_NFC_LISTEN_TYPE_NFCA :
if ( ! gNfcDev . isTechInit )
{
rfalNfcaPollerInitialize ( ) ;
gNfcDev . isTechInit = true ;
gNfcDev . isOperOngoing = false ;
return ERR_BUSY ;
}
if ( gNfcDev . devList [ devIt ] . dev . nfca . isSleep ) /* Check if desired device is in Sleep */
{
rfalNfcaSensRes sensRes ;
rfalNfcaSelRes selRes ;
if ( ! gNfcDev . isOperOngoing )
{
/* Wake up all cards */
EXIT_ON_ERR ( err , rfalNfcaPollerCheckPresence ( RFAL_14443A_SHORTFRAME_CMD_WUPA , & sensRes ) ) ;
gNfcDev . isOperOngoing = true ;
}
else
{
/* Select specific device */
EXIT_ON_ERR ( err , rfalNfcaPollerSelect ( gNfcDev . devList [ devIt ] . dev . nfca . nfcId1 , gNfcDev . devList [ devIt ] . dev . nfca . nfcId1Len , & selRes ) ) ;
gNfcDev . devList [ devIt ] . dev . nfca . isSleep = false ;
gNfcDev . isOperOngoing = false ;
}
return ERR_BUSY ;
}
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . nfca . nfcId1 ;
gNfcDev . devList [ devIt ] . nfcidLen = gNfcDev . devList [ devIt ] . dev . nfca . nfcId1Len ;
/*******************************************************************************/
/* Perform protocol specific activation */
switch ( gNfcDev . devList [ devIt ] . dev . nfca . type )
{
/*******************************************************************************/
case RFAL_NFCA_T1T :
/* No further activation needed for T1T (RID already performed) */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . nfca . ridRes . uid ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_T1T_UID_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ;
break ;
case RFAL_NFCA_T2T :
/* No further activation needed for a T2T */
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ;
break ;
/*******************************************************************************/
case RFAL_NFCA_T4T : /* Device supports ISO-DEP */
# if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL
if ( ! gNfcDev . isOperOngoing )
{
/* Perform ISO-DEP (ISO14443-4) activation: RATS and PPS if supported */
rfalIsoDepInitialize ( ) ;
EXIT_ON_ERR ( err , rfalIsoDepPollAStartActivation ( ( rfalIsoDepFSxI ) RFAL_ISODEP_FSDI_DEFAULT , RFAL_ISODEP_NO_DID , gNfcDev . disc . maxBR , & gNfcDev . devList [ devIt ] . proto . isoDep ) ) ;
gNfcDev . isOperOngoing = true ;
return ERR_BUSY ;
}
err = rfalIsoDepPollAGetActivationStatus ( ) ;
if ( err ! = ERR_NONE )
{
return err ;
}
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_ISODEP ; /* NFC-A T4T device activated */
# else
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* No ISO-DEP supported activate using RF interface */
# endif /* RFAL_FEATURE_ISO_DEP_POLL */
break ;
/*******************************************************************************/
case RFAL_NFCA_T4T_NFCDEP : /* Device supports both T4T and NFC-DEP */
case RFAL_NFCA_NFCDEP : /* Device supports NFC-DEP */
# if RFAL_FEATURE_NFC_DEP
/* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */
EXIT_ON_ERR ( err , rfalNfcNfcDepActivate ( & gNfcDev . devList [ devIt ] , RFAL_NFCDEP_COMM_PASSIVE , NULL , 0 ) ) ;
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . proto . nfcDep . activation . Target . ATR_RES . NFCID3 ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCDEP_NFCID3_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_NFCDEP ; /* NFC-A P2P device activated */
# else
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* No NFC-DEP supported activate using RF interface */
# endif /* RFAL_FEATURE_NFC_DEP */
break ;
/*******************************************************************************/
default :
return ERR_WRONG_STATE ;
}
break ;
# endif /* RFAL_FEATURE_NFCA */
/*******************************************************************************/
/* Passive NFC-B Activation */
/*******************************************************************************/
# if RFAL_FEATURE_NFCB
case RFAL_NFC_LISTEN_TYPE_NFCB :
if ( ! gNfcDev . isTechInit )
{
rfalNfcbPollerInitialize ( ) ;
gNfcDev . isTechInit = true ;
gNfcDev . isOperOngoing = false ;
return ERR_BUSY ;
}
if ( gNfcDev . devList [ devIt ] . dev . nfcb . isSleep ) /* Check if desired device is in Sleep */
{
rfalNfcbSensbRes sensbRes ;
uint8_t sensbResLen ;
/* Wake up all cards. SENSB_RES may return collision but the NFCID0 is available to explicitly select NFC-B card via ATTRIB; so error will be ignored here */
rfalNfcbPollerCheckPresence ( RFAL_NFCB_SENS_CMD_ALLB_REQ , RFAL_NFCB_SLOT_NUM_1 , & sensbRes , & sensbResLen ) ;
}
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . nfcb . sensbRes . nfcid0 ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCB_NFCID0_LEN ;
# if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL
/* Check if device supports ISO-DEP (ISO14443-4) */
if ( ( gNfcDev . devList [ devIt ] . dev . nfcb . sensbRes . protInfo . FsciProType & RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK ) ! = 0U )
{
if ( ! gNfcDev . isOperOngoing )
{
rfalIsoDepInitialize ( ) ;
/* Perform ISO-DEP (ISO14443-4) activation: ATTRIB */
EXIT_ON_ERR ( err , rfalIsoDepPollBStartActivation ( ( rfalIsoDepFSxI ) RFAL_ISODEP_FSDI_DEFAULT , RFAL_ISODEP_NO_DID , gNfcDev . disc . maxBR , 0x00 , & gNfcDev . devList [ devIt ] . dev . nfcb , NULL , 0 , & gNfcDev . devList [ devIt ] . proto . isoDep ) ) ;
gNfcDev . isOperOngoing = true ;
return ERR_BUSY ;
}
err = rfalIsoDepPollBGetActivationStatus ( ) ;
if ( err ! = ERR_NONE )
{
return err ;
}
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_ISODEP ; /* NFC-B T4T device activated */
break ;
}
# endif /* RFAL_FEATURE_ISO_DEP_POLL */
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* NFC-B device activated */
break ;
# endif /* RFAL_FEATURE_NFCB */
/*******************************************************************************/
/* Passive NFC-F Activation */
/*******************************************************************************/
# if RFAL_FEATURE_NFCF
case RFAL_NFC_LISTEN_TYPE_NFCF :
rfalNfcfPollerInitialize ( gNfcDev . disc . nfcfBR ) ;
# if RFAL_FEATURE_NFC_DEP
if ( rfalNfcfIsNfcDepSupported ( & gNfcDev . devList [ devIt ] . dev . nfcf ) )
{
/* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */
EXIT_ON_ERR ( err , rfalNfcNfcDepActivate ( & gNfcDev . devList [ devIt ] , RFAL_NFCDEP_COMM_PASSIVE , NULL , 0 ) ) ;
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . proto . nfcDep . activation . Target . ATR_RES . NFCID3 ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCDEP_NFCID3_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_NFCDEP ; /* NFC-F P2P device activated */
break ;
}
# endif /* RFAL_FEATURE_NFC_DEP */
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . nfcf . sensfRes . NFCID2 ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCF_NFCID2_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* NFC-F T3T device activated */
break ;
# endif /* RFAL_FEATURE_NFCF */
/*******************************************************************************/
/* Passive NFC-V Activation */
/*******************************************************************************/
# if RFAL_FEATURE_NFCV
case RFAL_NFC_LISTEN_TYPE_NFCV :
rfalNfcvPollerInitialize ( ) ;
/* No specific activation needed for a T5T */
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . nfcv . InvRes . UID ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_NFCV_UID_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* NFC-V T5T device activated */
break ;
# endif /* RFAL_FEATURE_NFCV */
/*******************************************************************************/
/* Passive ST25TB Activation */
/*******************************************************************************/
# if RFAL_FEATURE_ST25TB
case RFAL_NFC_LISTEN_TYPE_ST25TB :
rfalSt25tbPollerInitialize ( ) ;
/* No specific activation needed for a ST25TB */
/* Set NFCID */
gNfcDev . devList [ devIt ] . nfcid = gNfcDev . devList [ devIt ] . dev . st25tb . UID ;
gNfcDev . devList [ devIt ] . nfcidLen = RFAL_ST25TB_UID_LEN ;
gNfcDev . devList [ devIt ] . rfInterface = RFAL_NFC_INTERFACE_RF ; /* ST25TB device activated */
break ;
# endif /* RFAL_FEATURE_ST25TB */
/*******************************************************************************/
default :
return ERR_WRONG_STATE ;
}
gNfcDev . activeDev = & gNfcDev . devList [ devIt ] ; /* Assign active device to be used further on */
return ERR_NONE ;
}
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Listener Activation
*
* This method handles the listen mode Activation according to the different
* protocols the Reader / Initiator performs
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_PROTO : Unexpected frame received
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# if RFAL_FEATURE_LISTEN_MODE
static ReturnCode rfalNfcListenActivation ( void )
{
bool isDataRcvd ;
ReturnCode ret ;
rfalLmState lmSt ;
rfalBitRate bitRate ;
# if RFAL_FEATURE_NFC_DEP
uint8_t hdrLen ;
/* Set the header length in NFC-A */
hdrLen = ( RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN ) ;
# endif /* RFAL_FEATURE_NFC_DEP */
lmSt = rfalListenGetState ( & isDataRcvd , & bitRate ) ;
switch ( lmSt )
{
# if RFAL_FEATURE_NFCA
/*******************************************************************************/
case RFAL_LM_STATE_ACTIVE_A : /* NFC-A CE activation */
case RFAL_LM_STATE_ACTIVE_Ax :
if ( isDataRcvd ) /* Check if Reader/Initator has sent some data */
{
/* Check if received data is a Sleep request */
if ( rfalNfcaListenerIsSleepReq ( gNfcDev . rxBuf . rfBuf , rfalConvBitsToBytes ( gNfcDev . rxLen ) ) ) /* Check if received data is a SLP_REQ */
{
/* Set the Listen Mode in Sleep state */
EXIT_ON_ERR ( ret , rfalListenSleepStart ( RFAL_LM_STATE_SLEEP_A , gNfcDev . rxBuf . rfBuf , sizeof ( gNfcDev . rxBuf . rfBuf ) , & gNfcDev . rxLen ) ) ;
}
else if ( gNfcDev . disc . activate_after_sak ) {
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_NFCA ;
rfalListenSetState ( RFAL_LM_STATE_ACTIVE_A ) ;
return ERR_NONE ;
}
# if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_LISTEN
/* Check if received data is a valid RATS */
else if ( rfalIsoDepIsRats ( gNfcDev . rxBuf . rfBuf , ( uint8_t ) rfalConvBitsToBytes ( gNfcDev . rxLen ) ) )
{
rfalIsoDepAtsParam atsParam ;
rfalIsoDepListenActvParam rxParam ;
/* Set ATS parameters */
atsParam . fsci = ( uint8_t ) RFAL_ISODEP_DEFAULT_FSCI ;
atsParam . fwi = RFAL_ISODEP_DEFAULT_FWI ;
atsParam . sfgi = RFAL_ISODEP_DEFAULT_SFGI ;
atsParam . didSupport = false ;
atsParam . ta = RFAL_ISODEP_ATS_TA_SAME_D ;
atsParam . hb = NULL ;
atsParam . hbLen = 0 ;
/* Set Rx parameters */
rxParam . rxBuf = ( rfalIsoDepBufFormat * ) & gNfcDev . rxBuf . isoDepBuf ; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */
rxParam . rxLen = & gNfcDev . rxLen ;
rxParam . isoDepDev = & gNfcDev . devList - > proto . isoDep ;
rxParam . isRxChaining = & gNfcDev . isRxChaining ;
rfalListenSetState ( RFAL_LM_STATE_CARDEMU_4A ) ; /* Set next state CE T4T */
rfalIsoDepInitialize ( ) ; /* Initialize ISO-DEP layer to handle ISO14443-a activation / RATS */
/* Set ISO-DEP layer to digest RATS and handle activation */
EXIT_ON_ERR ( ret , rfalIsoDepListenStartActivation ( & atsParam , NULL , gNfcDev . rxBuf . rfBuf , gNfcDev . rxLen , rxParam ) ) ;
}
# endif /* RFAL_FEATURE_ISO_DEP_LISTEN */
# if RFAL_FEATURE_NFC_DEP
/* Check if received data is a valid ATR_REQ */
else if ( rfalNfcDepIsAtrReq ( & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) , gNfcDev . devList - > nfcid ) )
{
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_NFCA ;
EXIT_ON_ERR ( ret , rfalNfcNfcDepActivate ( gNfcDev . devList , RFAL_NFCDEP_COMM_PASSIVE , & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) ) ) ;
}
# endif /* RFAL_FEATURE_NFC_DEP */
else
{
return ERR_PROTO ;
}
}
return ERR_BUSY ;
# endif /* RFAL_FEATURE_NFCA */
# if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_LISTEN
/*******************************************************************************/
case RFAL_LM_STATE_CARDEMU_4A : /* T4T ISO-DEP activation */
ret = rfalIsoDepListenGetActivationStatus ( ) ;
if ( ret = = ERR_NONE )
{
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_NFCA ;
gNfcDev . devList - > rfInterface = RFAL_NFC_INTERFACE_ISODEP ;
gNfcDev . devList - > nfcid = NULL ;
gNfcDev . devList - > nfcidLen = 0 ;
}
return ret ;
# endif /* RFAL_FEATURE_ISO_DEP_LISTEN */
/*******************************************************************************/
case RFAL_LM_STATE_READY_F : /* NFC-F CE activation */
if ( isDataRcvd ) /* Wait for the first received data */
{
# if RFAL_FEATURE_NFC_DEP
/* Set the header length in NFC-F */
hdrLen = RFAL_NFCDEP_LEN_LEN ;
if ( rfalNfcDepIsAtrReq ( & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) , gNfcDev . devList - > nfcid ) )
{
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_NFCF ;
EXIT_ON_ERR ( ret , rfalNfcNfcDepActivate ( gNfcDev . devList , RFAL_NFCDEP_COMM_PASSIVE , & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) ) ) ;
}
else
# endif /* RFAL_FEATURE_NFC_DEP */
{
rfalListenSetState ( RFAL_LM_STATE_CARDEMU_3 ) ; /* First data already received - set T3T CE */
}
}
return ERR_BUSY ;
/*******************************************************************************/
case RFAL_LM_STATE_CARDEMU_3 : /* T3T activated */
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_NFCF ;
gNfcDev . devList - > rfInterface = RFAL_NFC_INTERFACE_RF ;
gNfcDev . devList - > nfcid = NULL ;
gNfcDev . devList - > nfcidLen = 0 ;
return ERR_NONE ;
# if RFAL_FEATURE_NFC_DEP
/*******************************************************************************/
case RFAL_LM_STATE_TARGET_A : /* NFC-DEP activation */
case RFAL_LM_STATE_TARGET_F :
ret = rfalNfcDepListenGetActivationStatus ( ) ;
if ( ret = = ERR_NONE )
{
gNfcDev . devList - > rfInterface = RFAL_NFC_INTERFACE_NFCDEP ;
gNfcDev . devList - > nfcidLen = RFAL_NFCDEP_NFCID3_LEN ;
}
return ret ;
# endif /* RFAL_FEATURE_NFC_DEP */
/*******************************************************************************/
case RFAL_LM_STATE_IDLE : /* AP2P activation */
if ( isDataRcvd ) /* Check if Reader/Initator has sent some data */
{
if ( ( gNfcDev . lmMask & RFAL_LM_MASK_ACTIVE_P2P ) ! = 0U ) /* Check if AP2P is enabled */
{
# if RFAL_FEATURE_NFC_DEP
/* Calculate the header length in NFC-A or NFC-F mode*/
hdrLen = ( ( bitRate = = RFAL_BR_106 ) ? ( RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN ) : RFAL_NFCDEP_LEN_LEN ) ;
if ( rfalNfcDepIsAtrReq ( & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) , NULL ) )
{
gNfcDev . devList - > type = RFAL_NFC_POLL_TYPE_AP2P ;
rfalSetMode ( ( RFAL_MODE_LISTEN_ACTIVE_P2P ) , bitRate , bitRate ) ;
EXIT_ON_ERR ( ret , rfalNfcNfcDepActivate ( gNfcDev . devList , RFAL_NFCDEP_COMM_ACTIVE , & gNfcDev . rxBuf . rfBuf [ hdrLen ] , ( rfalConvBitsToBytes ( gNfcDev . rxLen ) - hdrLen ) ) ) ;
}
else
# endif /* RFAL_FEATURE_NFC_DEP */
{
return ERR_PROTO ;
}
}
}
return ERR_BUSY ;
/*******************************************************************************/
case RFAL_LM_STATE_READY_A :
case RFAL_LM_STATE_READY_Ax :
case RFAL_LM_STATE_SLEEP_A :
case RFAL_LM_STATE_SLEEP_AF :
return ERR_BUSY ;
/*******************************************************************************/
case RFAL_LM_STATE_POWER_OFF :
return ERR_LINK_LOSS ;
default : /* Wait for activation */
break ;
}
return ERR_INTERNAL ;
}
# endif /* RFAL_FEATURE_LISTEN_MODE */
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Poller NFC DEP Activate
*
* This method performs NFC - DEP Activation
*
* \ param [ in ] device : device info
* \ param [ in ] commMode : communication mode ( Passive / Active )
* \ param [ in ] atrReq : received ATR_REQ
* \ param [ in ] atrReqLen : received ATR_REQ size
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# if RFAL_FEATURE_NFC_DEP
static ReturnCode rfalNfcNfcDepActivate ( rfalNfcDevice * device , rfalNfcDepCommMode commMode , const uint8_t * atrReq , uint16_t atrReqLen )
{
rfalNfcDepAtrParam initParam ;
/* Supress warnings if Listen mode is disabled */
NO_WARNING ( atrReq ) ;
NO_WARNING ( atrReqLen ) ;
/* If we are in Poll mode */
if ( rfalNfcIsRemDevListener ( device - > type ) )
{
/*******************************************************************************/
/* If Passive F use the NFCID2 retrieved from SENSF */
if ( device - > type = = RFAL_NFC_LISTEN_TYPE_NFCF )
{
initParam . nfcid = device - > dev . nfcf . sensfRes . NFCID2 ;
initParam . nfcidLen = RFAL_NFCF_NFCID2_LEN ;
}
else
{
initParam . nfcid = gNfcDev . disc . nfcid3 ;
initParam . nfcidLen = RFAL_NFCDEP_NFCID3_LEN ;
}
initParam . BS = RFAL_NFCDEP_Bx_NO_HIGH_BR ;
initParam . BR = RFAL_NFCDEP_Bx_NO_HIGH_BR ;
initParam . DID = RFAL_NFCDEP_DID_NO ;
initParam . NAD = RFAL_NFCDEP_NAD_NO ;
initParam . LR = RFAL_NFCDEP_LR_254 ;
initParam . GB = gNfcDev . disc . GB ;
initParam . GBLen = gNfcDev . disc . GBLen ;
initParam . commMode = commMode ;
initParam . operParam = ( RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN ) ;
rfalNfcDepInitialize ( ) ;
/* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */
return rfalNfcDepInitiatorHandleActivation ( & initParam , gNfcDev . disc . maxBR , & device - > proto . nfcDep ) ;
}
/* If we are in Listen mode */
# if RFAL_FEATURE_LISTEN_MODE
else if ( rfalNfcIsRemDevPoller ( device - > type ) )
{
rfalNfcDepListenActvParam actvParams ;
rfalNfcDepTargetParam targetParam ;
ST_MEMCPY ( targetParam . nfcid3 , ( uint8_t * ) gNfcDev . disc . nfcid3 , RFAL_NFCDEP_NFCID3_LEN ) ;
targetParam . bst = RFAL_NFCDEP_Bx_NO_HIGH_BR ;
targetParam . brt = RFAL_NFCDEP_Bx_NO_HIGH_BR ;
targetParam . to = RFAL_NFCDEP_WT_TRG_MAX_L13 ; /* [LLCP] 1.3 6.2.1 */
targetParam . ppt = rfalNfcDepLR2PP ( RFAL_NFCDEP_LR_254 ) ;
if ( gNfcDev . disc . GBLen > = RFAL_NFCDEP_GB_MAX_LEN )
{
return ERR_PARAM ;
}
targetParam . GBtLen = gNfcDev . disc . GBLen ;
if ( gNfcDev . disc . GBLen > 0U )
{
ST_MEMCPY ( targetParam . GBt , gNfcDev . disc . GB , gNfcDev . disc . GBLen ) ;
}
targetParam . operParam = ( RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN ) ;
targetParam . commMode = commMode ;
/* Set activation buffer (including header) for NFC-DEP */
actvParams . rxBuf = ( rfalNfcDepBufFormat * ) & gNfcDev . rxBuf . nfcDepBuf ; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */
actvParams . rxLen = & gNfcDev . rxLen ;
actvParams . isRxChaining = & gNfcDev . isRxChaining ;
actvParams . nfcDepDev = & gNfcDev . devList - > proto . nfcDep ;
rfalListenSetState ( ( ( device - > type = = RFAL_NFC_POLL_TYPE_NFCA ) ? RFAL_LM_STATE_TARGET_A : RFAL_LM_STATE_TARGET_F ) ) ;
rfalNfcDepInitialize ( ) ;
/* Perform NFC-DEP (P2P) activation: send ATR_RES and handle activation */
return rfalNfcDepListenStartActivation ( & targetParam , atrReq , atrReqLen , actvParams ) ;
}
# endif /* RFAL_FEATURE_LISTEN_MODE */
else
{
return ERR_INTERNAL ;
}
}
# endif /* RFAL_FEATURE_NFC_DEP */
/*!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* \ brief Poller NFC Deactivate
*
* This method Deactivates the device if a deactivation procedure exists
*
* \ return ERR_NONE : Operation completed with no error
* \ return ERR_BUSY : Operation ongoing
* \ return ERR_XXXX : Error occurred
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcDeactivation ( void )
{
/* Check if a device has been activated */
if ( gNfcDev . activeDev ! = NULL )
{
if ( rfalNfcIsRemDevListener ( gNfcDev . activeDev - > type ) ) /* Listen mode no additional deactivation to be performed*/
{
# ifndef RFAL_NFC_SKIP_DEACT
switch ( gNfcDev . activeDev - > rfInterface )
{
/*******************************************************************************/
case RFAL_NFC_INTERFACE_RF :
break ; /* No specific deactivation to be performed */
/*******************************************************************************/
# if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL
case RFAL_NFC_INTERFACE_ISODEP :
rfalIsoDepDeselect ( ) ; /* Send a Deselect to device */
break ;
# endif /* RFAL_FEATURE_ISO_DEP_POLL */
/*******************************************************************************/
# if RFAL_FEATURE_NFC_DEP
case RFAL_NFC_INTERFACE_NFCDEP :
switch ( gNfcDev . activeDev - > type )
{
case RFAL_NFC_LISTEN_TYPE_AP2P :
rfalNfcDepRLS ( ) ; /* Send a Release to device */
break ;
default :
rfalNfcDepDSL ( ) ; /* Send a Deselect to device */
break ;
}
break ;
# endif /* RFAL_FEATURE_NFC_DEP */
default :
return ERR_REQUEST ;
}
# endif /* RFAL_NFC_SKIP_DEACT */
}
}
# if RFAL_FEATURE_WAKEUP_MODE
rfalWakeUpModeStop ( ) ;
# endif /* RFAL_FEATURE_WAKEUP_MODE */
# if RFAL_FEATURE_LISTEN_MODE
rfalListenStop ( ) ;
# else
rfalFieldOff ( ) ;
# endif
gNfcDev . activeDev = NULL ;
return ERR_NONE ;
}