389ff92cc1
* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
586 lines
22 KiB
C
586 lines
22 KiB
C
|
|
/******************************************************************************
|
|
* \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_nfcf.c
|
|
*
|
|
* \author Gustavo Patricio
|
|
*
|
|
* \brief Implementation of NFC-F Poller (FeliCa PCD) device
|
|
*
|
|
* The definitions and helpers methods provided by this module are
|
|
* aligned with NFC-F (FeliCa - JIS X6319-4)
|
|
*
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* INCLUDES
|
|
******************************************************************************
|
|
*/
|
|
#include "rfal_nfcf.h"
|
|
#include "utils.h"
|
|
|
|
/*
|
|
******************************************************************************
|
|
* ENABLE SWITCH
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef RFAL_FEATURE_NFCF
|
|
#define RFAL_FEATURE_NFCF false /* NFC-F module configuration missing. Disabled by default */
|
|
#endif
|
|
|
|
#if RFAL_FEATURE_NFCF
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL DEFINES
|
|
******************************************************************************
|
|
*/
|
|
#define RFAL_NFCF_SENSF_REQ_LEN_MIN \
|
|
5U /*!< SENSF_RES minimum length */
|
|
|
|
#define RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN \
|
|
15U /*!< Minimum length for a Check Command T3T 5.4.1 */
|
|
#define RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN \
|
|
31U /*!< Minimum length for an Update Command T3T 5.5.1 */
|
|
|
|
#define RFAL_NFCF_CHECK_RES_MIN_LEN \
|
|
11U /*!< CHECK Response minimum length T3T 1.0 Table 8 */
|
|
#define RFAL_NFCF_UPDATE_RES_MIN_LEN \
|
|
11U /*!< UPDATE Response minimum length T3T 1.0 Table 8 */
|
|
|
|
#define RFAL_NFCF_CHECK_REQ_MAX_LEN \
|
|
86U /*!< Max length of a Check request T3T 1.0 Table 7 */
|
|
#define RFAL_NFCF_CHECK_REQ_MAX_SERV \
|
|
15U /*!< Max Services number on Check request T3T 1.0 5.4.1.5 */
|
|
#define RFAL_NFCF_CHECK_REQ_MAX_BLOCK \
|
|
15U /*!< Max Blocks number on Check request T3T 1.0 5.4.1.10 */
|
|
#define RFAL_NFCF_UPDATE_REQ_MAX_SERV \
|
|
15U /*!< Max Services number Update request T3T 1.0 5.4.1.5 */
|
|
#define RFAL_NFCF_UPDATE_REQ_MAX_BLOCK \
|
|
13U /*!< Max Blocks number on Update request T3T 1.0 5.4.1.10 */
|
|
|
|
/*! MRT Check | Uupdate = (Tt3t x ((A+1) + n (B+1)) x 4^E) + dRWTt3t T3T 5.8
|
|
Max values used: A = 7 ; B = 7 ; E = 3 ; n = 15 (NFC Forum n = 15, JIS n = 32)
|
|
*/
|
|
#define RFAL_NFCF_MRT_CHECK_UPDATE ((4096 * (8 + (15 * 8)) * 64) + 16)
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL MACROS
|
|
******************************************************************************
|
|
*/
|
|
#define rfalNfcfSlots2CardNum(s) \
|
|
((uint8_t)(s) + 1U) /*!< Converts Time Slot Number (TSN) into num of slots */
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL TYPES
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*! Structure/Buffer to hold the SENSF_RES with LEN byte prepended */
|
|
typedef struct {
|
|
uint8_t LEN; /*!< NFC-F LEN byte */
|
|
rfalNfcfSensfRes SENSF_RES; /*!< SENSF_RES */
|
|
} rfalNfcfSensfResBuf;
|
|
|
|
/*! Greedy collection for NFCF GRE_POLL_F Activity 1.0 Table 10 */
|
|
typedef struct {
|
|
uint8_t pollFound; /*!< Number of devices found by the Poll */
|
|
uint8_t pollCollision; /*!< Number of collisions detected */
|
|
rfalFeliCaPollRes POLL_F[RFAL_NFCF_POLL_MAXCARDS]; /*!< GRE_POLL_F Activity 1.0 Table 10 */
|
|
} rfalNfcfGreedyF;
|
|
|
|
/*! NFC-F SENSF_REQ format Digital 1.1 8.6.1 */
|
|
typedef struct {
|
|
uint8_t CMD; /*!< Command code: 00h */
|
|
uint8_t SC[RFAL_NFCF_SENSF_SC_LEN]; /*!< System Code */
|
|
uint8_t RC; /*!< Request Code */
|
|
uint8_t TSN; /*!< Time Slot Number */
|
|
} rfalNfcfSensfReq;
|
|
|
|
/*
|
|
******************************************************************************
|
|
* LOCAL VARIABLES
|
|
******************************************************************************
|
|
*/
|
|
static rfalNfcfGreedyF gRfalNfcfGreedyF; /*!< Activity's NFCF Greedy collection */
|
|
|
|
/*
|
|
******************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
******************************************************************************
|
|
*/
|
|
static void rfalNfcfComputeValidSENF(
|
|
rfalNfcfListenDevice* outDevInfo,
|
|
uint8_t* curDevIdx,
|
|
uint8_t devLimit,
|
|
bool overwrite,
|
|
bool* nfcDepFound);
|
|
|
|
/*
|
|
******************************************************************************
|
|
* LOCAL VARIABLES
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*******************************************************************************/
|
|
static void rfalNfcfComputeValidSENF(
|
|
rfalNfcfListenDevice* outDevInfo,
|
|
uint8_t* curDevIdx,
|
|
uint8_t devLimit,
|
|
bool overwrite,
|
|
bool* nfcDepFound) {
|
|
uint8_t tmpIdx;
|
|
bool duplicate;
|
|
const rfalNfcfSensfResBuf* sensfBuf;
|
|
rfalNfcfSensfResBuf sensfCopy;
|
|
|
|
/*******************************************************************************/
|
|
/* Go through all responses check if valid and duplicates */
|
|
/*******************************************************************************/
|
|
while((gRfalNfcfGreedyF.pollFound > 0U) && ((*curDevIdx) < devLimit)) {
|
|
duplicate = false;
|
|
gRfalNfcfGreedyF.pollFound--;
|
|
|
|
/* MISRA 11.3 - Cannot point directly into different object type, use local copy */
|
|
ST_MEMCPY(
|
|
(uint8_t*)&sensfCopy,
|
|
(uint8_t*)&gRfalNfcfGreedyF.POLL_F[gRfalNfcfGreedyF.pollFound],
|
|
sizeof(rfalNfcfSensfResBuf));
|
|
|
|
/* Point to received SENSF_RES */
|
|
sensfBuf = &sensfCopy;
|
|
|
|
/* Check for devices that are already in device list */
|
|
for(tmpIdx = 0; tmpIdx < (*curDevIdx); tmpIdx++) {
|
|
if(ST_BYTECMP(
|
|
sensfBuf->SENSF_RES.NFCID2,
|
|
outDevInfo[tmpIdx].sensfRes.NFCID2,
|
|
RFAL_NFCF_NFCID2_LEN) == 0) {
|
|
duplicate = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If is a duplicate skip this (and not to overwrite)*/
|
|
if(duplicate && !overwrite) {
|
|
continue;
|
|
}
|
|
|
|
/* Check if response length is OK */
|
|
if(((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) < RFAL_NFCF_SENSF_RES_LEN_MIN) ||
|
|
((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) > RFAL_NFCF_SENSF_RES_LEN_MAX)) {
|
|
continue;
|
|
}
|
|
|
|
/* Check if the response is a SENSF_RES / Polling response */
|
|
if(sensfBuf->SENSF_RES.CMD != (uint8_t)RFAL_NFCF_CMD_POLLING_RES) {
|
|
continue;
|
|
}
|
|
|
|
/* Check if is an overwrite request or new device*/
|
|
if(duplicate && overwrite) {
|
|
/* overwrite deviceInfo/GRE_SENSF_RES with SENSF_RES */
|
|
outDevInfo[tmpIdx].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN);
|
|
ST_MEMCPY(
|
|
&outDevInfo[tmpIdx].sensfRes,
|
|
&sensfBuf->SENSF_RES,
|
|
outDevInfo[tmpIdx].sensfResLen);
|
|
continue;
|
|
} else {
|
|
/* fill deviceInfo/GRE_SENSF_RES with new SENSF_RES */
|
|
outDevInfo[(*curDevIdx)].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN);
|
|
ST_MEMCPY(
|
|
&outDevInfo[(*curDevIdx)].sensfRes,
|
|
&sensfBuf->SENSF_RES,
|
|
outDevInfo[(*curDevIdx)].sensfResLen);
|
|
}
|
|
|
|
/* Check if this device supports NFC-DEP and signal it (ACTIVITY 1.1 9.3.6.63) */
|
|
*nfcDepFound = rfalNfcfIsNfcDepSupported(&outDevInfo[(*curDevIdx)]);
|
|
|
|
(*curDevIdx)++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
******************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerInitialize(rfalBitRate bitRate) {
|
|
ReturnCode ret;
|
|
|
|
if((bitRate != RFAL_BR_212) && (bitRate != RFAL_BR_424)) {
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCF, bitRate, bitRate));
|
|
rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC);
|
|
|
|
rfalSetGT(RFAL_GT_NFCF);
|
|
rfalSetFDTListen(RFAL_FDT_LISTEN_NFCF_POLLER);
|
|
rfalSetFDTPoll(RFAL_FDT_POLL_NFCF_POLLER);
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerPoll(
|
|
rfalFeliCaPollSlots slots,
|
|
uint16_t sysCode,
|
|
uint8_t reqCode,
|
|
rfalFeliCaPollRes* cardList,
|
|
uint8_t* devCnt,
|
|
uint8_t* collisions) {
|
|
return rfalFeliCaPoll(
|
|
slots, sysCode, reqCode, cardList, rfalNfcfSlots2CardNum(slots), devCnt, collisions);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerCheckPresence(void) {
|
|
gRfalNfcfGreedyF.pollFound = 0;
|
|
gRfalNfcfGreedyF.pollCollision = 0;
|
|
|
|
/* ACTIVITY 1.0 & 1.1 - 9.2.3.17 SENSF_REQ must be with number of slots equal to 4
|
|
* SC must be 0xFFFF
|
|
* RC must be 0x00 (No system code info required) */
|
|
return rfalFeliCaPoll(
|
|
RFAL_FELICA_4_SLOTS,
|
|
RFAL_NFCF_SYSTEMCODE,
|
|
RFAL_FELICA_POLL_RC_NO_REQUEST,
|
|
gRfalNfcfGreedyF.POLL_F,
|
|
rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS),
|
|
&gRfalNfcfGreedyF.pollFound,
|
|
&gRfalNfcfGreedyF.pollCollision);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerCollisionResolution(
|
|
rfalComplianceMode compMode,
|
|
uint8_t devLimit,
|
|
rfalNfcfListenDevice* nfcfDevList,
|
|
uint8_t* devCnt) {
|
|
ReturnCode ret;
|
|
bool nfcDepFound;
|
|
|
|
if((nfcfDevList == NULL) || (devCnt == NULL)) {
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
*devCnt = 0;
|
|
nfcDepFound = false;
|
|
|
|
/*******************************************************************************************/
|
|
/* ACTIVITY 1.0 - 9.3.6.3 Copy valid SENSF_RES in GRE_POLL_F into GRE_SENSF_RES */
|
|
/* ACTIVITY 1.0 - 9.3.6.6 The NFC Forum Device MUST remove all entries from GRE_SENSF_RES[]*/
|
|
/* ACTIVITY 1.1 - 9.3.63.59 Populate GRE_SENSF_RES with data from GRE_POLL_F */
|
|
/* */
|
|
/* CON_DEVICES_LIMIT = 0 Just check if devices from Tech Detection exceeds -> always true */
|
|
/* Allow the number of slots open on Technology Detection */
|
|
/*******************************************************************************************/
|
|
rfalNfcfComputeValidSENF(
|
|
nfcfDevList,
|
|
devCnt,
|
|
((devLimit == 0U) ? rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS) : devLimit),
|
|
false,
|
|
&nfcDepFound);
|
|
|
|
/*******************************************************************************/
|
|
/* ACTIVITY 1.0 - 9.3.6.4 */
|
|
/* ACTIVITY 1.1 - 9.3.63.60 Check if devices found are lower than the limit */
|
|
/* and send a SENSF_REQ if so */
|
|
/*******************************************************************************/
|
|
if(*devCnt < devLimit) {
|
|
/* ACTIVITY 1.0 - 9.3.6.5 Copy valid SENSF_RES and then to remove it
|
|
* ACTIVITY 1.1 - 9.3.6.65 Copy and filter duplicates
|
|
* For now, due to some devices keep generating different nfcid2, we use 1.0
|
|
* Phones detected: Samsung Galaxy Nexus,Samsung Galaxy S3,Samsung Nexus S */
|
|
*devCnt = 0;
|
|
|
|
ret = rfalNfcfPollerPoll(
|
|
RFAL_FELICA_16_SLOTS,
|
|
RFAL_NFCF_SYSTEMCODE,
|
|
RFAL_FELICA_POLL_RC_NO_REQUEST,
|
|
gRfalNfcfGreedyF.POLL_F,
|
|
&gRfalNfcfGreedyF.pollFound,
|
|
&gRfalNfcfGreedyF.pollCollision);
|
|
if(ret == ERR_NONE) {
|
|
rfalNfcfComputeValidSENF(nfcfDevList, devCnt, devLimit, false, &nfcDepFound);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* ACTIVITY 1.1 - 9.3.6.63 Check if any device supports NFC DEP */
|
|
/*******************************************************************************/
|
|
if(nfcDepFound && (compMode == RFAL_COMPLIANCE_MODE_NFC)) {
|
|
ret = rfalNfcfPollerPoll(
|
|
RFAL_FELICA_16_SLOTS,
|
|
RFAL_NFCF_SYSTEMCODE,
|
|
RFAL_FELICA_POLL_RC_SYSTEM_CODE,
|
|
gRfalNfcfGreedyF.POLL_F,
|
|
&gRfalNfcfGreedyF.pollFound,
|
|
&gRfalNfcfGreedyF.pollCollision);
|
|
if(ret == ERR_NONE) {
|
|
rfalNfcfComputeValidSENF(nfcfDevList, devCnt, devLimit, true, &nfcDepFound);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerCheck(
|
|
const uint8_t* nfcid2,
|
|
const rfalNfcfServBlockListParam* servBlock,
|
|
uint8_t* rxBuf,
|
|
uint16_t rxBufLen,
|
|
uint16_t* rcvdLen) {
|
|
uint8_t txBuf[RFAL_NFCF_CHECK_REQ_MAX_LEN];
|
|
uint8_t msgIt;
|
|
uint8_t i;
|
|
ReturnCode ret;
|
|
const uint8_t* checkRes;
|
|
|
|
/* Check parameters */
|
|
if((nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (servBlock->numBlock == 0U) ||
|
|
(servBlock->numBlock > RFAL_NFCF_CHECK_REQ_MAX_BLOCK) || (servBlock->numServ == 0U) ||
|
|
(servBlock->numServ > RFAL_NFCF_CHECK_REQ_MAX_SERV) ||
|
|
(rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECK_RES_MIN_LEN))) {
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
msgIt = 0;
|
|
|
|
/*******************************************************************************/
|
|
/* Compose CHECK command/request */
|
|
|
|
txBuf[msgIt++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION; /* Command Code */
|
|
|
|
ST_MEMCPY(&txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN); /* NFCID2 */
|
|
msgIt += RFAL_NFCF_NFCID2_LEN;
|
|
|
|
txBuf[msgIt++] = servBlock->numServ; /* NoS */
|
|
for(i = 0; i < servBlock->numServ; i++) {
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU);
|
|
}
|
|
|
|
txBuf[msgIt++] = servBlock->numBlock; /* NoB */
|
|
for(i = 0; i < servBlock->numBlock; i++) {
|
|
txBuf[msgIt++] =
|
|
servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */
|
|
if((servBlock->blockList[i].conf & 0x80U) !=
|
|
0U) /* Check if 2 or 3 byte block list element */
|
|
{
|
|
txBuf[msgIt++] =
|
|
(uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */
|
|
} else {
|
|
txBuf[msgIt++] =
|
|
(uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Transceive CHECK command/request */
|
|
ret = rfalTransceiveBlockingTxRx(
|
|
txBuf,
|
|
msgIt,
|
|
rxBuf,
|
|
rxBufLen,
|
|
rcvdLen,
|
|
RFAL_TXRX_FLAGS_DEFAULT,
|
|
RFAL_NFCF_MRT_CHECK_UPDATE);
|
|
|
|
if(ret == ERR_NONE) {
|
|
/* Skip LEN byte */
|
|
checkRes = (rxBuf + RFAL_NFCF_LENGTH_LEN);
|
|
|
|
/* Check response length */
|
|
if(*rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS)) {
|
|
ret = ERR_PROTO;
|
|
}
|
|
/* Check for a valid response */
|
|
else if(
|
|
(checkRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES) ||
|
|
(checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ||
|
|
(checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS)) {
|
|
ret = ERR_REQUEST;
|
|
}
|
|
/* CHECK succesfull, remove header */
|
|
else {
|
|
(*rcvdLen) -= (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_NOB_POS);
|
|
|
|
if(*rcvdLen > 0U) {
|
|
ST_MEMMOVE(rxBuf, &checkRes[RFAL_NFCF_CHECKUPDATE_RES_NOB_POS], (*rcvdLen));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
ReturnCode rfalNfcfPollerUpdate(
|
|
const uint8_t* nfcid2,
|
|
const rfalNfcfServBlockListParam* servBlock,
|
|
uint8_t* txBuf,
|
|
uint16_t txBufLen,
|
|
const uint8_t* blockData,
|
|
uint8_t* rxBuf,
|
|
uint16_t rxBufLen) {
|
|
uint8_t i;
|
|
uint16_t msgIt;
|
|
uint16_t rcvdLen;
|
|
uint16_t auxLen;
|
|
const uint8_t* updateRes;
|
|
ReturnCode ret;
|
|
|
|
/* Check parameters */
|
|
if((nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (txBuf == NULL) ||
|
|
(servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_UPDATE_REQ_MAX_BLOCK) ||
|
|
(servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_UPDATE_REQ_MAX_SERV) ||
|
|
(rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_UPDATE_RES_MIN_LEN))) {
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
/* Calculate required txBuffer lenth */
|
|
auxLen = (uint16_t)( RFAL_NFCF_CMD_LEN + RFAL_NFCF_NFCID2_LEN + ( servBlock->numServ * sizeof(rfalNfcfServ) ) +
|
|
(servBlock->numBlock * sizeof(rfalNfcfBlockListElem)) + (uint16_t)((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN) );
|
|
|
|
/* Check whether the provided buffer is sufficient for this request */
|
|
if(txBufLen < auxLen) {
|
|
return ERR_PARAM;
|
|
}
|
|
|
|
msgIt = 0;
|
|
|
|
/*******************************************************************************/
|
|
/* Compose UPDATE command/request */
|
|
|
|
txBuf[msgIt++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION; /* Command Code */
|
|
|
|
ST_MEMCPY(&txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN); /* NFCID2 */
|
|
msgIt += RFAL_NFCF_NFCID2_LEN;
|
|
|
|
txBuf[msgIt++] = servBlock->numServ; /* NoS */
|
|
for(i = 0; i < servBlock->numServ; i++) {
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU);
|
|
}
|
|
|
|
txBuf[msgIt++] = servBlock->numBlock; /* NoB */
|
|
for(i = 0; i < servBlock->numBlock; i++) {
|
|
txBuf[msgIt++] =
|
|
servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */
|
|
if((servBlock->blockList[i].conf & 0x80U) !=
|
|
0U) /* Check if 2 or 3 byte block list element */
|
|
{
|
|
txBuf[msgIt++] =
|
|
(uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */
|
|
} else {
|
|
txBuf[msgIt++] =
|
|
(uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */
|
|
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU);
|
|
}
|
|
}
|
|
|
|
auxLen = ((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN);
|
|
ST_MEMCPY(&txBuf[msgIt], blockData, auxLen); /* Block Data */
|
|
msgIt += auxLen;
|
|
|
|
/*******************************************************************************/
|
|
/* Transceive UPDATE command/request */
|
|
ret = rfalTransceiveBlockingTxRx(
|
|
txBuf,
|
|
msgIt,
|
|
rxBuf,
|
|
rxBufLen,
|
|
&rcvdLen,
|
|
RFAL_TXRX_FLAGS_DEFAULT,
|
|
RFAL_NFCF_MRT_CHECK_UPDATE);
|
|
|
|
if(ret == ERR_NONE) {
|
|
/* Skip LEN byte */
|
|
updateRes = (rxBuf + RFAL_NFCF_LENGTH_LEN);
|
|
|
|
/* Check response length */
|
|
if(rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS)) {
|
|
ret = ERR_PROTO;
|
|
}
|
|
/* Check for a valid response */
|
|
else if(
|
|
(updateRes[RFAL_NFCF_CMD_POS] !=
|
|
(uint8_t)RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES) ||
|
|
(updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ||
|
|
(updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS)) {
|
|
ret = ERR_REQUEST;
|
|
} else {
|
|
/* MISRA 15.7 - Empty else */
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
bool rfalNfcfListenerIsT3TReq(const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2) {
|
|
/* Check cmd byte */
|
|
switch(*buf) {
|
|
case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION:
|
|
if(bufLen < RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN) {
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION:
|
|
if(bufLen < RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN) {
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
/* Output NFID2 if requested */
|
|
if(nfcid2 != NULL) {
|
|
ST_MEMCPY(nfcid2, &buf[RFAL_NFCF_CMD_LEN], RFAL_NFCF_NFCID2_LEN);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif /* RFAL_FEATURE_NFCF */
|