| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059 |
- /******************************************************************************
- * \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 "../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 */
|