api-hal-nfc.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. rfalNfcDiscoverParam params = {
  86. .compMode = RFAL_COMPLIANCE_MODE_NFC,
  87. .techs2Find = RFAL_NFC_LISTEN_TECH_A,
  88. .totalDuration = 1000,
  89. .devLimit = 1,
  90. .wakeupEnabled = false,
  91. .wakeupConfigDefault = true,
  92. .nfcfBR = RFAL_BR_212,
  93. .ap2pBR = RFAL_BR_424,
  94. .maxBR = RFAL_BR_KEEP,
  95. .GBLen = RFAL_NFCDEP_GB_MAX_LEN,
  96. .notifyCb = NULL,
  97. };
  98. params.lmConfigPA.nfcidLen = uid_len;
  99. memcpy(params.lmConfigPA.nfcid, uid, uid_len);
  100. params.lmConfigPA.SENS_RES[0] = atqa[0];
  101. params.lmConfigPA.SENS_RES[1] = atqa[1];
  102. params.lmConfigPA.SEL_RES = sak;
  103. rfalNfcDiscover(&params);
  104. uint32_t start = DWT->CYCCNT;
  105. while(state != RFAL_NFC_STATE_ACTIVATED) {
  106. rfalNfcWorker();
  107. state = rfalNfcGetState();
  108. FURI_LOG_D("HAL NFC", "Current state %d", state);
  109. if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
  110. rfalNfcDeactivate(true);
  111. return false;
  112. }
  113. osThreadYield();
  114. }
  115. return true;
  116. }
  117. ReturnCode api_hal_nfc_data_exchange(uint8_t* tx_buff, uint16_t tx_len, uint8_t** rx_buff, uint16_t** rx_len, bool deactivate) {
  118. furi_assert(rx_buff);
  119. furi_assert(rx_len);
  120. ReturnCode ret;
  121. rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
  122. ret = rfalNfcDataExchangeStart(tx_buff, tx_len, rx_buff, rx_len, 0);
  123. if(ret != ERR_NONE) {
  124. return ret;
  125. }
  126. uint32_t start = DWT->CYCCNT;
  127. while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
  128. rfalNfcWorker();
  129. state = rfalNfcGetState();
  130. ret = rfalNfcDataExchangeGetStatus();
  131. FURI_LOG_D("HAL NFC", "Nfc st: %d Data st: %d", state, ret);
  132. if(ret > ERR_SLEEP_REQ) {
  133. return ret;
  134. }
  135. if(ret == ERR_BUSY) {
  136. if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
  137. return ERR_TIMEOUT;
  138. }
  139. continue;
  140. } else {
  141. start = DWT->CYCCNT;
  142. }
  143. taskYIELD();
  144. }
  145. if(deactivate) {
  146. rfalNfcDeactivate(false);
  147. rfalLowPowerModeStart();
  148. }
  149. return ERR_NONE;
  150. }
  151. void api_hal_nfc_deactivate() {
  152. rfalNfcDeactivate(false);
  153. rfalLowPowerModeStart();
  154. }