api-hal-nfc.c 4.9 KB

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