furi_hal_nfc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include "furi_hal_nfc.h"
  2. #include <st25r3916.h>
  3. #include <rfal_rf.h>
  4. #include <furi.h>
  5. #include <m-string.h>
  6. #include <lib/nfc_protocols/nfca.h>
  7. #define TAG "FuriHalNfc"
  8. static const uint32_t clocks_in_ms = 64 * 1000;
  9. osEventFlagsId_t event = NULL;
  10. #define EVENT_FLAG_INTERRUPT (1UL << 0)
  11. #define EVENT_FLAG_STATE_CHANGED (1UL << 1)
  12. #define EVENT_FLAG_STOP (1UL << 2)
  13. #define EVENT_FLAG_ALL (EVENT_FLAG_INTERRUPT | EVENT_FLAG_STATE_CHANGED | EVENT_FLAG_STOP)
  14. void furi_hal_nfc_init() {
  15. ReturnCode ret = rfalNfcInitialize();
  16. if(ret == ERR_NONE) {
  17. furi_hal_nfc_start_sleep();
  18. event = osEventFlagsNew(NULL);
  19. FURI_LOG_I(TAG, "Init OK");
  20. } else {
  21. FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret);
  22. }
  23. }
  24. bool furi_hal_nfc_is_busy() {
  25. return rfalNfcGetState() != RFAL_NFC_STATE_IDLE;
  26. }
  27. void furi_hal_nfc_field_on() {
  28. furi_hal_nfc_exit_sleep();
  29. st25r3916TxRxOn();
  30. }
  31. void furi_hal_nfc_field_off() {
  32. st25r3916TxRxOff();
  33. furi_hal_nfc_start_sleep();
  34. }
  35. void furi_hal_nfc_start_sleep() {
  36. rfalLowPowerModeStart();
  37. }
  38. void furi_hal_nfc_exit_sleep() {
  39. rfalLowPowerModeStop();
  40. }
  41. bool furi_hal_nfc_detect(
  42. rfalNfcDevice** dev_list,
  43. uint8_t* dev_cnt,
  44. uint32_t timeout,
  45. bool deactivate) {
  46. furi_assert(dev_list);
  47. furi_assert(dev_cnt);
  48. rfalLowPowerModeStop();
  49. rfalNfcState state = rfalNfcGetState();
  50. if(state == RFAL_NFC_STATE_NOTINIT) {
  51. rfalNfcInitialize();
  52. }
  53. rfalNfcDiscoverParam params;
  54. params.compMode = RFAL_COMPLIANCE_MODE_EMV;
  55. params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F |
  56. RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB;
  57. params.totalDuration = 1000;
  58. params.devLimit = 3;
  59. params.wakeupEnabled = false;
  60. params.wakeupConfigDefault = true;
  61. params.nfcfBR = RFAL_BR_212;
  62. params.ap2pBR = RFAL_BR_424;
  63. params.maxBR = RFAL_BR_KEEP;
  64. params.GBLen = RFAL_NFCDEP_GB_MAX_LEN;
  65. params.notifyCb = NULL;
  66. uint32_t start = DWT->CYCCNT;
  67. rfalNfcDiscover(&params);
  68. while(state != RFAL_NFC_STATE_ACTIVATED) {
  69. rfalNfcWorker();
  70. state = rfalNfcGetState();
  71. FURI_LOG_T(TAG, "Current state %d", state);
  72. if(state == RFAL_NFC_STATE_POLL_ACTIVATION) {
  73. start = DWT->CYCCNT;
  74. continue;
  75. }
  76. if(state == RFAL_NFC_STATE_POLL_SELECT) {
  77. rfalNfcSelect(0);
  78. }
  79. if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
  80. rfalNfcDeactivate(true);
  81. FURI_LOG_T(TAG, "Timeout");
  82. return false;
  83. }
  84. osThreadYield();
  85. }
  86. rfalNfcGetDevicesFound(dev_list, dev_cnt);
  87. if(deactivate) {
  88. rfalNfcDeactivate(false);
  89. rfalLowPowerModeStart();
  90. }
  91. return true;
  92. }
  93. bool furi_hal_nfc_listen(
  94. uint8_t* uid,
  95. uint8_t uid_len,
  96. uint8_t* atqa,
  97. uint8_t sak,
  98. bool activate_after_sak,
  99. uint32_t timeout) {
  100. rfalNfcState state = rfalNfcGetState();
  101. if(state == RFAL_NFC_STATE_NOTINIT) {
  102. rfalNfcInitialize();
  103. } else if(state >= RFAL_NFC_STATE_ACTIVATED) {
  104. rfalNfcDeactivate(false);
  105. }
  106. rfalLowPowerModeStop();
  107. rfalNfcDiscoverParam params = {
  108. .compMode = RFAL_COMPLIANCE_MODE_NFC,
  109. .techs2Find = RFAL_NFC_LISTEN_TECH_A,
  110. .totalDuration = 1000,
  111. .devLimit = 1,
  112. .wakeupEnabled = false,
  113. .wakeupConfigDefault = true,
  114. .nfcfBR = RFAL_BR_212,
  115. .ap2pBR = RFAL_BR_424,
  116. .maxBR = RFAL_BR_KEEP,
  117. .GBLen = RFAL_NFCDEP_GB_MAX_LEN,
  118. .notifyCb = NULL,
  119. .activate_after_sak = activate_after_sak,
  120. };
  121. params.lmConfigPA.nfcidLen = uid_len;
  122. memcpy(params.lmConfigPA.nfcid, uid, uid_len);
  123. params.lmConfigPA.SENS_RES[0] = atqa[0];
  124. params.lmConfigPA.SENS_RES[1] = atqa[1];
  125. params.lmConfigPA.SEL_RES = sak;
  126. rfalNfcDiscover(&params);
  127. uint32_t start = DWT->CYCCNT;
  128. while(state != RFAL_NFC_STATE_ACTIVATED) {
  129. rfalNfcWorker();
  130. state = rfalNfcGetState();
  131. if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
  132. rfalNfcDeactivate(true);
  133. return false;
  134. }
  135. osThreadYield();
  136. }
  137. return true;
  138. }
  139. void rfal_interrupt_callback_handler() {
  140. osEventFlagsSet(event, EVENT_FLAG_INTERRUPT);
  141. }
  142. void rfal_state_changed_callback(void* context) {
  143. osEventFlagsSet(event, EVENT_FLAG_STATE_CHANGED);
  144. }
  145. void furi_hal_nfc_stop() {
  146. if(event) {
  147. osEventFlagsSet(event, EVENT_FLAG_STOP);
  148. }
  149. }
  150. bool furi_hal_nfc_emulate_nfca(
  151. uint8_t* uid,
  152. uint8_t uid_len,
  153. uint8_t* atqa,
  154. uint8_t sak,
  155. FuriHalNfcEmulateCallback callback,
  156. void* context,
  157. uint32_t timeout) {
  158. rfalSetUpperLayerCallback(rfal_interrupt_callback_handler);
  159. rfal_set_state_changed_callback(rfal_state_changed_callback);
  160. rfalLmConfPA config;
  161. config.nfcidLen = uid_len;
  162. memcpy(config.nfcid, uid, uid_len);
  163. memcpy(config.SENS_RES, atqa, RFAL_LM_SENS_RES_LEN);
  164. config.SEL_RES = sak;
  165. uint8_t buff_rx[256];
  166. uint16_t buff_rx_size = 256;
  167. uint16_t buff_rx_len = 0;
  168. uint8_t buff_tx[256];
  169. uint16_t buff_tx_len = 0;
  170. uint32_t data_type = FURI_HAL_NFC_TXRX_DEFAULT;
  171. rfalLowPowerModeStop();
  172. if(rfalListenStart(
  173. RFAL_LM_MASK_NFCA,
  174. &config,
  175. NULL,
  176. NULL,
  177. buff_rx,
  178. rfalConvBytesToBits(buff_rx_size),
  179. &buff_rx_len)) {
  180. rfalListenStop();
  181. FURI_LOG_E(TAG, "Failed to start listen mode");
  182. return false;
  183. }
  184. while(true) {
  185. buff_rx_len = 0;
  186. buff_tx_len = 0;
  187. uint32_t flag = osEventFlagsWait(event, EVENT_FLAG_ALL, osFlagsWaitAny, timeout);
  188. if(flag == osErrorTimeout || flag == EVENT_FLAG_STOP) {
  189. break;
  190. }
  191. bool data_received = false;
  192. buff_rx_len = 0;
  193. rfalWorker();
  194. rfalLmState state = rfalListenGetState(&data_received, NULL);
  195. if(data_received) {
  196. rfalTransceiveBlockingRx();
  197. if(nfca_emulation_handler(buff_rx, buff_rx_len, buff_tx, &buff_tx_len)) {
  198. if(rfalListenSleepStart(
  199. RFAL_LM_STATE_SLEEP_A,
  200. buff_rx,
  201. rfalConvBytesToBits(buff_rx_size),
  202. &buff_rx_len)) {
  203. FURI_LOG_E(TAG, "Failed to enter sleep mode");
  204. break;
  205. } else {
  206. continue;
  207. }
  208. }
  209. if(buff_tx_len) {
  210. ReturnCode ret = rfalTransceiveBitsBlockingTx(
  211. buff_tx,
  212. buff_tx_len,
  213. buff_rx,
  214. sizeof(buff_rx),
  215. &buff_rx_len,
  216. data_type,
  217. RFAL_FWT_NONE);
  218. if(ret) {
  219. FURI_LOG_E(TAG, "Tranceive failed with status %d", ret);
  220. break;
  221. }
  222. continue;
  223. }
  224. if((state == RFAL_LM_STATE_ACTIVE_A || state == RFAL_LM_STATE_ACTIVE_Ax)) {
  225. if(callback) {
  226. callback(buff_rx, buff_rx_len, buff_tx, &buff_tx_len, &data_type, context);
  227. }
  228. if(!rfalIsExtFieldOn()) {
  229. break;
  230. }
  231. if(buff_tx_len) {
  232. ReturnCode ret = rfalTransceiveBitsBlockingTx(
  233. buff_tx,
  234. buff_tx_len,
  235. buff_rx,
  236. sizeof(buff_rx),
  237. &buff_rx_len,
  238. data_type,
  239. RFAL_FWT_NONE);
  240. if(ret) {
  241. FURI_LOG_E(TAG, "Tranceive failed with status %d", ret);
  242. continue;
  243. }
  244. } else {
  245. break;
  246. }
  247. }
  248. }
  249. }
  250. rfalListenStop();
  251. return true;
  252. }
  253. bool furi_hal_nfc_get_first_frame(uint8_t** rx_buff, uint16_t** rx_len) {
  254. ReturnCode ret =
  255. rfalNfcDataExchangeStart(NULL, 0, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT);
  256. return ret == ERR_NONE;
  257. }
  258. ReturnCode furi_hal_nfc_data_exchange(
  259. uint8_t* tx_buff,
  260. uint16_t tx_len,
  261. uint8_t** rx_buff,
  262. uint16_t** rx_len,
  263. bool deactivate) {
  264. furi_assert(rx_buff);
  265. furi_assert(rx_len);
  266. ReturnCode ret;
  267. rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
  268. ret = rfalNfcDataExchangeStart(tx_buff, tx_len, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT);
  269. if(ret != ERR_NONE) {
  270. return ret;
  271. }
  272. uint32_t start = DWT->CYCCNT;
  273. while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
  274. rfalNfcWorker();
  275. state = rfalNfcGetState();
  276. ret = rfalNfcDataExchangeGetStatus();
  277. if(ret > ERR_SLEEP_REQ) {
  278. return ret;
  279. }
  280. if(ret == ERR_BUSY) {
  281. if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
  282. return ERR_TIMEOUT;
  283. }
  284. continue;
  285. } else {
  286. start = DWT->CYCCNT;
  287. }
  288. taskYIELD();
  289. }
  290. if(deactivate) {
  291. rfalNfcDeactivate(false);
  292. rfalLowPowerModeStart();
  293. }
  294. return ERR_NONE;
  295. }
  296. ReturnCode furi_hal_nfc_raw_bitstream_exchange(
  297. uint8_t* tx_buff,
  298. uint16_t tx_bit_len,
  299. uint8_t** rx_buff,
  300. uint16_t** rx_bit_len,
  301. bool deactivate) {
  302. furi_assert(rx_buff);
  303. furi_assert(rx_bit_len);
  304. ReturnCode ret;
  305. rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
  306. ret =
  307. rfalNfcDataExchangeStart(tx_buff, tx_bit_len, rx_buff, rx_bit_len, 0, RFAL_TXRX_FLAGS_RAW);
  308. if(ret != ERR_NONE) {
  309. return ret;
  310. }
  311. uint32_t start = DWT->CYCCNT;
  312. while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
  313. rfalNfcWorker();
  314. state = rfalNfcGetState();
  315. ret = rfalNfcDataExchangeGetStatus();
  316. if(ret > ERR_SLEEP_REQ) {
  317. return ret;
  318. }
  319. if(ret == ERR_BUSY) {
  320. if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
  321. return ERR_TIMEOUT;
  322. }
  323. continue;
  324. } else {
  325. start = DWT->CYCCNT;
  326. }
  327. taskYIELD();
  328. }
  329. if(deactivate) {
  330. rfalNfcDeactivate(false);
  331. rfalLowPowerModeStart();
  332. }
  333. return ERR_NONE;
  334. }
  335. void furi_hal_nfc_deactivate() {
  336. rfalNfcDeactivate(false);
  337. rfalLowPowerModeStart();
  338. }