871 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			871 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| 
 | |
| /******************************************************************************
 | |
|   * \attention
 | |
|   *
 | |
|   * <h2><center>© 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                 : 20ms
 | |
|  *                    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 (96bits) for INV_RES we get:
 | |
|  *                    - ISO t3min = 96/26 ms + 300us = 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 */
 | 
