2021-10-18 01:54:19 +03:00
/******************************************************************************
* \ attention
*
* < h2 > < center > & copy ; COPYRIGHT 2020 STMicroelectronics < / center > < / h2 >
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT ( the " License " ) ;
* You may not use this file except in compliance with the License .
* You may obtain a copy of the License at :
*
* www . st . com / myliberty
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied ,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE , AND NON - INFRINGEMENT .
* See the License for the specific language governing permissions and
* limitations under the License .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* PROJECT : ST25R391x firmware
* Revision :
* LANGUAGE : ISO C99
*/
/*! \file rfal_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
2022-01-05 19:10:18 +03:00
# define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
2021-10-18 01:54:19 +03:00
# endif
# if RFAL_FEATURE_NFCV
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL DEFINES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
# 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 */
2021-10-18 01:54:19 +03:00
/*! 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
*/
2022-01-05 19:10:18 +03:00
# define RFAL_NFCV_FDT_EOF 20U
2021-10-18 01:54:19 +03:00
/*! 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 */
2022-01-05 19:10:18 +03:00
# define RFAL_NFCV_FDT_V_INVENT_NORES 4U
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL MACROS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
/*! 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 ) )
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL TYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */
2022-01-05 19:10:18 +03:00
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 */
2021-10-18 01:54:19 +03:00
} rfalNfcvInventoryReq ;
/*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */
2022-01-05 19:10:18 +03:00
typedef struct {
uint8_t REQ_FLAG ; /*!< Request Flags */
uint8_t CMD ; /*!< Command code: 02h */
uint8_t UID [ RFAL_NFCV_UID_LEN ] ; /*!< Mask Value */
2021-10-18 01:54:19 +03:00
} rfalNfcvSlpvReq ;
/*! Container for a collision found during Anticollision loop */
2022-01-05 19:10:18 +03:00
typedef struct {
uint8_t maskLen ;
uint8_t maskVal [ RFAL_NFCV_MASKVAL_MAX_LEN ] ;
} rfalNfcvCollision ;
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTION PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-01-05 19:10:18 +03:00
static ReturnCode rfalNfcvParseError ( uint8_t err ) ;
2021-10-18 01:54:19 +03:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL VARIABLES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LOCAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
}
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBAL FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerInitialize ( void ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
EXIT_ON_ERR ( ret , rfalSetMode ( RFAL_MODE_POLL_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 ) ;
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerCheckPresence ( rfalNfcvInventoryRes * invRes ) {
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */
2022-01-05 19:10:18 +03:00
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 ) ) {
2021-10-18 01:54:19 +03:00
ret = ERR_NONE ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ret ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerInventory (
rfalNfcvNumSlots nSlots ,
uint8_t maskLen ,
const uint8_t * maskVal ,
rfalNfcvInventoryRes * invRes ,
uint16_t * rcvdLen ) {
ReturnCode ret ;
2021-10-18 01:54:19 +03:00
rfalNfcvInventoryReq invReq ;
2022-01-05 19:10:18 +03:00
uint16_t rxLen ;
if ( ( ( maskVal = = NULL ) & & ( maskLen ! = 0U ) ) | | ( invRes = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
invReq . INV_FLAG = ( RFAL_NFCV_INV_REQ_FLAG | ( uint8_t ) nSlots ) ;
2022-01-05 19:10:18 +03:00
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 */
2021-10-18 01:54:19 +03:00
{
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( invReq . MASK_VALUE , maskVal , rfalConvBitsToBytes ( invReq . MASK_LEN ) ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
ret = rfalISO15693TransceiveAnticollisionFrame (
( uint8_t * ) & invReq ,
( uint8_t ) ( RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes ( invReq . MASK_LEN ) ) ,
( uint8_t * ) invRes ,
sizeof ( rfalNfcvInventoryRes ) ,
& rxLen ) ;
2021-10-18 01:54:19 +03:00
/* Check for optional output parameter */
2022-01-05 19:10:18 +03:00
if ( rcvdLen ! = NULL ) {
2021-10-18 01:54:19 +03:00
* rcvdLen = rxLen ;
}
2022-01-05 19:10:18 +03:00
if ( ret = = ERR_NONE ) {
2021-10-18 01:54:19 +03:00
/* Check for valid INVENTORY_RES Digital 2.2 9.6.2.1 & 9.6.2.3 */
2022-01-05 19:10:18 +03:00
if ( ! rfalNfcvCheckInvRes ( invRes - > RES_FLAG , rxLen ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ret ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvCollision colFound [ RFAL_NFCV_MAX_COLL_SUPPORTED ] ;
2022-01-05 19:10:18 +03:00
if ( ( nfcvDevList = = NULL ) | | ( devCnt = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
/* Initialize parameters */
* devCnt = 0 ;
2022-01-05 19:10:18 +03:00
colIt = 0 ;
colCnt = 0 ;
colPending = false ;
ST_MEMSET ( colFound , 0x00 , ( sizeof ( rfalNfcvCollision ) * RFAL_NFCV_MAX_COLL_SUPPORTED ) ) ;
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( devLimit > 0U ) /* MISRA 21.18 */
2021-10-18 01:54:19 +03:00
{
2022-01-05 19:10:18 +03:00
ST_MEMSET ( nfcvDevList , 0x00 , ( sizeof ( rfalNfcvListenDevice ) * devLimit ) ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
NO_WARNING (
colPending ) ; /* colPending is not exposed externally, in future it might become exposed/ouput parameter */
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( compMode = = RFAL_COMPLIANCE_MODE_NFC ) {
2021-10-18 01:54:19 +03:00
/* Send INVENTORY_REQ with one slot Activity 2.1 9.3.7.1 (Symbol 0) */
2022-01-05 19:10:18 +03:00
ret = rfalNfcvPollerInventory ( RFAL_NFCV_NUM_SLOTS_1 , 0 , NULL , & nfcvDevList - > InvRes , NULL ) ;
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( ret = = ERR_TIMEOUT ) /* Exit if no device found Activity 2.1 9.3.7.2 (Symbol 1) */
2021-10-18 01:54:19 +03:00
{
return ERR_NONE ;
}
2022-01-05 19:10:18 +03:00
if ( ret = =
ERR_NONE ) /* Device found without transmission error/collision Activity 2.1 9.3.7.3 (Symbol 2) */
2021-10-18 01:54:19 +03:00
{
( * devCnt ) + + ;
return ERR_NONE ;
}
/* A Collision has been identified Activity 2.1 9.3.7.4 (Symbol 3) */
colPending = true ;
2022-01-05 19:10:18 +03:00
colCnt = 1 ;
2021-10-18 01:54:19 +03:00
/* Check if the Collision Resolution is set to perform only Collision detection Activity 2.1 9.3.7.5 (Symbol 4)*/
2022-01-05 19:10:18 +03:00
if ( devLimit = = 0U ) {
2021-10-18 01:54:19 +03:00
return ERR_RF_COLLISION ;
}
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
/*******************************************************************************/
/* Collisions pending, Anticollision loop must be executed */
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
} else {
2021-10-18 01:54:19 +03:00
/* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */
colPending = true ;
2022-01-05 19:10:18 +03:00
colCnt = 1 ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Execute until all collisions are resolved Activity 2.1 9.3.7.18 (Symbol 17) */
2022-01-05 19:10:18 +03:00
do {
2021-10-18 01:54:19 +03:00
/* Activity 2.1 9.3.7.7 (Symbol 6 / 7) */
colPending = false ;
2022-01-05 19:10:18 +03:00
slotNum = 0 ;
do {
if ( slotNum = = 0U ) {
2021-10-18 01:54:19 +03:00
/* Send INVENTORY_REQ with 16 slots Activity 2.1 9.3.7.9 (Symbol 8) */
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
}
slotNum + + ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 */
2021-10-18 01:54:19 +03:00
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if response is a correct frame (no TxRx error) Activity 2.1 9.3.7.11 (Symbol 10)*/
2022-01-05 19:10:18 +03:00
if ( ( ret = = ERR_NONE ) | | ( ret = = ERR_PROTO ) ) {
2021-10-18 01:54:19 +03:00
/* Check if the device found is already on the list and its response is a valid INVENTORY_RES */
2022-01-05 19:10:18 +03:00
if ( rfalNfcvCheckInvRes ( nfcvDevList [ ( * devCnt ) ] . InvRes . RES_FLAG , rcvdLen ) ) {
2021-10-18 01:54:19 +03:00
/* Activity 2.1 9.3.7.12 (Symbol 11) */
( * devCnt ) + + ;
}
2022-01-05 19:10:18 +03:00
} else /* Treat everything else as collision */
2021-10-18 01:54:19 +03:00
{
/* Activity 2.1 9.3.7.17 (Symbol 16) */
colPending = true ;
/*******************************************************************************/
/* Ensure that this collision still fits on the container */
2022-01-05 19:10:18 +03:00
if ( colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED ) {
2021-10-18 01:54:19 +03:00
/* 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 */
2022-01-05 19:10:18 +03:00
ST_MEMCPY (
colFound [ colCnt ] . maskVal , colFound [ colIt ] . maskVal , RFAL_NFCV_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
colPos = colFound [ colIt ] . maskLen ;
2022-01-05 19:10:18 +03:00
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 ) ) ) ;
2021-10-18 01:54:19 +03:00
colFound [ colCnt ] . maskLen = ( colFound [ colIt ] . maskLen + 4U ) ;
colCnt + + ;
}
}
2022-01-05 19:10:18 +03:00
} else {
2021-10-18 01:54:19 +03:00
/* Timeout */
platformDelay ( RFAL_NFCV_FDT_V_INVENT_NORES ) ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if devices found have reached device limit Activity 2.1 9.3.7.13 (Symbol 12) */
2022-01-05 19:10:18 +03:00
if ( * devCnt > = devLimit ) {
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
2022-01-05 19:10:18 +03:00
} while ( slotNum < RFAL_NFCV_MAX_SLOTS ) ; /* Slot loop */
2021-10-18 01:54:19 +03:00
colIt + + ;
2022-01-05 19:10:18 +03:00
} while ( colIt < colCnt ) ; /* Collisions found loop */
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerSleepCollisionResolution (
uint8_t devLimit ,
rfalNfcvListenDevice * nfcvDevList ,
uint8_t * devCnt ) {
uint8_t tmpDevCnt ;
2021-10-18 01:54:19 +03:00
ReturnCode ret ;
2022-01-05 19:10:18 +03:00
uint8_t i ;
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
if ( ( nfcvDevList = = NULL ) | | ( devCnt = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
* devCnt = 0 ;
2022-01-05 19:10:18 +03:00
do {
2021-10-18 01:54:19 +03:00
tmpDevCnt = 0 ;
2022-01-05 19:10:18 +03:00
ret = rfalNfcvPollerCollisionResolution (
RFAL_COMPLIANCE_MODE_ISO , ( devLimit - * devCnt ) , & nfcvDevList [ * devCnt ] , & tmpDevCnt ) ;
2021-10-18 01:54:19 +03:00
2022-01-05 19:10:18 +03:00
for ( i = * devCnt ; i < ( * devCnt + tmpDevCnt ) ; i + + ) {
rfalNfcvPollerSleep ( 0x00 , nfcvDevList [ i ] . InvRes . UID ) ;
2021-10-18 01:54:19 +03:00
nfcvDevList [ i ] . isSleep = true ;
}
* devCnt + = tmpDevCnt ;
2022-01-05 19:10:18 +03:00
} while ( ( ret = = ERR_NONE ) & & ( tmpDevCnt > 0U ) & & ( * devCnt < devLimit ) ) ;
2021-10-18 01:54:19 +03:00
return ret ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerSleep ( uint8_t flags , const uint8_t * uid ) {
ReturnCode ret ;
2021-10-18 01:54:19 +03:00
rfalNfcvSlpvReq slpReq ;
2022-01-05 19:10:18 +03:00
uint8_t rxBuf ; /* dummy buffer, just to perform Rx */
if ( uid = = NULL ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute SLPV_REQ */
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
/* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */
2022-01-05 19:10:18 +03:00
ret = rfalTransceiveBlockingTxRx (
( uint8_t * ) & slpReq ,
sizeof ( rfalNfcvSlpvReq ) ,
& rxBuf ,
sizeof ( rxBuf ) ,
NULL ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCV_FDT_MAX1 ) ;
if ( ret ! = ERR_TIMEOUT ) {
2021-10-18 01:54:19 +03:00
return ret ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerSelect ( uint8_t flags , const uint8_t * uid ) {
uint16_t rcvLen ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
if ( uid = = NULL ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_SELECT ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
NULL ,
0U ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerReadSingleBlock (
uint8_t flags ,
const uint8_t * uid ,
uint8_t blockNum ,
uint8_t * rxBuf ,
uint16_t rxBufLen ,
uint16_t * rcvLen ) {
2021-10-18 01:54:19 +03:00
uint8_t bn ;
bn = blockNum ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_READ_SINGLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
& bn ,
sizeof ( uint8_t ) ,
rxBuf ,
rxBufLen ,
rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check for valid parameters */
2022-01-05 19:10:18 +03:00
if ( ( blockLen = = 0U ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) | | ( wrData = = NULL ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Data */
2022-01-05 19:10:18 +03:00
data [ dataLen + + ] = blockNum ; /* Set Block Number (8 bits) */
ST_MEMCPY ( & data [ dataLen ] , wrData , blockLen ) ; /* Append Block data to write */
2021-10-18 01:54:19 +03:00
dataLen + = blockLen ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
data ,
dataLen ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerLockBlock ( uint8_t flags , const uint8_t * uid , uint8_t blockNum ) {
uint16_t rcvLen ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
uint8_t bn ;
2021-10-18 01:54:19 +03:00
bn = blockNum ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_LOCK_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
& bn ,
sizeof ( uint8_t ) ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Data */
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
uint16_t msgIt ;
2021-10-18 01:54:19 +03:00
/* Calculate required buffer length */
2022-01-05 19:10:18 +03:00
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 ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
msgIt = 0 ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Command */
txBuf [ msgIt + + ] = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
txBuf [ msgIt + + ] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
2022-01-05 19:10:18 +03:00
if ( uid ! = NULL ) {
2021-10-18 01:54:19 +03:00
txBuf [ RFAL_NFCV_FLAG_POS ] | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & txBuf [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
msgIt + = ( uint8_t ) RFAL_NFCV_UID_LEN ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
txBuf [ msgIt + + ] = firstBlockNum ;
txBuf [ msgIt + + ] = ( numOfBlocks - 1U ) ;
2022-01-05 19:10:18 +03:00
if ( wrDataLen > 0U ) /* MISRA 21.18 */
2021-10-18 01:54:19 +03:00
{
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & txBuf [ msgIt ] , wrData , wrDataLen ) ;
2021-10-18 01:54:19 +03:00
msgIt + = wrDataLen ;
}
2022-01-05 19:10:18 +03:00
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx (
txBuf ,
msgIt ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCV_FDT_MAX ) ;
if ( ret ! = ERR_NONE ) {
2021-10-18 01:54:19 +03:00
return ret ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if the response minimum length has been received */
2022-01-05 19:10:18 +03:00
if ( rcvLen < ( uint8_t ) RFAL_NFCV_FLAG_LEN ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if an error has been signalled */
2022-01-05 19:10:18 +03:00
if ( ( res . RES_FLAG & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U ) {
return rfalNfcvParseError ( * res . data ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerExtendedReadSingleBlock (
uint8_t flags ,
const uint8_t * uid ,
uint16_t blockNum ,
uint8_t * rxBuf ,
uint16_t rxBufLen ,
uint16_t * rcvLen ) {
2021-10-18 01:54:19 +03:00
uint8_t data [ RFAL_NFCV_BLOCKNUM_EXTENDED_LEN ] ;
uint8_t dataLen ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Data */
2022-01-05 19:10:18 +03:00
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. */
2021-10-18 01:54:19 +03:00
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
data ,
dataLen ,
rxBuf ,
rxBufLen ,
rcvLen ) ;
}
2021-10-18 01:54:19 +03:00
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check for valid parameters */
2022-01-05 19:10:18 +03:00
if ( ( blockLen = = 0U ) | | ( blockLen > ( uint8_t ) RFAL_NFCV_MAX_BLOCK_LEN ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Data */
2022-01-05 19:10:18 +03:00
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. */
2021-10-18 01:54:19 +03:00
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & data [ dataLen ] , wrData , blockLen ) ; /* Append Block data to write */
2021-10-18 01:54:19 +03:00
dataLen + = blockLen ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
data ,
dataLen ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Data */
2022-01-05 19:10:18 +03:00
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. */
2021-10-18 01:54:19 +03:00
data [ dataLen + + ] = ( uint8_t ) ( ( blockNum > > 8U ) & 0xFFU ) ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
data ,
dataLen ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks (
uint8_t flags ,
const uint8_t * uid ,
uint16_t firstBlockNum ,
uint16_t numOfBlocks ,
uint8_t * rxBuf ,
uint16_t rxBufLen ,
uint16_t * rcvLen ) {
2021-10-18 01:54:19 +03:00
uint8_t data [ ( RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN ) ] ;
uint8_t dataLen ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
dataLen = 0U ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* 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 ) ;
2022-01-05 19:10:18 +03:00
return rfalNfcvPollerTransceiveReq (
RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK ,
flags ,
RFAL_NFCV_PARAM_SKIP ,
uid ,
data ,
dataLen ,
rxBuf ,
rxBufLen ,
rcvLen ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericRes res ;
2022-01-05 19:10:18 +03:00
uint16_t msgIt ;
uint16_t nBlocks ;
2021-10-18 01:54:19 +03:00
/* Calculate required buffer length */
2022-01-05 19:10:18 +03:00
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 ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
msgIt = 0 ;
2021-10-18 01:54:19 +03:00
nBlocks = ( numOfBlocks - 1U ) ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Command */
txBuf [ msgIt + + ] = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
txBuf [ msgIt + + ] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
2022-01-05 19:10:18 +03:00
if ( uid ! = NULL ) {
2021-10-18 01:54:19 +03:00
txBuf [ RFAL_NFCV_FLAG_POS ] | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & txBuf [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
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 ) ;
2022-01-05 19:10:18 +03:00
if ( wrDataLen > 0U ) /* MISRA 21.18 */
2021-10-18 01:54:19 +03:00
{
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & txBuf [ msgIt ] , wrData , wrDataLen ) ;
2021-10-18 01:54:19 +03:00
msgIt + = wrDataLen ;
}
2022-01-05 19:10:18 +03:00
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx (
txBuf ,
msgIt ,
( uint8_t * ) & res ,
sizeof ( rfalNfcvGenericRes ) ,
& rcvLen ,
RFAL_TXRX_FLAGS_DEFAULT ,
RFAL_NFCV_FDT_MAX ) ;
if ( ret ! = ERR_NONE ) {
2021-10-18 01:54:19 +03:00
return ret ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if the response minimum length has been received */
2022-01-05 19:10:18 +03:00
if ( rcvLen < ( uint8_t ) RFAL_NFCV_FLAG_LEN ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if an error has been signalled */
2022-01-05 19:10:18 +03:00
if ( ( res . RES_FLAG & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U ) {
return rfalNfcvParseError ( * res . data ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
ReturnCode 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 ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
}
/*******************************************************************************/
2022-01-05 19:10:18 +03:00
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 ;
2021-10-18 01:54:19 +03:00
rfalNfcvGenericReq req ;
2022-01-05 19:10:18 +03:00
uint8_t msgIt ;
rfalBitRate rxBR ;
bool fastMode ;
msgIt = 0 ;
2021-10-18 01:54:19 +03:00
fastMode = false ;
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check for valid parameters */
2022-01-05 19:10:18 +03:00
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 ) ) ) ) {
2021-10-18 01:54:19 +03:00
return ERR_PARAM ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if the command is an ST's Fast command */
2022-01-05 19:10:18 +03:00
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 ) ) {
2021-10-18 01:54:19 +03:00
/* Store current Rx bit rate and move to fast mode */
2022-01-05 19:10:18 +03:00
rfalGetBitRate ( NULL , & rxBR ) ;
rfalSetBitRate ( RFAL_BR_KEEP , RFAL_BR_52p97 ) ;
2021-10-18 01:54:19 +03:00
fastMode = true ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Compute Request Command */
2022-01-05 19:10:18 +03:00
req . REQ_FLAG = ( uint8_t ) ( flags & ( ~ ( ( uint32_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ) ) ) ;
req . CMD = cmd ;
2021-10-18 01:54:19 +03:00
/* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */
2022-01-05 19:10:18 +03:00
if ( param ! = RFAL_NFCV_PARAM_SKIP ) {
2021-10-18 01:54:19 +03:00
req . payload . data [ msgIt + + ] = param ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
2022-01-05 19:10:18 +03:00
if ( uid ! = NULL ) {
2021-10-18 01:54:19 +03:00
req . REQ_FLAG | = ( uint8_t ) RFAL_NFCV_REQ_FLAG_ADDRESS ;
2022-01-05 19:10:18 +03:00
ST_MEMCPY ( & req . payload . data [ msgIt ] , uid , RFAL_NFCV_UID_LEN ) ;
2021-10-18 01:54:19 +03:00
msgIt + = RFAL_NFCV_UID_LEN ;
}
2022-01-05 19:10:18 +03:00
if ( dataLen > 0U ) {
ST_MEMCPY ( & req . payload . data [ msgIt ] , data , dataLen ) ;
2021-10-18 01:54:19 +03:00
msgIt + = ( uint8_t ) dataLen ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Transceive Command */
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
/* 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 */
2022-01-05 19:10:18 +03:00
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 ) ;
2021-10-18 01:54:19 +03:00
}
/* Restore Rx BitRate */
2022-01-05 19:10:18 +03:00
if ( fastMode ) {
rfalSetBitRate ( RFAL_BR_KEEP , rxBR ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
if ( ret ! = ERR_NONE ) {
2021-10-18 01:54:19 +03:00
return ret ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if the response minimum length has been received */
2022-01-05 19:10:18 +03:00
if ( ( * rcvLen ) < ( uint8_t ) RFAL_NFCV_FLAG_LEN ) {
2021-10-18 01:54:19 +03:00
return ERR_PROTO ;
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
/* Check if an error has been signalled */
2022-01-05 19:10:18 +03:00
if ( ( rxBuf [ RFAL_NFCV_FLAG_POS ] & ( uint8_t ) RFAL_NFCV_RES_FLAG_ERROR ) ! = 0U ) {
return rfalNfcvParseError ( rxBuf [ RFAL_NFCV_DATASTART_POS ] ) ;
2021-10-18 01:54:19 +03:00
}
2022-01-05 19:10:18 +03:00
2021-10-18 01:54:19 +03:00
return ERR_NONE ;
}
# endif /* RFAL_FEATURE_NFCV */