api-hal-nfc.c 5.0 KB

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