2021-10-17 22:54:19 +00: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_nfcv.c
*
* \ author Gustavo Patricio
*
* \ brief Implementation of NFC - V Poller ( ISO15693 ) device
*
* The definitions and helpers methods provided by this module are
* aligned with NFC - V ( ISO15693 )
*
* The definitions and helpers methods provided by this module
* are aligned with NFC - V Digital 2.1
*
*/
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* INCLUDES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# include "rfal_nfcv.h"
# include "utils.h"
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ENABLE SWITCH
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# ifndef RFAL_FEATURE_NFCV
# define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
# endif
# if RFAL_FEATURE_NFCV
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL DEFINES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# define RFAL_NFCV_INV_REQ_FLAG 0x06U /*!< INVENTORY_REQ INV_FLAG Digital 2.1 9.6.1 */
# define RFAL_NFCV_MASKVAL_MAX_LEN 8U /*!< Mask value max length: 64 bits (UID length) */
# define RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN 64U /*!< Mask value max length in 1 Slot mode in bits Digital 2.1 9.6.1.6 */
# define RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN 60U /*!< Mask value max length in 16 Slot mode in bits Digital 2.1 9.6.1.6 */
# define RFAL_NFCV_MAX_SLOTS 16U /*!< NFC-V max number of Slots */
# define RFAL_NFCV_INV_REQ_HEADER_LEN 3U /*!< INVENTORY_REQ header length (INV_FLAG, CMD, MASK_LEN) */
# define RFAL_NFCV_INV_RES_LEN 10U /*!< INVENTORY_RES length */
# define RFAL_NFCV_WR_MUL_REQ_HEADER_LEN 4U /*!< Write Multiple header length (INV_FLAG, CMD, [UID], BNo, Bno) */
# define RFAL_NFCV_CMD_LEN 1U /*!< Commandbyte length */
# define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */
# define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */
# define RFAL_NFCV_DATASTART_POS 1U /*!< Position of start of data */
# define RFAL_NFCV_DSFI_LEN 1U /*!< DSFID length */
# define RFAL_NFCV_SLPREQ_REQ_FLAG 0x22U /*!< SLPV_REQ request flags Digital 2.0 (Candidate) 9.7.1.1 */
# define RFAL_NFCV_RES_FLAG_NOERROR 0x00U /*!< RES_FLAG indicating no error (checked during activation) */
# define RFAL_NFCV_MAX_COLL_SUPPORTED 16U /*!< Maximum number of collisions supported by the Anticollision loop */
# define RFAL_NFCV_FDT_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF and MAX2 Digital 2.1 B.5*/
# define RFAL_NFCV_FDT_MAX1 4394U /*!< Read alike command FWT FDTV,LISTEN,MAX1 Digital 2.0 B.5 */
/*! Time from special frame to EOF
* ISO15693 2009 10.4 .2 : 20 ms
* NFC Forum defines Digital 2.0 9.7 .4 : FDTV , EOF = [ 10 ; 20 ] ms
*/
# define RFAL_NFCV_FDT_EOF 20U
/*! Time between slots - ISO 15693 defines t3min depending on modulation depth and data rate.
* With only high - bitrate supported , AM modulation and a length of 12 bytes ( 96 bits ) for INV_RES we get :
* - ISO t3min = 96 / 26 ms + 300u s = 4 ms
* - NFC Forum defines FDTV , INVENT_NORES = ( 4394 + 2048 ) / fc . Digital 2.0 B .5 */
# define RFAL_NFCV_FDT_V_INVENT_NORES 4U
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL MACROS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! Checks if a valid INVENTORY_RES is valid Digital 2.2 9.6.2.1 & 9.6.2.3 */
# define rfalNfcvCheckInvRes( f, l ) (((l)==rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN)) && ((f)==RFAL_NFCV_RES_FLAG_NOERROR))
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL TYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */
typedef struct
{
uint8_t INV_FLAG ; /*!< Inventory Flags */
uint8_t CMD ; /*!< Command code: 01h */
uint8_t MASK_LEN ; /*!< Mask Value Length */
uint8_t MASK_VALUE [ RFAL_NFCV_MASKVAL_MAX_LEN ] ; /*!< Mask Value */
} rfalNfcvInventoryReq ;
/*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */
typedef struct
{
uint8_t REQ_FLAG ; /*!< Request Flags */
uint8_t CMD ; /*!< Command code: 02h */
uint8_t UID [ RFAL_NFCV_UID_LEN ] ; /*!< Mask Value */
} rfalNfcvSlpvReq ;
/*! Container for a collision found during Anticollision loop */
typedef struct
{
uint8_t maskLen ;
uint8_t maskVal [ RFAL_NFCV_MASKVAL_MAX_LEN ] ;
} rfalNfcvCollision ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTION PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static ReturnCode rfalNfcvParseError ( uint8_t err ) ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL VARIABLES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*******************************************************************************/
static ReturnCode rfalNfcvParseError ( uint8_t err )
{
switch ( err )
{
case RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED :
case RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED :
return ERR_NOTSUPP ;
case RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED :
return ERR_PROTO ;
case RFAL_NFCV_ERROR_WRITE_FAILED :
return ERR_WRITE ;
default :
return ERR_REQUEST ;
}
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*******************************************************************************/
ReturnCode rfalNfcvPollerInitialize ( void )
{
ReturnCode ret ;
EXIT_ON_ERR ( ret , rfalSetMode ( RFAL_MODE_POLL_NFCV , RFAL_BR_26p48 , RFAL_BR_26p48 ) ) ;
rfalSetErrorHandling ( RFAL_ERRORHANDLING_NFC ) ;
rfalSetGT ( RFAL_GT_NFCV ) ;
rfalSetFDTListen ( RFAL_FDT_LISTEN_NFCV_POLLER ) ;
rfalSetFDTPoll ( RFAL_FDT_POLL_NFCV_POLLER ) ;
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerCheckPresence ( rfalNfcvInventoryRes * invRes )
{
ReturnCode ret ;
/* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */
ret = rfalNfcvPollerInventory ( RFAL_NFCV_NUM_SLOTS_1 , 0 , NULL , invRes , NULL ) ;
if ( ( ret = = ERR_RF_COLLISION ) | | ( ret = = ERR_CRC ) | |
( ret = = ERR_FRAMING ) | | ( ret = = ERR_PROTO ) )
{
ret = ERR_NONE ;
}
return ret ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerInventory ( rfalNfcvNumSlots nSlots , uint8_t maskLen , const uint8_t * maskVal , rfalNfcvInventoryRes * invRes , uint16_t * rcvdLen )
{
ReturnCode ret ;
rfalNfcvInventoryReq invReq ;
uint16_t rxLen ;
if ( ( ( maskVal = = NULL ) & & ( maskLen ! = 0U ) ) | | ( invRes = = NULL ) )
{
return ERR_PARAM ;
}
invReq . INV_FLAG = ( RFAL_NFCV_INV_REQ_FLAG | ( uint8_t ) nSlots ) ;
invReq . CMD = RFAL_NFCV_CMD_INVENTORY ;
invReq . MASK_LEN = ( uint8_t ) MIN ( maskLen , ( ( nSlots = = RFAL_NFCV_NUM_SLOTS_1 ) ? RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN : RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN ) ) ; /* Digital 2.0 9.6.1.6 */
if ( ( rfalConvBitsToBytes ( invReq . MASK_LEN ) > 0U ) & & ( maskVal ! = NULL ) ) /* MISRA 21.18 & 1.3 */
{
ST_MEMCPY ( invReq . MASK_VALUE , maskVal , rfalConvBitsToBytes ( invReq . MASK_LEN ) ) ;
}
ret = rfalISO15693TransceiveAnticollisionFrame ( ( uint8_t * ) & invReq , ( uint8_t ) ( RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes ( invReq . MASK_LEN ) ) , ( uint8_t * ) invRes , sizeof ( rfalNfcvInventoryRes ) , & rxLen ) ;
/* Check for optional output parameter */
if ( rcvdLen ! = NULL )
{
* rcvdLen = rxLen ;
}
if ( ret = = ERR_NONE )
{
/* Check for valid INVENTORY_RES Digital 2.2 9.6.2.1 & 9.6.2.3 */
if ( ! rfalNfcvCheckInvRes ( invRes - > RES_FLAG , rxLen ) )
{
return ERR_PROTO ;
}
}
return ret ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerCollisionResolution ( rfalComplianceMode compMode , uint8_t devLimit , rfalNfcvListenDevice * nfcvDevList , uint8_t * devCnt )
{
ReturnCode ret ;
uint8_t slotNum ;
uint16_t rcvdLen ;
uint8_t colIt ;
uint8_t colCnt ;
uint8_t colPos ;
bool colPending ;
rfalNfcvCollision colFound [ RFAL_NFCV_MAX_COLL_SUPPORTED ] ;
if ( ( nfcvDevList = = NULL ) | | ( devCnt = = NULL ) )
{
return ERR_PARAM ;
}
/* Initialize parameters */
* devCnt = 0 ;
colIt = 0 ;
colCnt = 0 ;
colPending = false ;
ST_MEMSET ( colFound , 0x00 , ( sizeof ( rfalNfcvCollision ) * RFAL_NFCV_MAX_COLL_SUPPORTED ) ) ;
if ( devLimit > 0U ) /* MISRA 21.18 */
{
ST_MEMSET ( nfcvDevList , 0x00 , ( sizeof ( rfalNfcvListenDevice ) * devLimit ) ) ;
}
NO_WARNING ( colPending ) ; /* colPending is not exposed externally, in future it might become exposed/ouput parameter */
if ( compMode = = RFAL_COMPLIANCE_MODE_NFC )
{
/* Send INVENTORY_REQ with one slot Activity 2.1 9.3.7.1 (Symbol 0) */
ret = rfalNfcvPollerInventory ( RFAL_NFCV_NUM_SLOTS_1 , 0 , NULL , & nfcvDevList - > InvRes , NULL ) ;
if ( ret = = ERR_TIMEOUT ) /* Exit if no device found Activity 2.1 9.3.7.2 (Symbol 1) */
{
return ERR_NONE ;
}
if ( ret = = ERR_NONE ) /* Device found without transmission error/collision Activity 2.1 9.3.7.3 (Symbol 2) */
{
( * devCnt ) + + ;
return ERR_NONE ;
}
/* A Collision has been identified Activity 2.1 9.3.7.4 (Symbol 3) */
colPending = true ;
colCnt = 1 ;
/* Check if the Collision Resolution is set to perform only Collision detection Activity 2.1 9.3.7.5 (Symbol 4)*/
if ( devLimit = = 0U )
{
return ERR_RF_COLLISION ;
}
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
/*******************************************************************************/
/* Collisions pending, Anticollision loop must be executed */
/*******************************************************************************/
}
else
{
/* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */
colPending = true ;
colCnt = 1 ;
}
/* Execute until all collisions are resolved Activity 2.1 9.3.7.18 (Symbol 17) */
do
{
/* Activity 2.1 9.3.7.7 (Symbol 6 / 7) */
colPending = false ;
slotNum = 0 ;
do
{
if ( slotNum = = 0U )
{
/* Send INVENTORY_REQ with 16 slots Activity 2.1 9.3.7.9 (Symbol 8) */
ret = rfalNfcvPollerInventory ( RFAL_NFCV_NUM_SLOTS_16 , colFound [ colIt ] . maskLen , colFound [ colIt ] . maskVal , & nfcvDevList [ ( * devCnt ) ] . InvRes , & rcvdLen ) ;
}
else
{
ret = rfalISO15693TransceiveEOFAnticollision ( ( uint8_t * ) & nfcvDevList [ ( * devCnt ) ] . InvRes , sizeof ( rfalNfcvInventoryRes ) , & rcvdLen ) ;
}
slotNum + + ;
/*******************************************************************************/
if ( ret ! = ERR_TIMEOUT )
{
if ( rcvdLen < rfalConvBytesToBits ( RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN ) )
{ /* If only a partial frame was received make sure the FDT_V_INVENT_NORES is fulfilled */
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
}
/* Check if response is a correct frame (no TxRx error) Activity 2.1 9.3.7.11 (Symbol 10)*/
if ( ( ret = = ERR_NONE ) | | ( ret = = ERR_PROTO ) )
{
/* Check if the device found is already on the list and its response is a valid INVENTORY_RES */
if ( rfalNfcvCheckInvRes ( nfcvDevList [ ( * devCnt ) ] . InvRes . RES_FLAG , rcvdLen ) )
{
/* Activity 2.1 9.3.7.12 (Symbol 11) */
( * devCnt ) + + ;
}
}
else /* Treat everything else as collision */
{
/* Activity 2.1 9.3.7.17 (Symbol 16) */
colPending = true ;
/*******************************************************************************/
/* Ensure that this collision still fits on the container */
if ( colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED )
{
/* Store this collision on the container to be resolved later */
/* Activity 2.1 9.3.7.17 (Symbol 16): add the collision information
* ( MASK_VAL + SN ) to the list containing the collision information */
ST_MEMCPY ( colFound [ colCnt ] . maskVal , colFound [ colIt ] . maskVal , RFAL_NFCV_UID_LEN ) ;
colPos = colFound [ colIt ] . maskLen ;
colFound [ colCnt ] . maskVal [ ( colPos / RFAL_BITS_IN_BYTE ) ] & = ( uint8_t ) ( ( 1U < < ( colPos % RFAL_BITS_IN_BYTE ) ) - 1U ) ;
colFound [ colCnt ] . maskVal [ ( colPos / RFAL_BITS_IN_BYTE ) ] | = ( uint8_t ) ( ( slotNum - 1U ) < < ( colPos % RFAL_BITS_IN_BYTE ) ) ;
colFound [ colCnt ] . maskVal [ ( ( colPos / RFAL_BITS_IN_BYTE ) + 1U ) ] = ( uint8_t ) ( ( slotNum - 1U ) > > ( RFAL_BITS_IN_BYTE - ( colPos % RFAL_BITS_IN_BYTE ) ) ) ;
colFound [ colCnt ] . maskLen = ( colFound [ colIt ] . maskLen + 4U ) ;
colCnt + + ;
}
}
}
else
{
/* Timeout */
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
}
/* Check if devices found have reached device limit Activity 2.1 9.3.7.13 (Symbol 12) */
if ( * devCnt > = devLimit )
{
return ERR_NONE ;
}
} while ( slotNum < RFAL_NFCV_MAX_SLOTS ) ; /* Slot loop */
colIt + + ;
} while ( colIt < colCnt ) ; /* Collisions found loop */
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSleepCollisionResolution ( uint8_t devLimit , rfalNfcvListenDevice * nfcvDevList , uint8_t * devCnt )
{
uint8_t tmpDevCnt ;
ReturnCode ret ;
uint8_t i ;
if ( ( nfcvDevList = = NULL ) | | ( devCnt = = NULL ) )
{
return ERR_PARAM ;
}
* devCnt = 0 ;
do
{
tmpDevCnt = 0 ;
ret = rfalNfcvPollerCollisionResolution ( RFAL_COMPLIANCE_MODE_ISO , ( devLimit - * devCnt ) , & nfcvDevList [ * devCnt ] , & tmpDevCnt ) ;
for ( i = * devCnt ; i < ( * devCnt + tmpDevCnt ) ; i + + )
{
rfalNfcvPollerSleep ( 0x00 , nfcvDevList [ i ] . InvRes . UID ) ;
nfcvDevList [ i ] . isSleep = true ;
}
* devCnt + = tmpDevCnt ;
}
while ( ( ret = = ERR_NONE ) & & ( tmpDevCnt > 0U ) & & ( * devCnt < devLimit ) ) ;
return ret ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSleep ( uint8_t flags , const uint8_t * uid )
{
ReturnCode ret ;
rfalNfcvSlpvReq slpReq ;
uint8_t rxBuf ; /* dummy buffer, just to perform Rx */
if ( uid = = NULL )
{
return ERR_PARAM ;
}
/* Compute SLPV_REQ */
slpReq . REQ_FLAG = ( flags | ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ; /* Should be with UID according Digital 2.0 (Candidate) 9.7.1.1 */
slpReq . CMD = RFAL_NFCV_CMD_SLPV ;
ST_MEMCPY ( slpReq . UID , uid , RFAL_NFCV_UID_LEN ) ;
/* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */
ret = rfalTransceiveBlockingTxRx ( ( uint8_t * ) & slpReq , sizeof ( rfalNfcvSlpvReq ) , & rxBuf , sizeof ( rxBuf ) , NULL , RFAL_TXRX_FLAGS_DEFAULT , RFAL_NFCV_FDT_MAX1 ) ;
if ( ret ! = ERR_TIMEOUT )
{
return ret ;
}
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSelect ( uint8_t flags , const uint8_t * uid )
{
uint16_t rcvLen ;
rfalNfcvGenericRes res ;
if ( uid = = NULL )
{
return ERR_PARAM ;
}
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_SELECT , flags , RFAL_NFCV_PARAM_SKIP , uid , NULL , 0U , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerReadSingleBlock ( uint8_t flags , const uint8_t * uid , uint8_t blockNum , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
uint8_t bn ;
bn = blockNum ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_READ_SINGLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , & bn , sizeof ( uint8_t ) , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerWriteSingleBlock ( uint8_t flags , const uint8_t * uid , uint8_t blockNum , const uint8_t * wrData , uint8_t blockLen )
{
uint8_t data [ ( RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_MAX_BLOCK_LEN ) ] ;
uint8_t dataLen ;
uint16_t rcvLen ;
rfalNfcvGenericRes res ;
/* Check for valid parameters */
if ( ( blockLen = = 0U ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) | | ( wrData = = NULL ) )
{
return ERR_PARAM ;
}
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = blockNum ; /* Set Block Number (8 bits) */
ST_MEMCPY ( & data [ dataLen ] , wrData , blockLen ) ; /* Append Block data to write */
dataLen + = blockLen ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerLockBlock ( uint8_t flags , const uint8_t * uid , uint8_t blockNum )
{
uint16_t rcvLen ;
rfalNfcvGenericRes res ;
uint8_t bn ;
bn = blockNum ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_LOCK_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , & bn , sizeof ( uint8_t ) , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerReadMultipleBlocks ( uint8_t flags , const uint8_t * uid , uint8_t firstBlockNum , uint8_t numOfBlocks , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
uint8_t data [ ( RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN ) ] ;
uint8_t dataLen ;
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = firstBlockNum ; /* Set first Block Number */
data [ dataLen + + ] = numOfBlocks ; /* Set number of blocks to read */
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerWriteMultipleBlocks ( uint8_t flags , const uint8_t * uid , uint8_t firstBlockNum , uint8_t numOfBlocks , uint8_t * txBuf , uint16_t txBufLen , uint8_t blockLen , const uint8_t * wrData , uint16_t wrDataLen )
{
ReturnCode ret ;
uint16_t rcvLen ;
uint16_t reqLen ;
rfalNfcvGenericRes res ;
uint16_t msgIt ;
/* Calculate required buffer length */
reqLen = ( uint16_t ) ( ( uid ! = NULL ) ? ( RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen ) : ( RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen ) ) ;
if ( ( reqLen > txBufLen ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) | | ( ( ( ( uint16_t ) numOfBlocks ) * ( uint16_t ) blockLen ) ! = wrDataLen ) | | ( numOfBlocks = = 0U ) | | ( wrData = = NULL ) )
{
return ERR_PARAM ;
}
msgIt = 0 ;
/* Compute Request Command */
txBuf [ msgIt + + ] = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
txBuf [ msgIt + + ] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS ;
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if ( uid ! = NULL )
{
txBuf [ RFAL_NFCV_FLAG_POS ] | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
ST_MEMCPY ( & txBuf [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
msgIt + = ( uint8_t ) RFAL_NFCV_UID_LEN ;
}
txBuf [ msgIt + + ] = firstBlockNum ;
txBuf [ msgIt + + ] = ( numOfBlocks - 1U ) ;
if ( wrDataLen > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY ( & txBuf [ msgIt ] , wrData , wrDataLen ) ;
msgIt + = wrDataLen ;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx ( txBuf , msgIt , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen , RFAL_TXRX_FLAGS_DEFAULT , RFAL_NFCV_FDT_MAX ) ;
if ( ret ! = ERR_NONE )
{
return ret ;
}
/* Check if the response minimum length has been received */
if ( rcvLen < ( uint8_t ) RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO ;
}
/* Check if an error has been signalled */
if ( ( res . RES_FLAG & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U )
{
return rfalNfcvParseError ( * res . data ) ;
}
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedReadSingleBlock ( uint8_t flags , const uint8_t * uid , uint16_t blockNum , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
uint8_t data [ RFAL_NFCV_BLOCKNUM_EXTENDED_LEN ] ;
uint8_t dataLen ;
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = ( uint8_t ) blockNum ; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedWriteSingleBlock ( uint8_t flags , const uint8_t * uid , uint16_t blockNum , const uint8_t * wrData , uint8_t blockLen )
{
uint8_t data [ ( RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_MAX_BLOCK_LEN ) ] ;
uint8_t dataLen ;
uint16_t rcvLen ;
rfalNfcvGenericRes res ;
/* Check for valid parameters */
if ( ( blockLen = = 0U ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) )
{
return ERR_PARAM ;
}
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = ( uint8_t ) blockNum ; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
ST_MEMCPY ( & data [ dataLen ] , wrData , blockLen ) ; /* Append Block data to write */
dataLen + = blockLen ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedLockSingleBlock ( uint8_t flags , const uint8_t * uid , uint16_t blockNum )
{
uint8_t data [ RFAL_NFCV_BLOCKNUM_EXTENDED_LEN ] ;
uint8_t dataLen ;
uint16_t rcvLen ;
rfalNfcvGenericRes res ;
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = ( uint8_t ) blockNum ; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks ( uint8_t flags , const uint8_t * uid , uint16_t firstBlockNum , uint16_t numOfBlocks , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
uint8_t data [ ( RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN ) ] ;
uint8_t dataLen ;
dataLen = 0U ;
/* Compute Request Data */
data [ dataLen + + ] = ( uint8_t ) ( ( firstBlockNum > > 0U ) & 0xFFU ) ;
data [ dataLen + + ] = ( uint8_t ) ( ( firstBlockNum > > 8U ) & 0xFFU ) ;
data [ dataLen + + ] = ( uint8_t ) ( ( numOfBlocks > > 0U ) & 0xFFU ) ;
data [ dataLen + + ] = ( uint8_t ) ( ( numOfBlocks > > 8U ) & 0xFFU ) ;
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK , flags , RFAL_NFCV_PARAM_SKIP , uid , data , dataLen , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedWriteMultipleBlocks ( uint8_t flags , const uint8_t * uid , uint16_t firstBlockNum , uint16_t numOfBlocks , uint8_t * txBuf , uint16_t txBufLen , uint8_t blockLen , const uint8_t * wrData , uint16_t wrDataLen )
{
ReturnCode ret ;
uint16_t rcvLen ;
uint16_t reqLen ;
rfalNfcvGenericRes res ;
uint16_t msgIt ;
uint16_t nBlocks ;
/* Calculate required buffer length */
reqLen = ( ( uid ! = NULL ) ? ( RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen ) : ( RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen ) ) ;
if ( ( reqLen > txBufLen ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) | | ( ( ( uint16_t ) numOfBlocks * ( uint16_t ) blockLen ) ! = wrDataLen ) | | ( numOfBlocks = = 0U ) )
{
return ERR_PARAM ;
}
msgIt = 0 ;
nBlocks = ( numOfBlocks - 1U ) ;
/* Compute Request Command */
txBuf [ msgIt + + ] = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
txBuf [ msgIt + + ] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK ;
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if ( uid ! = NULL )
{
txBuf [ RFAL_NFCV_FLAG_POS ] | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
ST_MEMCPY ( & txBuf [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
msgIt + = ( uint8_t ) RFAL_NFCV_UID_LEN ;
}
txBuf [ msgIt + + ] = ( uint8_t ) ( ( firstBlockNum > > 0 ) & 0xFFU ) ;
txBuf [ msgIt + + ] = ( uint8_t ) ( ( firstBlockNum > > 8 ) & 0xFFU ) ;
txBuf [ msgIt + + ] = ( uint8_t ) ( ( nBlocks > > 0 ) & 0xFFU ) ;
txBuf [ msgIt + + ] = ( uint8_t ) ( ( nBlocks > > 8 ) & 0xFFU ) ;
if ( wrDataLen > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY ( & txBuf [ msgIt ] , wrData , wrDataLen ) ;
msgIt + = wrDataLen ;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx ( txBuf , msgIt , ( uint8_t * ) & res , sizeof ( rfalNfcvGenericRes ) , & rcvLen , RFAL_TXRX_FLAGS_DEFAULT , RFAL_NFCV_FDT_MAX ) ;
if ( ret ! = ERR_NONE )
{
return ret ;
}
/* Check if the response minimum length has been received */
if ( rcvLen < ( uint8_t ) RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO ;
}
/* Check if an error has been signalled */
if ( ( res . RES_FLAG & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U )
{
return rfalNfcvParseError ( * res . data ) ;
}
return ERR_NONE ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerGetSystemInformation ( uint8_t flags , const uint8_t * uid , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_GET_SYS_INFO , flags , RFAL_NFCV_PARAM_SKIP , uid , NULL , 0U , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedGetSystemInformation ( uint8_t flags , const uint8_t * uid , uint8_t requestField , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
return rfalNfcvPollerTransceiveReq ( RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO , flags , requestField , uid , NULL , 0U , rxBuf , rxBufLen , rcvLen ) ;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerTransceiveReq ( uint8_t cmd , uint8_t flags , uint8_t param , const uint8_t * uid , const uint8_t * data , uint16_t dataLen , uint8_t * rxBuf , uint16_t rxBufLen , uint16_t * rcvLen )
{
ReturnCode ret ;
rfalNfcvGenericReq req ;
uint8_t msgIt ;
rfalBitRate rxBR ;
bool fastMode ;
msgIt = 0 ;
fastMode = false ;
/* Check for valid parameters */
if ( ( rxBuf = = NULL ) | | ( rcvLen = = NULL ) | | ( ( dataLen > 0U ) & & ( data = = NULL ) ) | |
( dataLen > ( ( uid ! = NULL ) ? RFAL_NFCV_MAX_GEN_DATA_LEN : ( RFAL_NFCV_MAX_GEN_DATA_LEN - RFAL_NFCV_UID_LEN ) ) ) )
{
return ERR_PARAM ;
}
/* Check if the command is an ST's Fast command */
if ( ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_WRITE_MESSAGE ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_READ_MESSAGE ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION ) )
{
/* Store current Rx bit rate and move to fast mode */
rfalGetBitRate ( NULL , & rxBR ) ;
rfalSetBitRate ( RFAL_BR_KEEP , RFAL_BR_52p97 ) ;
fastMode = true ;
}
/* Compute Request Command */
req . REQ_FLAG = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
req . CMD = cmd ;
/* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */
if ( param ! = RFAL_NFCV_PARAM_SKIP )
{
req . payload . data [ msgIt + + ] = param ;
}
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if ( uid ! = NULL )
{
req . REQ_FLAG | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
ST_MEMCPY ( & req . payload . data [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
msgIt + = RFAL_NFCV_UID_LEN ;
}
if ( dataLen > 0U )
{
ST_MEMCPY ( & req . payload . data [ msgIt ] , data , dataLen ) ;
msgIt + = ( uint8_t ) dataLen ;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx ( ( uint8_t * ) & req , ( RFAL_NFCV_CMD_LEN + RFAL_NFCV_FLAG_LEN + ( uint16_t ) msgIt ) , rxBuf , rxBufLen , rcvLen , RFAL_TXRX_FLAGS_DEFAULT , RFAL_NFCV_FDT_MAX ) ;
/* If the Option Flag is set in certain commands an EOF needs to be sent after 20ms to retrieve the VICC response ISO15693-3 2009 10.4.2 & 10.4.3 & 10.4.5 */
if ( ( ( flags & ( uint8_t ) RFAL_NFCV_REQ_FLAG_OPTION ) ! = 0U ) & & ( ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_LOCK_BLOCK ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK ) | |
( cmd = = ( uint8_t ) RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK ) | | ( cmd = = ( uint8_t ) RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK ) ) )
{
ret = rfalISO15693TransceiveEOF ( rxBuf , ( uint8_t ) rxBufLen , rcvLen ) ;
}
/* Restore Rx BitRate */
if ( fastMode )
{
rfalSetBitRate ( RFAL_BR_KEEP , rxBR ) ;
}
if ( ret ! = ERR_NONE )
{
return ret ;
}
/* Check if the response minimum length has been received */
if ( ( * rcvLen ) < ( uint8_t ) RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO ;
}
/* Check if an error has been signalled */
if ( ( rxBuf [ RFAL_NFCV_FLAG_POS ] & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U )
{
return rfalNfcvParseError ( rxBuf [ RFAL_NFCV_DATASTART_POS ] ) ;
}
return ERR_NONE ;
}
# endif /* RFAL_FEATURE_NFCV */