rfal_nfcb.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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_nfcb.c
  27. *
  28. * \author Gustavo Patricio
  29. *
  30. * \brief Implementation of NFC-B (ISO14443B) helpers
  31. *
  32. */
  33. /*
  34. ******************************************************************************
  35. * INCLUDES
  36. ******************************************************************************
  37. */
  38. #include "rfal_nfcb.h"
  39. #include "utils.h"
  40. /*
  41. ******************************************************************************
  42. * ENABLE SWITCH
  43. ******************************************************************************
  44. */
  45. #ifndef RFAL_FEATURE_NFCB
  46. #define RFAL_FEATURE_NFCB false /* NFC-B module configuration missing. Disabled by default */
  47. #endif
  48. #if RFAL_FEATURE_NFCB
  49. /*
  50. ******************************************************************************
  51. * GLOBAL DEFINES
  52. ******************************************************************************
  53. */
  54. #define RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED 0x10U /*!< Bit mask for Extended SensB Response support in SENSB_REQ */
  55. #define RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */
  56. #define RFAL_NFCB_SLOT_MARKER_SC_SHIFT 4U /*!< Slot Code position on SLOT_MARKER APn */
  57. #define RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN 1U /*!< SLOT_MARKER Slot Code minimum Digital 1.1 Table 37 */
  58. #define RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX 16U /*!< SLOT_MARKER Slot Code maximum Digital 1.1 Table 37 */
  59. #define RFAL_NFCB_ACTIVATION_FWT (RFAL_NFCB_FWTSENSB + RFAL_NFCB_DTPOLL_20) /*!< FWT(SENSB) + dTbPoll Digital 2.0 7.9.1.3 */
  60. /*! Advanced and Extended bit mask in Parameter of SENSB_REQ */
  61. #define RFAL_NFCB_SENSB_REQ_PARAM (RFAL_NFCB_SENSB_REQ_ADV_FEATURE | RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED)
  62. /*! NFC-B commands definition */
  63. enum
  64. {
  65. RFAL_NFCB_CMD_SENSB_REQ = 0x05, /*!< SENSB_REQ (REQB) & SLOT_MARKER Digital 1.1 Table 24 */
  66. RFAL_NFCB_CMD_SENSB_RES = 0x50, /*!< SENSB_RES (ATQB) & SLOT_MARKER Digital 1.1 Table 27 */
  67. RFAL_NFCB_CMD_SLPB_REQ = 0x50, /*!< SLPB_REQ (HLTB command) Digital 1.1 Table 38 */
  68. RFAL_NFCB_CMD_SLPB_RES = 0x00 /*!< SLPB_RES (HLTB Answer) Digital 1.1 Table 39 */
  69. };
  70. /*
  71. ******************************************************************************
  72. * GLOBAL MACROS
  73. ******************************************************************************
  74. */
  75. #define rfalNfcbNI2NumberOfSlots( ni ) (uint8_t)(1U << (ni)) /*!< Converts the Number of slots Identifier to slot number */
  76. /*
  77. ******************************************************************************
  78. * GLOBAL TYPES
  79. ******************************************************************************
  80. */
  81. /*! ALLB_REQ (WUPB) and SENSB_REQ (REQB) Command Format Digital 1.1 7.6.1 */
  82. typedef struct
  83. {
  84. uint8_t cmd; /*!< xxxxB_REQ: 05h */
  85. uint8_t AFI; /*!< NFC Identifier */
  86. uint8_t PARAM; /*!< Application Data */
  87. } rfalNfcbSensbReq;
  88. /*! SLOT_MARKER Command format Digital 1.1 7.7.1 */
  89. typedef struct
  90. {
  91. uint8_t APn; /*!< Slot number 2..16 | 0101b */
  92. } rfalNfcbSlotMarker;
  93. /*! SLPB_REQ (HLTB) Command Format Digital 1.1 7.8.1 */
  94. typedef struct
  95. {
  96. uint8_t cmd; /*!< SLPB_REQ: 50h */
  97. uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/
  98. } rfalNfcbSlpbReq;
  99. /*! SLPB_RES (HLTB) Response Format Digital 1.1 7.8.2 */
  100. typedef struct
  101. {
  102. uint8_t cmd; /*!< SLPB_RES: 00h */
  103. } rfalNfcbSlpbRes;
  104. /*! RFAL NFC-B instance */
  105. typedef struct
  106. {
  107. uint8_t AFI; /*!< AFI to be used */
  108. uint8_t PARAM; /*!< PARAM to be used */
  109. } rfalNfcb;
  110. /*
  111. ******************************************************************************
  112. * LOCAL FUNCTION PROTOTYPES
  113. ******************************************************************************
  114. */
  115. static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen );
  116. /*
  117. ******************************************************************************
  118. * LOCAL VARIABLES
  119. ******************************************************************************
  120. */
  121. static rfalNfcb gRfalNfcb; /*!< RFAL NFC-B Instance */
  122. /*
  123. ******************************************************************************
  124. * LOCAL FUNCTIONS
  125. ******************************************************************************
  126. */
  127. /*******************************************************************************/
  128. static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen )
  129. {
  130. /* Check response length */
  131. if( ( (sensbResLen != RFAL_NFCB_SENSB_RES_LEN) && (sensbResLen != RFAL_NFCB_SENSB_RES_EXT_LEN) ) )
  132. {
  133. return ERR_PROTO;
  134. }
  135. /* Check SENSB_RES and Protocol Type Digital 1.1 7.6.2.19 */
  136. if( ((sensbRes->protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU) != 0U) || (sensbRes->cmd != (uint8_t)RFAL_NFCB_CMD_SENSB_RES) )
  137. {
  138. return ERR_PROTO;
  139. }
  140. return ERR_NONE;
  141. }
  142. /*
  143. ******************************************************************************
  144. * GLOBAL FUNCTIONS
  145. ******************************************************************************
  146. */
  147. /*******************************************************************************/
  148. ReturnCode rfalNfcbPollerInitialize( void )
  149. {
  150. ReturnCode ret;
  151. EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCB, RFAL_BR_106, RFAL_BR_106 ) );
  152. rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
  153. rfalSetGT( RFAL_GT_NFCB );
  154. rfalSetFDTListen( RFAL_FDT_LISTEN_NFCB_POLLER );
  155. rfalSetFDTPoll( RFAL_FDT_POLL_NFCB_POLLER );
  156. gRfalNfcb.AFI = RFAL_NFCB_AFI;
  157. gRfalNfcb.PARAM = RFAL_NFCB_PARAM;
  158. return ERR_NONE;
  159. }
  160. /*******************************************************************************/
  161. ReturnCode rfalNfcbPollerInitializeWithParams( uint8_t AFI, uint8_t PARAM )
  162. {
  163. ReturnCode ret;
  164. EXIT_ON_ERR( ret, rfalNfcbPollerInitialize() );
  165. gRfalNfcb.AFI = AFI;
  166. gRfalNfcb.PARAM = (PARAM & RFAL_NFCB_SENSB_REQ_PARAM);
  167. return ERR_NONE;
  168. }
  169. /*******************************************************************************/
  170. ReturnCode rfalNfcbPollerCheckPresence( rfalNfcbSensCmd cmd, rfalNfcbSlots slots, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
  171. {
  172. uint16_t rxLen;
  173. ReturnCode ret;
  174. rfalNfcbSensbReq sensbReq;
  175. /* Check if the command requested and given the slot number are valid */
  176. if( ((RFAL_NFCB_SENS_CMD_SENSB_REQ != cmd) && (RFAL_NFCB_SENS_CMD_ALLB_REQ != cmd)) ||
  177. (slots > RFAL_NFCB_SLOT_NUM_16) || (sensbRes == NULL) || (sensbResLen == NULL) )
  178. {
  179. return ERR_PARAM;
  180. }
  181. *sensbResLen = 0;
  182. ST_MEMSET(sensbRes, 0x00, sizeof(rfalNfcbSensbRes) );
  183. /* Compute SENSB_REQ */
  184. sensbReq.cmd = RFAL_NFCB_CMD_SENSB_REQ;
  185. sensbReq.AFI = gRfalNfcb.AFI;
  186. sensbReq.PARAM = (((uint8_t)gRfalNfcb.PARAM & RFAL_NFCB_SENSB_REQ_PARAM) | (uint8_t)cmd | (uint8_t)slots);
  187. /* Send SENSB_REQ and disable AGC to detect collisions */
  188. ret = rfalTransceiveBlockingTxRx( (uint8_t*)&sensbReq, sizeof(rfalNfcbSensbReq), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_FWTSENSB );
  189. *sensbResLen = (uint8_t)rxLen;
  190. /* Check if a transmission error was detected */
  191. if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
  192. {
  193. /* Invalidate received frame as an error was detected (CollisionResolution checks if valid) */
  194. *sensbResLen = 0;
  195. return ERR_NONE;
  196. }
  197. if( ret == ERR_NONE )
  198. {
  199. return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen );
  200. }
  201. return ret;
  202. }
  203. /*******************************************************************************/
  204. ReturnCode rfalNfcbPollerSleep( const uint8_t* nfcid0 )
  205. {
  206. uint16_t rxLen;
  207. ReturnCode ret;
  208. rfalNfcbSlpbReq slpbReq;
  209. rfalNfcbSlpbRes slpbRes;
  210. if( nfcid0 == NULL )
  211. {
  212. return ERR_PARAM;
  213. }
  214. /* Compute SLPB_REQ */
  215. slpbReq.cmd = RFAL_NFCB_CMD_SLPB_REQ;
  216. ST_MEMCPY( slpbReq.nfcid0, nfcid0, RFAL_NFCB_NFCID0_LEN );
  217. EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&slpbReq, sizeof(rfalNfcbSlpbReq), (uint8_t*)&slpbRes, sizeof(rfalNfcbSlpbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT ));
  218. /* Check SLPB_RES */
  219. if( (rxLen != sizeof(rfalNfcbSlpbRes)) || (slpbRes.cmd != (uint8_t)RFAL_NFCB_CMD_SLPB_RES) )
  220. {
  221. return ERR_PROTO;
  222. }
  223. return ERR_NONE;
  224. }
  225. /*******************************************************************************/
  226. ReturnCode rfalNfcbPollerSlotMarker( uint8_t slotCode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
  227. {
  228. ReturnCode ret;
  229. rfalNfcbSlotMarker slotMarker;
  230. uint16_t rxLen;
  231. /* Check parameters */
  232. if( (sensbRes == NULL) || (sensbResLen == NULL) ||
  233. (slotCode < RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN) ||
  234. (slotCode > RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX) )
  235. {
  236. return ERR_PARAM;
  237. }
  238. /* Compose and send SLOT_MARKER with disabled AGC to detect collisions */
  239. slotMarker.APn = ((slotCode << RFAL_NFCB_SLOT_MARKER_SC_SHIFT) | (uint8_t)RFAL_NFCB_CMD_SENSB_REQ);
  240. ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slotMarker, sizeof(rfalNfcbSlotMarker), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT );
  241. *sensbResLen = (uint8_t)rxLen;
  242. /* Check if a transmission error was detected */
  243. if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
  244. {
  245. return ERR_RF_COLLISION;
  246. }
  247. if( ret == ERR_NONE )
  248. {
  249. return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen );
  250. }
  251. return ret;
  252. }
  253. ReturnCode rfalNfcbPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
  254. {
  255. NO_WARNING(compMode);
  256. return rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, RFAL_NFCB_SLOT_NUM_1, sensbRes, sensbResLen );
  257. }
  258. /*******************************************************************************/
  259. ReturnCode rfalNfcbPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt )
  260. {
  261. bool colPending; /* dummy */
  262. return rfalNfcbPollerSlottedCollisionResolution( compMode, devLimit, RFAL_NFCB_SLOT_NUM_1, RFAL_NFCB_SLOT_NUM_16, nfcbDevList, devCnt, &colPending );
  263. }
  264. /*******************************************************************************/
  265. ReturnCode rfalNfcbPollerSlottedCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbSlots initSlots, rfalNfcbSlots endSlots, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt, bool *colPending )
  266. {
  267. ReturnCode ret;
  268. uint8_t slotsNum;
  269. uint8_t slotCode;
  270. uint8_t curDevCnt;
  271. /* Check parameters. In ISO | Activity 1.0 mode the initial slots must be 1 as continuation of Technology Detection */
  272. if( (nfcbDevList == NULL) || (devCnt == NULL) || (colPending == NULL) || (initSlots > RFAL_NFCB_SLOT_NUM_16) ||
  273. (endSlots > RFAL_NFCB_SLOT_NUM_16) || ((compMode == RFAL_COMPLIANCE_MODE_ISO) && (initSlots != RFAL_NFCB_SLOT_NUM_1)) )
  274. {
  275. return ERR_PARAM;
  276. }
  277. /* Initialise as no error in case Activity 1.0 where the previous SENSB_RES from technology detection should be used */
  278. ret = ERR_NONE;
  279. *devCnt = 0;
  280. curDevCnt = 0;
  281. *colPending = false;
  282. /* Send ALLB_REQ Activity 1.1 9.3.5.2 and 9.3.5.3 (Symbol 1 and 2) */
  283. if( compMode != RFAL_COMPLIANCE_MODE_ISO )
  284. {
  285. ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_ALLB_REQ, initSlots, &nfcbDevList->sensbRes, &nfcbDevList->sensbResLen );
  286. if( (ret != ERR_NONE) && (initSlots == RFAL_NFCB_SLOT_NUM_1) )
  287. {
  288. return ret;
  289. }
  290. }
  291. /* Check if there was a transmission error on WUPB EMVCo 2.6 9.3.3.1 */
  292. if( (compMode == RFAL_COMPLIANCE_MODE_EMV) && (nfcbDevList->sensbResLen == 0U) )
  293. {
  294. return ERR_FRAMING;
  295. }
  296. for( slotsNum = (uint8_t)initSlots; slotsNum <= (uint8_t)endSlots; slotsNum++ )
  297. {
  298. do {
  299. /* Activity 1.1 9.3.5.23 - Symbol 22 */
  300. if( (compMode == RFAL_COMPLIANCE_MODE_NFC) && (curDevCnt != 0U) )
  301. {
  302. rfalNfcbPollerSleep( nfcbDevList[((*devCnt) - (uint8_t)1U)].sensbRes.nfcid0 );
  303. nfcbDevList[((*devCnt) - (uint8_t)1U)].isSleep = true;
  304. }
  305. /* Send SENSB_REQ with number of slots if not the first Activity 1.1 9.3.5.24 - Symbol 23 */
  306. if( (slotsNum != (uint8_t)initSlots) || *colPending )
  307. {
  308. /* PRQA S 4342 1 # MISRA 10.5 - Layout of rfalNfcbSlots and above loop guarantee that no invalid enum values are created. */
  309. ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, (rfalNfcbSlots)slotsNum, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen );
  310. }
  311. /* Activity 1.1 9.3.5.6 - Symbol 5 */
  312. slotCode = 0;
  313. curDevCnt = 0;
  314. *colPending = false;
  315. do{
  316. /* Activity 1.1 9.3.5.26 - Symbol 25 */
  317. if( slotCode != 0U )
  318. {
  319. ret = rfalNfcbPollerSlotMarker( slotCode, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen );
  320. }
  321. /* Activity 1.1 9.3.5.7 and 9.3.5.8 - Symbol 6 */
  322. if( ret != ERR_TIMEOUT )
  323. {
  324. /* Activity 1.1 9.3.5.8 - Symbol 7 */
  325. if( (rfalNfcbCheckSensbRes( &nfcbDevList[*devCnt].sensbRes, nfcbDevList[*devCnt].sensbResLen) == ERR_NONE) && (ret == ERR_NONE) )
  326. {
  327. nfcbDevList[*devCnt].isSleep = false;
  328. if( compMode == RFAL_COMPLIANCE_MODE_EMV )
  329. {
  330. (*devCnt)++;
  331. return ret;
  332. }
  333. else if( compMode == RFAL_COMPLIANCE_MODE_ISO )
  334. {
  335. /* Activity 1.0 9.3.5.8 - Symbol 7 */
  336. (*devCnt)++;
  337. curDevCnt++;
  338. /* Activity 1.0 9.3.5.10 - Symbol 9 */
  339. if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
  340. {
  341. return ret;
  342. }
  343. /* Activity 1.0 9.3.5.11 - Symbol 10 */
  344. rfalNfcbPollerSleep( nfcbDevList[*devCnt-1U].sensbRes.nfcid0 );
  345. nfcbDevList[*devCnt-1U].isSleep = true;
  346. }
  347. else if( compMode == RFAL_COMPLIANCE_MODE_NFC )
  348. {
  349. /* Activity 1.1 9.3.5.10 and 9.3.5.11 - Symbol 9 and Symbol 11*/
  350. if(curDevCnt != 0U)
  351. {
  352. rfalNfcbPollerSleep( nfcbDevList[(*devCnt) - (uint8_t)1U].sensbRes.nfcid0 );
  353. nfcbDevList[(*devCnt) - (uint8_t)1U].isSleep = true;
  354. }
  355. /* Activity 1.1 9.3.5.12 - Symbol 11 */
  356. (*devCnt)++;
  357. curDevCnt++;
  358. /* Activity 1.1 9.3.5.6 - Symbol 13 */
  359. if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
  360. {
  361. return ret;
  362. }
  363. }
  364. else
  365. {
  366. /* MISRA 15.7 - Empty else */
  367. }
  368. }
  369. else
  370. {
  371. /* If deviceLimit is set to 0 the NFC Forum Device is configured to perform collision detection only Activity 1.0 and 1.1 9.3.5.5 - Symbol 4 */
  372. if( (devLimit == 0U) && (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
  373. {
  374. return ERR_RF_COLLISION;
  375. }
  376. /* Activity 1.1 9.3.5.9 - Symbol 8 */
  377. *colPending = true;
  378. }
  379. }
  380. /* Activity 1.1 9.3.5.15 - Symbol 14 */
  381. slotCode++;
  382. }
  383. while( slotCode < rfalNfcbNI2NumberOfSlots(slotsNum) );
  384. /* Activity 1.1 9.3.5.17 - Symbol 16 */
  385. if( !(*colPending) )
  386. {
  387. return ERR_NONE;
  388. }
  389. /* Activity 1.1 9.3.5.18 - Symbol 17 */
  390. } while (curDevCnt != 0U); /* If a collision is detected and card(s) were found on this loop keep the same number of available slots */
  391. }
  392. return ERR_NONE;
  393. }
  394. /*******************************************************************************/
  395. uint32_t rfalNfcbTR2ToFDT( uint8_t tr2Code )
  396. {
  397. /*******************************************************************************/
  398. /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */
  399. /*! TR2 Table according to Digital 1.1 Table 33 */
  400. const uint16_t rfalNfcbTr2Table[] = { 1792, 3328, 5376, 9472 };
  401. /*******************************************************************************/
  402. return rfalNfcbTr2Table[ (tr2Code & RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK) ];
  403. }
  404. #endif /* RFAL_FEATURE_NFCB */