furi-hal-nfc.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "furi-hal-nfc.h"
  2. #include <st25r3916.h>
  3. #define TAG "FuriHalNfc"
  4. static const uint32_t clocks_in_ms = 64 * 1000;
  5. void furi_hal_nfc_init() {
  6. ReturnCode ret = rfalNfcInitialize();
  7. if(ret == ERR_NONE) {
  8. furi_hal_nfc_start_sleep();
  9. FURI_LOG_I(TAG, "Init OK");
  10. } else {
  11. FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret);
  12. }
  13. }
  14. bool furi_hal_nfc_is_busy() {
  15. return rfalNfcGetState() != RFAL_NFC_STATE_IDLE;
  16. }
  17. void furi_hal_nfc_field_on() {
  18. furi_hal_nfc_exit_sleep();
  19. st25r3916TxRxOn();
  20. }
  21. void furi_hal_nfc_field_off() {
  22. st25r3916TxRxOff();
  23. furi_hal_nfc_start_sleep();
  24. }
  25. void furi_hal_nfc_start_sleep() {
  26. rfalLowPowerModeStart();
  27. }
  28. void furi_hal_nfc_exit_sleep() {
  29. rfalLowPowerModeStop();
  30. }
  31. bool furi_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t timeout, bool deactivate) {
  32. furi_assert(dev_list);
  33. furi_assert(dev_cnt);
  34. rfalLowPowerModeStop();
  35. rfalNfcState state = rfalNfcGetState();
  36. if(state == RFAL_NFC_STATE_NOTINIT) {
  37. rfalNfcInitialize();
  38. }
  39. rfalNfcDiscoverParam params;
  40. params.compMode = RFAL_COMPLIANCE_MODE_EMV;
  41. params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F |
  42. RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB;
  43. params.totalDuration = 1000;
  44. params.devLimit = 3;
  45. params.wakeupEnabled = false;
  46. params.wakeupConfigDefault = true;
  47. params.nfcfBR = RFAL_BR_212;
  48. params.ap2pBR = RFAL_BR_424;
  49. params.maxBR = RFAL_BR_KEEP;
  50. params.GBLen = RFAL_NFCDEP_GB_MAX_LEN;
  51. params.notifyCb = NULL;
  52. uint32_t start = DWT->CYCCNT;
  53. rfalNfcDiscover(&params);
  54. while(state != RFAL_NFC_STATE_ACTIVATED) {
  55. rfalNfcWorker();
  56. state = rfalNfcGetState();
  57. FURI_LOG_D(TAG, "Current state %d", state);
  58. if(state == RFAL_NFC_STATE_POLL_ACTIVATION) {
  59. start = DWT->CYCCNT;
  60. continue;
  61. }
  62. if(state == RFAL_NFC_STATE_POLL_SELECT) {
  63. rfalNfcSelect(0);
  64. }
  65. if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
  66. rfalNfcDeactivate(true);
  67. FURI_LOG_D(TAG, "Timeout");
  68. return false;
  69. }
  70. osThreadYield();
  71. }
  72. rfalNfcGetDevicesFound(dev_list, dev_cnt);
  73. if(deactivate) {
  74. rfalNfcDeactivate(false);
  75. rfalLowPowerModeStart();
  76. }
  77. return true;
  78. }
  79. bool furi_hal_nfc_listen(uint8_t* uid, uint8_t uid_len, uint8_t* atqa, uint8_t sak, bool activate_after_sak, uint32_t timeout) {
  80. rfalNfcState state = rfalNfcGetState();
  81. if(state == RFAL_NFC_STATE_NOTINIT) {
  82. rfalNfcInitialize();
  83. } else if(state >= RFAL_NFC_STATE_ACTIVATED) {
  84. rfalNfcDeactivate(false);
  85. }
  86. rfalLowPowerModeStop();
  87. rfalNfcDiscoverParam params = {
  88. .compMode = RFAL_COMPLIANCE_MODE_NFC,
  89. .techs2Find = RFAL_NFC_LISTEN_TECH_A,
  90. .totalDuration = 1000,
  91. .devLimit = 1,
  92. .wakeupEnabled = false,
  93. .wakeupConfigDefault = true,
  94. .nfcfBR = RFAL_BR_212,
  95. .ap2pBR = RFAL_BR_424,
  96. .maxBR = RFAL_BR_KEEP,
  97. .GBLen = RFAL_NFCDEP_GB_MAX_LEN,
  98. .notifyCb = NULL,
  99. .activate_after_sak = activate_after_sak,
  100. };
  101. params.lmConfigPA.nfcidLen = uid_len;
  102. memcpy(params.lmConfigPA.nfcid, uid, uid_len);
  103. params.lmConfigPA.SENS_RES[0] = atqa[0];
  104. params.lmConfigPA.SENS_RES[1] = atqa[1];
  105. params.lmConfigPA.SEL_RES = sak;
  106. rfalNfcDiscover(&params);
  107. uint32_t start = DWT->CYCCNT;
  108. while(state != RFAL_NFC_STATE_ACTIVATED) {
  109. rfalNfcWorker();
  110. state = rfalNfcGetState();
  111. if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
  112. rfalNfcDeactivate(true);
  113. return false;
  114. }
  115. osThreadYield();
  116. }
  117. return true;
  118. }
  119. bool furi_hal_nfc_get_first_frame(uint8_t** rx_buff, uint16_t** rx_len) {
  120. ReturnCode ret = rfalNfcDataExchangeStart(NULL, 0, rx_buff, rx_len, 0);
  121. return ret == ERR_NONE;
  122. }
  123. ReturnCode furi_hal_nfc_data_exchange(uint8_t* tx_buff, uint16_t tx_len, uint8_t** rx_buff, uint16_t** rx_len, bool deactivate) {
  124. furi_assert(rx_buff);
  125. furi_assert(rx_len);
  126. ReturnCode ret;
  127. rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
  128. ret = rfalNfcDataExchangeStart(tx_buff, tx_len, rx_buff, rx_len, 0);
  129. if(ret != ERR_NONE) {
  130. return ret;
  131. }
  132. uint32_t start = DWT->CYCCNT;
  133. while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
  134. rfalNfcWorker();
  135. state = rfalNfcGetState();
  136. ret = rfalNfcDataExchangeGetStatus();
  137. if(ret > ERR_SLEEP_REQ) {
  138. return ret;
  139. }
  140. if(ret == ERR_BUSY) {
  141. if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
  142. return ERR_TIMEOUT;
  143. }
  144. continue;
  145. } else {
  146. start = DWT->CYCCNT;
  147. }
  148. taskYIELD();
  149. }
  150. if(deactivate) {
  151. rfalNfcDeactivate(false);
  152. rfalLowPowerModeStart();
  153. }
  154. return ERR_NONE;
  155. }
  156. void furi_hal_nfc_deactivate() {
  157. rfalNfcDeactivate(false);
  158. rfalLowPowerModeStart();
  159. }