rfal_nfcv.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. /******************************************************************************
  2. * \attention
  3. *
  4. * <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
  5. *
  6. * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
  7. * You may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at:
  9. *
  10. * www.st.com/myliberty
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  15. * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. ******************************************************************************/
  21. /*
  22. * PROJECT: ST25R391x firmware
  23. * Revision:
  24. * LANGUAGE: ISO C99
  25. */
  26. /*! \file rfal_nfcv.c
  27. *
  28. * \author Gustavo Patricio
  29. *
  30. * \brief Implementation of NFC-V Poller (ISO15693) device
  31. *
  32. * The definitions and helpers methods provided by this module are
  33. * aligned with NFC-V (ISO15693)
  34. *
  35. * The definitions and helpers methods provided by this module
  36. * are aligned with NFC-V Digital 2.1
  37. *
  38. */
  39. /*
  40. ******************************************************************************
  41. * INCLUDES
  42. ******************************************************************************
  43. */
  44. #include "rfal_nfcv.h"
  45. #include "utils.h"
  46. /*
  47. ******************************************************************************
  48. * ENABLE SWITCH
  49. ******************************************************************************
  50. */
  51. #ifndef RFAL_FEATURE_NFCV
  52. #define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
  53. #endif
  54. #if RFAL_FEATURE_NFCV
  55. /*
  56. ******************************************************************************
  57. * GLOBAL DEFINES
  58. ******************************************************************************
  59. */
  60. #define RFAL_NFCV_INV_REQ_FLAG 0x06U /*!< INVENTORY_REQ INV_FLAG Digital 2.1 9.6.1 */
  61. #define RFAL_NFCV_MASKVAL_MAX_LEN 8U /*!< Mask value max length: 64 bits (UID length) */
  62. #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 */
  63. #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 */
  64. #define RFAL_NFCV_MAX_SLOTS 16U /*!< NFC-V max number of Slots */
  65. #define RFAL_NFCV_INV_REQ_HEADER_LEN 3U /*!< INVENTORY_REQ header length (INV_FLAG, CMD, MASK_LEN) */
  66. #define RFAL_NFCV_INV_RES_LEN 10U /*!< INVENTORY_RES length */
  67. #define RFAL_NFCV_WR_MUL_REQ_HEADER_LEN 4U /*!< Write Multiple header length (INV_FLAG, CMD, [UID], BNo, Bno) */
  68. #define RFAL_NFCV_CMD_LEN 1U /*!< Commandbyte length */
  69. #define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */
  70. #define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */
  71. #define RFAL_NFCV_DATASTART_POS 1U /*!< Position of start of data */
  72. #define RFAL_NFCV_DSFI_LEN 1U /*!< DSFID length */
  73. #define RFAL_NFCV_SLPREQ_REQ_FLAG 0x22U /*!< SLPV_REQ request flags Digital 2.0 (Candidate) 9.7.1.1 */
  74. #define RFAL_NFCV_RES_FLAG_NOERROR 0x00U /*!< RES_FLAG indicating no error (checked during activation) */
  75. #define RFAL_NFCV_MAX_COLL_SUPPORTED 16U /*!< Maximum number of collisions supported by the Anticollision loop */
  76. #define RFAL_NFCV_FDT_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF and MAX2 Digital 2.1 B.5*/
  77. #define RFAL_NFCV_FDT_MAX1 4394U /*!< Read alike command FWT FDTV,LISTEN,MAX1 Digital 2.0 B.5 */
  78. /*! Time from special frame to EOF
  79. * ISO15693 2009 10.4.2 : 20ms
  80. * NFC Forum defines Digital 2.0 9.7.4 : FDTV,EOF = [10 ; 20]ms
  81. */
  82. #define RFAL_NFCV_FDT_EOF 20U
  83. /*! Time between slots - ISO 15693 defines t3min depending on modulation depth and data rate.
  84. * With only high-bitrate supported, AM modulation and a length of 12 bytes (96bits) for INV_RES we get:
  85. * - ISO t3min = 96/26 ms + 300us = 4 ms
  86. * - NFC Forum defines FDTV,INVENT_NORES = (4394 + 2048)/fc. Digital 2.0 B.5*/
  87. #define RFAL_NFCV_FDT_V_INVENT_NORES 4U
  88. /*
  89. ******************************************************************************
  90. * GLOBAL MACROS
  91. ******************************************************************************
  92. */
  93. /*! Checks if a valid INVENTORY_RES is valid Digital 2.2 9.6.2.1 & 9.6.2.3 */
  94. #define rfalNfcvCheckInvRes( f, l ) (((l)==rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN)) && ((f)==RFAL_NFCV_RES_FLAG_NOERROR))
  95. /*
  96. ******************************************************************************
  97. * GLOBAL TYPES
  98. ******************************************************************************
  99. */
  100. /*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */
  101. typedef struct
  102. {
  103. uint8_t INV_FLAG; /*!< Inventory Flags */
  104. uint8_t CMD; /*!< Command code: 01h */
  105. uint8_t MASK_LEN; /*!< Mask Value Length */
  106. uint8_t MASK_VALUE[RFAL_NFCV_MASKVAL_MAX_LEN]; /*!< Mask Value */
  107. } rfalNfcvInventoryReq;
  108. /*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */
  109. typedef struct
  110. {
  111. uint8_t REQ_FLAG; /*!< Request Flags */
  112. uint8_t CMD; /*!< Command code: 02h */
  113. uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< Mask Value */
  114. } rfalNfcvSlpvReq;
  115. /*! Container for a collision found during Anticollision loop */
  116. typedef struct
  117. {
  118. uint8_t maskLen;
  119. uint8_t maskVal[RFAL_NFCV_MASKVAL_MAX_LEN];
  120. }rfalNfcvCollision;
  121. /*
  122. ******************************************************************************
  123. * LOCAL FUNCTION PROTOTYPES
  124. ******************************************************************************
  125. */
  126. static ReturnCode rfalNfcvParseError( uint8_t err );
  127. /*
  128. ******************************************************************************
  129. * LOCAL VARIABLES
  130. ******************************************************************************
  131. */
  132. /*
  133. ******************************************************************************
  134. * LOCAL FUNCTIONS
  135. ******************************************************************************
  136. */
  137. /*******************************************************************************/
  138. static ReturnCode rfalNfcvParseError( uint8_t err )
  139. {
  140. switch(err)
  141. {
  142. case RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED:
  143. case RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED:
  144. return ERR_NOTSUPP;
  145. case RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED:
  146. return ERR_PROTO;
  147. case RFAL_NFCV_ERROR_WRITE_FAILED:
  148. return ERR_WRITE;
  149. default:
  150. return ERR_REQUEST;
  151. }
  152. }
  153. /*
  154. ******************************************************************************
  155. * GLOBAL FUNCTIONS
  156. ******************************************************************************
  157. */
  158. /*******************************************************************************/
  159. ReturnCode rfalNfcvPollerInitialize( void )
  160. {
  161. ReturnCode ret;
  162. EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCV, RFAL_BR_26p48, RFAL_BR_26p48 ) );
  163. rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
  164. rfalSetGT( RFAL_GT_NFCV );
  165. rfalSetFDTListen( RFAL_FDT_LISTEN_NFCV_POLLER );
  166. rfalSetFDTPoll( RFAL_FDT_POLL_NFCV_POLLER );
  167. return ERR_NONE;
  168. }
  169. /*******************************************************************************/
  170. ReturnCode rfalNfcvPollerCheckPresence( rfalNfcvInventoryRes *invRes )
  171. {
  172. ReturnCode ret;
  173. /* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */
  174. ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, invRes, NULL );
  175. if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) ||
  176. (ret == ERR_FRAMING) || (ret == ERR_PROTO) )
  177. {
  178. ret = ERR_NONE;
  179. }
  180. return ret;
  181. }
  182. /*******************************************************************************/
  183. ReturnCode rfalNfcvPollerInventory( rfalNfcvNumSlots nSlots, uint8_t maskLen, const uint8_t *maskVal, rfalNfcvInventoryRes *invRes, uint16_t* rcvdLen )
  184. {
  185. ReturnCode ret;
  186. rfalNfcvInventoryReq invReq;
  187. uint16_t rxLen;
  188. if( ((maskVal == NULL) && (maskLen != 0U)) || (invRes == NULL) )
  189. {
  190. return ERR_PARAM;
  191. }
  192. invReq.INV_FLAG = (RFAL_NFCV_INV_REQ_FLAG | (uint8_t)nSlots);
  193. invReq.CMD = RFAL_NFCV_CMD_INVENTORY;
  194. 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 */
  195. if( (rfalConvBitsToBytes(invReq.MASK_LEN) > 0U) && (maskVal != NULL) ) /* MISRA 21.18 & 1.3 */
  196. {
  197. ST_MEMCPY( invReq.MASK_VALUE, maskVal, rfalConvBitsToBytes(invReq.MASK_LEN) );
  198. }
  199. ret = rfalISO15693TransceiveAnticollisionFrame( (uint8_t*)&invReq, (uint8_t)(RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes(invReq.MASK_LEN)), (uint8_t*)invRes, sizeof(rfalNfcvInventoryRes), &rxLen );
  200. /* Check for optional output parameter */
  201. if( rcvdLen != NULL )
  202. {
  203. *rcvdLen = rxLen;
  204. }
  205. if( ret == ERR_NONE )
  206. {
  207. /* Check for valid INVENTORY_RES Digital 2.2 9.6.2.1 & 9.6.2.3 */
  208. if( !rfalNfcvCheckInvRes( invRes->RES_FLAG, rxLen ) )
  209. {
  210. return ERR_PROTO;
  211. }
  212. }
  213. return ret;
  214. }
  215. /*******************************************************************************/
  216. ReturnCode rfalNfcvPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt )
  217. {
  218. ReturnCode ret;
  219. uint8_t slotNum;
  220. uint16_t rcvdLen;
  221. uint8_t colIt;
  222. uint8_t colCnt;
  223. uint8_t colPos;
  224. bool colPending;
  225. rfalNfcvCollision colFound[RFAL_NFCV_MAX_COLL_SUPPORTED];
  226. if( (nfcvDevList == NULL) || (devCnt == NULL) )
  227. {
  228. return ERR_PARAM;
  229. }
  230. /* Initialize parameters */
  231. *devCnt = 0;
  232. colIt = 0;
  233. colCnt = 0;
  234. colPending = false;
  235. ST_MEMSET(colFound, 0x00, (sizeof(rfalNfcvCollision)*RFAL_NFCV_MAX_COLL_SUPPORTED) );
  236. if( devLimit > 0U ) /* MISRA 21.18 */
  237. {
  238. ST_MEMSET(nfcvDevList, 0x00, (sizeof(rfalNfcvListenDevice)*devLimit) );
  239. }
  240. NO_WARNING(colPending); /* colPending is not exposed externally, in future it might become exposed/ouput parameter */
  241. if( compMode == RFAL_COMPLIANCE_MODE_NFC )
  242. {
  243. /* Send INVENTORY_REQ with one slot Activity 2.1 9.3.7.1 (Symbol 0) */
  244. ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &nfcvDevList->InvRes, NULL );
  245. if( ret == ERR_TIMEOUT ) /* Exit if no device found Activity 2.1 9.3.7.2 (Symbol 1) */
  246. {
  247. return ERR_NONE;
  248. }
  249. if( ret == ERR_NONE ) /* Device found without transmission error/collision Activity 2.1 9.3.7.3 (Symbol 2) */
  250. {
  251. (*devCnt)++;
  252. return ERR_NONE;
  253. }
  254. /* A Collision has been identified Activity 2.1 9.3.7.4 (Symbol 3) */
  255. colPending = true;
  256. colCnt = 1;
  257. /* Check if the Collision Resolution is set to perform only Collision detection Activity 2.1 9.3.7.5 (Symbol 4)*/
  258. if( devLimit == 0U )
  259. {
  260. return ERR_RF_COLLISION;
  261. }
  262. platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
  263. /*******************************************************************************/
  264. /* Collisions pending, Anticollision loop must be executed */
  265. /*******************************************************************************/
  266. }
  267. else
  268. {
  269. /* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */
  270. colPending = true;
  271. colCnt = 1;
  272. }
  273. /* Execute until all collisions are resolved Activity 2.1 9.3.7.18 (Symbol 17) */
  274. do
  275. {
  276. /* Activity 2.1 9.3.7.7 (Symbol 6 / 7) */
  277. colPending = false;
  278. slotNum = 0;
  279. do
  280. {
  281. if( slotNum == 0U )
  282. {
  283. /* Send INVENTORY_REQ with 16 slots Activity 2.1 9.3.7.9 (Symbol 8) */
  284. ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_16, colFound[colIt].maskLen, colFound[colIt].maskVal, &nfcvDevList[(*devCnt)].InvRes, &rcvdLen );
  285. }
  286. else
  287. {
  288. ret = rfalISO15693TransceiveEOFAnticollision( (uint8_t*)&nfcvDevList[(*devCnt)].InvRes, sizeof(rfalNfcvInventoryRes), &rcvdLen );
  289. }
  290. slotNum++;
  291. /*******************************************************************************/
  292. if( ret != ERR_TIMEOUT )
  293. {
  294. if( rcvdLen < rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN) )
  295. { /* If only a partial frame was received make sure the FDT_V_INVENT_NORES is fulfilled */
  296. platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
  297. }
  298. /* Check if response is a correct frame (no TxRx error) Activity 2.1 9.3.7.11 (Symbol 10)*/
  299. if( (ret == ERR_NONE) || (ret == ERR_PROTO) )
  300. {
  301. /* Check if the device found is already on the list and its response is a valid INVENTORY_RES */
  302. if( rfalNfcvCheckInvRes( nfcvDevList[(*devCnt)].InvRes.RES_FLAG, rcvdLen ) )
  303. {
  304. /* Activity 2.1 9.3.7.12 (Symbol 11) */
  305. (*devCnt)++;
  306. }
  307. }
  308. else /* Treat everything else as collision */
  309. {
  310. /* Activity 2.1 9.3.7.17 (Symbol 16) */
  311. colPending = true;
  312. /*******************************************************************************/
  313. /* Ensure that this collision still fits on the container */
  314. if( colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED )
  315. {
  316. /* Store this collision on the container to be resolved later */
  317. /* Activity 2.1 9.3.7.17 (Symbol 16): add the collision information
  318. * (MASK_VAL + SN) to the list containing the collision information */
  319. ST_MEMCPY(colFound[colCnt].maskVal, colFound[colIt].maskVal, RFAL_NFCV_UID_LEN);
  320. colPos = colFound[colIt].maskLen;
  321. colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] &= (uint8_t)((1U << (colPos % RFAL_BITS_IN_BYTE)) - 1U);
  322. colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] |= (uint8_t)((slotNum-1U) << (colPos % RFAL_BITS_IN_BYTE));
  323. colFound[colCnt].maskVal[((colPos/RFAL_BITS_IN_BYTE)+1U)] = (uint8_t)((slotNum-1U) >> (RFAL_BITS_IN_BYTE - (colPos % RFAL_BITS_IN_BYTE)));
  324. colFound[colCnt].maskLen = (colFound[colIt].maskLen + 4U);
  325. colCnt++;
  326. }
  327. }
  328. }
  329. else
  330. {
  331. /* Timeout */
  332. platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
  333. }
  334. /* Check if devices found have reached device limit Activity 2.1 9.3.7.13 (Symbol 12) */
  335. if( *devCnt >= devLimit )
  336. {
  337. return ERR_NONE;
  338. }
  339. } while( slotNum < RFAL_NFCV_MAX_SLOTS ); /* Slot loop */
  340. colIt++;
  341. } while( colIt < colCnt ); /* Collisions found loop */
  342. return ERR_NONE;
  343. }
  344. /*******************************************************************************/
  345. ReturnCode rfalNfcvPollerSleepCollisionResolution( uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt )
  346. {
  347. uint8_t tmpDevCnt;
  348. ReturnCode ret;
  349. uint8_t i;
  350. if( (nfcvDevList == NULL) || (devCnt == NULL) )
  351. {
  352. return ERR_PARAM;
  353. }
  354. *devCnt = 0;
  355. do
  356. {
  357. tmpDevCnt = 0;
  358. ret = rfalNfcvPollerCollisionResolution( RFAL_COMPLIANCE_MODE_ISO, (devLimit - *devCnt), &nfcvDevList[*devCnt], &tmpDevCnt );
  359. for( i = *devCnt; i < (*devCnt + tmpDevCnt); i++ )
  360. {
  361. rfalNfcvPollerSleep( 0x00, nfcvDevList[i].InvRes.UID );
  362. nfcvDevList[i].isSleep = true;
  363. }
  364. *devCnt += tmpDevCnt;
  365. }
  366. while( (ret == ERR_NONE) && (tmpDevCnt > 0U) && (*devCnt < devLimit) );
  367. return ret;
  368. }
  369. /*******************************************************************************/
  370. ReturnCode rfalNfcvPollerSleep( uint8_t flags, const uint8_t* uid )
  371. {
  372. ReturnCode ret;
  373. rfalNfcvSlpvReq slpReq;
  374. uint8_t rxBuf; /* dummy buffer, just to perform Rx */
  375. if( uid == NULL )
  376. {
  377. return ERR_PARAM;
  378. }
  379. /* Compute SLPV_REQ */
  380. slpReq.REQ_FLAG = (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS); /* Should be with UID according Digital 2.0 (Candidate) 9.7.1.1 */
  381. slpReq.CMD = RFAL_NFCV_CMD_SLPV;
  382. ST_MEMCPY( slpReq.UID, uid, RFAL_NFCV_UID_LEN );
  383. /* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */
  384. ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slpReq, sizeof(rfalNfcvSlpvReq), &rxBuf, sizeof(rxBuf), NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX1 );
  385. if( ret != ERR_TIMEOUT )
  386. {
  387. return ret;
  388. }
  389. return ERR_NONE;
  390. }
  391. /*******************************************************************************/
  392. ReturnCode rfalNfcvPollerSelect( uint8_t flags, const uint8_t* uid )
  393. {
  394. uint16_t rcvLen;
  395. rfalNfcvGenericRes res;
  396. if( uid == NULL )
  397. {
  398. return ERR_PARAM;
  399. }
  400. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_SELECT, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
  401. }
  402. /*******************************************************************************/
  403. ReturnCode rfalNfcvPollerReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  404. {
  405. uint8_t bn;
  406. bn = blockNum;
  407. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), rxBuf, rxBufLen, rcvLen );
  408. }
  409. /*******************************************************************************/
  410. ReturnCode rfalNfcvPollerWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, const uint8_t* wrData, uint8_t blockLen )
  411. {
  412. uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_MAX_BLOCK_LEN)];
  413. uint8_t dataLen;
  414. uint16_t rcvLen;
  415. rfalNfcvGenericRes res;
  416. /* Check for valid parameters */
  417. if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL) )
  418. {
  419. return ERR_PARAM;
  420. }
  421. dataLen = 0U;
  422. /* Compute Request Data */
  423. data[dataLen++] = blockNum; /* Set Block Number (8 bits) */
  424. ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */
  425. dataLen += blockLen;
  426. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
  427. }
  428. /*******************************************************************************/
  429. ReturnCode rfalNfcvPollerLockBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum )
  430. {
  431. uint16_t rcvLen;
  432. rfalNfcvGenericRes res;
  433. uint8_t bn;
  434. bn = blockNum;
  435. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_LOCK_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
  436. }
  437. /*******************************************************************************/
  438. ReturnCode rfalNfcvPollerReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  439. {
  440. uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)];
  441. uint8_t dataLen;
  442. dataLen = 0U;
  443. /* Compute Request Data */
  444. data[dataLen++] = firstBlockNum; /* Set first Block Number */
  445. data[dataLen++] = numOfBlocks; /* Set number of blocks to read */
  446. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
  447. }
  448. /*******************************************************************************/
  449. 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 )
  450. {
  451. ReturnCode ret;
  452. uint16_t rcvLen;
  453. uint16_t reqLen;
  454. rfalNfcvGenericRes res;
  455. uint16_t msgIt;
  456. /* Calculate required buffer length */
  457. 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));
  458. if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || ((((uint16_t)numOfBlocks) * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) || (wrData == NULL) )
  459. {
  460. return ERR_PARAM;
  461. }
  462. msgIt = 0;
  463. /* Compute Request Command */
  464. txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
  465. txBuf[msgIt++] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS;
  466. /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
  467. if( uid != NULL )
  468. {
  469. txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
  470. ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN );
  471. msgIt += (uint8_t)RFAL_NFCV_UID_LEN;
  472. }
  473. txBuf[msgIt++] = firstBlockNum;
  474. txBuf[msgIt++] = (numOfBlocks - 1U);
  475. if( wrDataLen > 0U ) /* MISRA 21.18 */
  476. {
  477. ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen );
  478. msgIt += wrDataLen;
  479. }
  480. /* Transceive Command */
  481. ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX );
  482. if( ret != ERR_NONE )
  483. {
  484. return ret;
  485. }
  486. /* Check if the response minimum length has been received */
  487. if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN )
  488. {
  489. return ERR_PROTO;
  490. }
  491. /* Check if an error has been signalled */
  492. if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
  493. {
  494. return rfalNfcvParseError( *res.data );
  495. }
  496. return ERR_NONE;
  497. }
  498. /*******************************************************************************/
  499. ReturnCode rfalNfcvPollerExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  500. {
  501. uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN];
  502. uint8_t dataLen;
  503. dataLen = 0U;
  504. /* Compute Request Data */
  505. 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. */
  506. data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
  507. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
  508. }
  509. /*******************************************************************************/
  510. ReturnCode rfalNfcvPollerExtendedWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen )
  511. {
  512. uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_MAX_BLOCK_LEN)];
  513. uint8_t dataLen;
  514. uint16_t rcvLen;
  515. rfalNfcvGenericRes res;
  516. /* Check for valid parameters */
  517. if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) )
  518. {
  519. return ERR_PARAM;
  520. }
  521. dataLen = 0U;
  522. /* Compute Request Data */
  523. 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. */
  524. data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
  525. ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */
  526. dataLen += blockLen;
  527. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
  528. }
  529. /*******************************************************************************/
  530. ReturnCode rfalNfcvPollerExtendedLockSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum )
  531. {
  532. uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN];
  533. uint8_t dataLen;
  534. uint16_t rcvLen;
  535. rfalNfcvGenericRes res;
  536. dataLen = 0U;
  537. /* Compute Request Data */
  538. 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. */
  539. data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
  540. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
  541. }
  542. /*******************************************************************************/
  543. ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  544. {
  545. uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)];
  546. uint8_t dataLen;
  547. dataLen = 0U;
  548. /* Compute Request Data */
  549. data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU);
  550. data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU);
  551. data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU);
  552. data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU);
  553. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
  554. }
  555. /*******************************************************************************/
  556. 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 )
  557. {
  558. ReturnCode ret;
  559. uint16_t rcvLen;
  560. uint16_t reqLen;
  561. rfalNfcvGenericRes res;
  562. uint16_t msgIt;
  563. uint16_t nBlocks;
  564. /* Calculate required buffer length */
  565. reqLen = ((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen) );
  566. if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (( (uint16_t)numOfBlocks * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) )
  567. {
  568. return ERR_PARAM;
  569. }
  570. msgIt = 0;
  571. nBlocks = (numOfBlocks - 1U);
  572. /* Compute Request Command */
  573. txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
  574. txBuf[msgIt++] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK;
  575. /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
  576. if( uid != NULL )
  577. {
  578. txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
  579. ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN );
  580. msgIt += (uint8_t)RFAL_NFCV_UID_LEN;
  581. }
  582. txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 0) & 0xFFU);
  583. txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 8) & 0xFFU);
  584. txBuf[msgIt++] = (uint8_t)((nBlocks >> 0) & 0xFFU);
  585. txBuf[msgIt++] = (uint8_t)((nBlocks >> 8) & 0xFFU);
  586. if( wrDataLen > 0U ) /* MISRA 21.18 */
  587. {
  588. ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen );
  589. msgIt += wrDataLen;
  590. }
  591. /* Transceive Command */
  592. ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX );
  593. if( ret != ERR_NONE )
  594. {
  595. return ret;
  596. }
  597. /* Check if the response minimum length has been received */
  598. if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN )
  599. {
  600. return ERR_PROTO;
  601. }
  602. /* Check if an error has been signalled */
  603. if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
  604. {
  605. return rfalNfcvParseError( *res.data );
  606. }
  607. return ERR_NONE;
  608. }
  609. /*******************************************************************************/
  610. ReturnCode rfalNfcvPollerGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  611. {
  612. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_GET_SYS_INFO, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen );
  613. }
  614. /*******************************************************************************/
  615. ReturnCode rfalNfcvPollerExtendedGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t requestField, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
  616. {
  617. return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO, flags, requestField, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen );
  618. }
  619. /*******************************************************************************/
  620. 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 )
  621. {
  622. ReturnCode ret;
  623. rfalNfcvGenericReq req;
  624. uint8_t msgIt;
  625. rfalBitRate rxBR;
  626. bool fastMode;
  627. msgIt = 0;
  628. fastMode = false;
  629. /* Check for valid parameters */
  630. if( (rxBuf == NULL) || (rcvLen == NULL) || ((dataLen > 0U) && (data == NULL)) ||
  631. (dataLen > ((uid != NULL) ? RFAL_NFCV_MAX_GEN_DATA_LEN : (RFAL_NFCV_MAX_GEN_DATA_LEN - RFAL_NFCV_UID_LEN))) )
  632. {
  633. return ERR_PARAM;
  634. }
  635. /* Check if the command is an ST's Fast command */
  636. if( (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK) ||
  637. (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS) ||
  638. (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH) ||
  639. (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION) ||
  640. (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION) )
  641. {
  642. /* Store current Rx bit rate and move to fast mode */
  643. rfalGetBitRate( NULL, &rxBR );
  644. rfalSetBitRate( RFAL_BR_KEEP, RFAL_BR_52p97 );
  645. fastMode = true;
  646. }
  647. /* Compute Request Command */
  648. req.REQ_FLAG = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
  649. req.CMD = cmd;
  650. /* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */
  651. if( param != RFAL_NFCV_PARAM_SKIP )
  652. {
  653. req.payload.data[msgIt++] = param;
  654. }
  655. /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
  656. if( uid != NULL )
  657. {
  658. req.REQ_FLAG |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
  659. ST_MEMCPY( &req.payload.data[msgIt], uid, RFAL_NFCV_UID_LEN );
  660. msgIt += RFAL_NFCV_UID_LEN;
  661. }
  662. if( dataLen > 0U )
  663. {
  664. ST_MEMCPY( &req.payload.data[msgIt], data, dataLen);
  665. msgIt += (uint8_t)dataLen;
  666. }
  667. /* Transceive Command */
  668. 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 );
  669. /* 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 */
  670. 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) ||
  671. (cmd == (uint8_t)RFAL_NFCV_CMD_LOCK_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK) ||
  672. (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK)) )
  673. {
  674. ret = rfalISO15693TransceiveEOF( rxBuf, (uint8_t)rxBufLen, rcvLen );
  675. }
  676. /* Restore Rx BitRate */
  677. if( fastMode )
  678. {
  679. rfalSetBitRate( RFAL_BR_KEEP, rxBR );
  680. }
  681. if( ret != ERR_NONE )
  682. {
  683. return ret;
  684. }
  685. /* Check if the response minimum length has been received */
  686. if( (*rcvLen) < (uint8_t)RFAL_NFCV_FLAG_LEN )
  687. {
  688. return ERR_PROTO;
  689. }
  690. /* Check if an error has been signalled */
  691. if( (rxBuf[RFAL_NFCV_FLAG_POS] & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
  692. {
  693. return rfalNfcvParseError( rxBuf[RFAL_NFCV_DATASTART_POS] );
  694. }
  695. return ERR_NONE;
  696. }
  697. #endif /* RFAL_FEATURE_NFCV */