gen1a_poller.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "gen1a_poller_i.h"
  2. #include <nfc/protocols/iso14443_3a/iso14443_3a.h>
  3. #include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
  4. #include <nfc/helpers/nfc_data_generator.h>
  5. #include <furi/furi.h>
  6. #define GEN1A_POLLER_THREAD_FLAG_DETECTED (1U << 0)
  7. typedef NfcCommand (*Gen1aPollerStateHandler)(Gen1aPoller* instance);
  8. typedef struct {
  9. Nfc* nfc;
  10. BitBuffer* tx_buffer;
  11. BitBuffer* rx_buffer;
  12. FuriThreadId thread_id;
  13. bool detected;
  14. } Gen1aPollerDetectContext;
  15. Gen1aPoller* gen1a_poller_alloc(Nfc* nfc) {
  16. furi_assert(nfc);
  17. Gen1aPoller* instance = malloc(sizeof(Gen1aPoller));
  18. instance->nfc = nfc;
  19. nfc_config(instance->nfc, NfcModePoller, NfcTechIso14443a);
  20. nfc_set_guard_time_us(instance->nfc, ISO14443_3A_GUARD_TIME_US);
  21. nfc_set_fdt_poll_fc(instance->nfc, ISO14443_3A_FDT_POLL_FC);
  22. nfc_set_fdt_poll_poll_us(instance->nfc, ISO14443_3A_POLL_POLL_MIN_US);
  23. instance->tx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
  24. instance->rx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
  25. instance->mfc_device = nfc_device_alloc();
  26. instance->gen1a_event.data = &instance->gen1a_event_data;
  27. return instance;
  28. }
  29. void gen1a_poller_free(Gen1aPoller* instance) {
  30. furi_assert(instance);
  31. bit_buffer_free(instance->tx_buffer);
  32. bit_buffer_free(instance->rx_buffer);
  33. nfc_device_free(instance->mfc_device);
  34. free(instance);
  35. }
  36. NfcCommand gen1a_poller_detect_callback(NfcEvent event, void* context) {
  37. furi_assert(context);
  38. NfcCommand command = NfcCommandStop;
  39. Gen1aPollerDetectContext* gen1a_poller_detect_ctx = context;
  40. if(event.type == NfcEventTypePollerReady) {
  41. do {
  42. bit_buffer_set_size(gen1a_poller_detect_ctx->tx_buffer, 7);
  43. bit_buffer_set_byte(gen1a_poller_detect_ctx->tx_buffer, 0, 0x40);
  44. NfcError error = nfc_poller_trx(
  45. gen1a_poller_detect_ctx->nfc,
  46. gen1a_poller_detect_ctx->tx_buffer,
  47. gen1a_poller_detect_ctx->rx_buffer,
  48. GEN1A_POLLER_MAX_FWT);
  49. if(error != NfcErrorNone) break;
  50. if(bit_buffer_get_size(gen1a_poller_detect_ctx->rx_buffer) != 4) break;
  51. if(bit_buffer_get_byte(gen1a_poller_detect_ctx->rx_buffer, 0) != 0x0A) break;
  52. gen1a_poller_detect_ctx->detected = true;
  53. } while(false);
  54. }
  55. furi_thread_flags_set(gen1a_poller_detect_ctx->thread_id, GEN1A_POLLER_THREAD_FLAG_DETECTED);
  56. return command;
  57. }
  58. bool gen1a_poller_detect(Nfc* nfc) {
  59. furi_assert(nfc);
  60. nfc_config(nfc, NfcModePoller, NfcTechIso14443a);
  61. nfc_set_guard_time_us(nfc, ISO14443_3A_GUARD_TIME_US);
  62. nfc_set_fdt_poll_fc(nfc, ISO14443_3A_FDT_POLL_FC);
  63. nfc_set_fdt_poll_poll_us(nfc, ISO14443_3A_POLL_POLL_MIN_US);
  64. Gen1aPollerDetectContext gen1a_poller_detect_ctx = {};
  65. gen1a_poller_detect_ctx.nfc = nfc;
  66. gen1a_poller_detect_ctx.tx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
  67. gen1a_poller_detect_ctx.rx_buffer = bit_buffer_alloc(GEN1A_POLLER_MAX_BUFFER_SIZE);
  68. gen1a_poller_detect_ctx.thread_id = furi_thread_get_current_id();
  69. gen1a_poller_detect_ctx.detected = false;
  70. nfc_start(nfc, gen1a_poller_detect_callback, &gen1a_poller_detect_ctx);
  71. uint32_t flags = furi_thread_flags_wait(
  72. GEN1A_POLLER_THREAD_FLAG_DETECTED, FuriFlagWaitAny, FuriWaitForever);
  73. if(flags & GEN1A_POLLER_THREAD_FLAG_DETECTED) {
  74. furi_thread_flags_clear(GEN1A_POLLER_THREAD_FLAG_DETECTED);
  75. }
  76. nfc_stop(nfc);
  77. bit_buffer_free(gen1a_poller_detect_ctx.tx_buffer);
  78. bit_buffer_free(gen1a_poller_detect_ctx.rx_buffer);
  79. return gen1a_poller_detect_ctx.detected;
  80. }
  81. static void gen1a_poller_reset(Gen1aPoller* instance) {
  82. instance->current_block = 0;
  83. nfc_data_generator_fill_data(NfcDataGeneratorTypeMfClassic1k_4b, instance->mfc_device);
  84. }
  85. NfcCommand gen1a_poller_idle_handler(Gen1aPoller* instance) {
  86. NfcCommand command = NfcCommandContinue;
  87. gen1a_poller_reset(instance);
  88. Gen1aPollerError error = gen1a_poller_wupa(instance);
  89. if(error == Gen1aPollerErrorNone) {
  90. instance->state = Gen1aPollerStateRequestMode;
  91. instance->gen1a_event.type = Gen1aPollerEventTypeDetected;
  92. command = instance->callback(instance->gen1a_event, instance->context);
  93. }
  94. return command;
  95. }
  96. NfcCommand gen1a_poller_request_mode_handler(Gen1aPoller* instance) {
  97. NfcCommand command = NfcCommandContinue;
  98. instance->gen1a_event.type = Gen1aPollerEventTypeRequestMode;
  99. command = instance->callback(instance->gen1a_event, instance->context);
  100. if(instance->gen1a_event_data.request_mode.mode == Gen1aPollerModeWipe) {
  101. instance->state = Gen1aPollerStateWipe;
  102. } else {
  103. instance->state = Gen1aPollerStateWriteDataRequest;
  104. }
  105. return command;
  106. }
  107. NfcCommand gen1a_poller_wipe_handler(Gen1aPoller* instance) {
  108. NfcCommand command = NfcCommandContinue;
  109. Gen1aPollerError error = Gen1aPollerErrorNone;
  110. const MfClassicData* mfc_data =
  111. nfc_device_get_data(instance->mfc_device, NfcProtocolMfClassic);
  112. uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
  113. if(instance->current_block == total_block_num) {
  114. instance->state = Gen1aPollerStateSuccess;
  115. } else {
  116. do {
  117. if(instance->current_block == 0) {
  118. error = gen1a_poller_data_access(instance);
  119. if(error != Gen1aPollerErrorNone) {
  120. instance->state = Gen1aPollerStateFail;
  121. break;
  122. }
  123. }
  124. error = gen1a_poller_write_block(
  125. instance, instance->current_block, &mfc_data->block[instance->current_block]);
  126. if(error != Gen1aPollerErrorNone) {
  127. instance->state = Gen1aPollerStateFail;
  128. break;
  129. }
  130. instance->current_block++;
  131. } while(false);
  132. }
  133. return command;
  134. }
  135. NfcCommand gen1a_poller_write_data_request_handler(Gen1aPoller* instance) {
  136. NfcCommand command = NfcCommandContinue;
  137. instance->gen1a_event.type = Gen1aPollerEventTypeRequestDataToWrite;
  138. command = instance->callback(instance->gen1a_event, instance->context);
  139. instance->state = Gen1aPollerStateWrite;
  140. return command;
  141. }
  142. NfcCommand gen1a_poller_write_handler(Gen1aPoller* instance) {
  143. NfcCommand command = NfcCommandContinue;
  144. Gen1aPollerError error = Gen1aPollerErrorNone;
  145. const MfClassicData* mfc_data = instance->gen1a_event_data.data_to_write.mfc_data;
  146. uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
  147. if(instance->current_block == total_block_num) {
  148. instance->state = Gen1aPollerStateSuccess;
  149. } else {
  150. do {
  151. if(instance->current_block == 0) {
  152. error = gen1a_poller_data_access(instance);
  153. if(error != Gen1aPollerErrorNone) {
  154. instance->state = Gen1aPollerStateFail;
  155. break;
  156. }
  157. }
  158. error = gen1a_poller_write_block(
  159. instance, instance->current_block, &mfc_data->block[instance->current_block]);
  160. if(error != Gen1aPollerErrorNone) {
  161. instance->state = Gen1aPollerStateFail;
  162. break;
  163. }
  164. instance->current_block++;
  165. } while(false);
  166. }
  167. return command;
  168. }
  169. NfcCommand gen1a_poller_success_handler(Gen1aPoller* instance) {
  170. NfcCommand command = NfcCommandContinue;
  171. instance->gen1a_event.type = Gen1aPollerEventTypeSuccess;
  172. command = instance->callback(instance->gen1a_event, instance->context);
  173. instance->state = Gen1aPollerStateIdle;
  174. return command;
  175. }
  176. NfcCommand gen1a_poller_fail_handler(Gen1aPoller* instance) {
  177. NfcCommand command = NfcCommandContinue;
  178. instance->gen1a_event.type = Gen1aPollerEventTypeFail;
  179. command = instance->callback(instance->gen1a_event, instance->context);
  180. instance->state = Gen1aPollerStateIdle;
  181. return command;
  182. }
  183. static const Gen1aPollerStateHandler gen1a_poller_state_handlers[Gen1aPollerStateNum] = {
  184. [Gen1aPollerStateIdle] = gen1a_poller_idle_handler,
  185. [Gen1aPollerStateRequestMode] = gen1a_poller_request_mode_handler,
  186. [Gen1aPollerStateWipe] = gen1a_poller_wipe_handler,
  187. [Gen1aPollerStateWriteDataRequest] = gen1a_poller_write_data_request_handler,
  188. [Gen1aPollerStateWrite] = gen1a_poller_write_handler,
  189. [Gen1aPollerStateSuccess] = gen1a_poller_success_handler,
  190. [Gen1aPollerStateFail] = gen1a_poller_fail_handler,
  191. };
  192. NfcCommand gen1a_poller_run(NfcEvent event, void* context) {
  193. NfcCommand command = NfcCommandContinue;
  194. Gen1aPoller* instance = context;
  195. if(event.type == NfcEventTypePollerReady) {
  196. command = gen1a_poller_state_handlers[instance->state](instance);
  197. }
  198. if(instance->session_state == Gen1aPollerSessionStateStopRequest) {
  199. command = NfcCommandStop;
  200. }
  201. return command;
  202. }
  203. void gen1a_poller_start(Gen1aPoller* instance, Gen1aPollerCallback callback, void* context) {
  204. furi_assert(instance);
  205. furi_assert(callback);
  206. instance->callback = callback;
  207. instance->context = context;
  208. instance->session_state = Gen1aPollerSessionStateStarted;
  209. nfc_start(instance->nfc, gen1a_poller_run, instance);
  210. }
  211. void gen1a_poller_stop(Gen1aPoller* instance) {
  212. furi_assert(instance);
  213. instance->session_state = Gen1aPollerSessionStateStopRequest;
  214. nfc_stop(instance->nfc);
  215. instance->session_state = Gen1aPollerSessionStateIdle;
  216. }