nfc_magic_scanner.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "nfc_magic_scanner.h"
  2. #include "core/check.h"
  3. #include "protocols/gen4/gen4.h"
  4. #include "protocols/gen1a/gen1a_poller.h"
  5. #include "protocols/gen2/gen2_poller.h"
  6. #include "protocols/gen4/gen4_poller.h"
  7. #include <nfc/nfc_poller.h>
  8. #include <furi/furi.h>
  9. typedef enum {
  10. NfcMagicScannerSessionStateIdle,
  11. NfcMagicScannerSessionStateActive,
  12. NfcMagicScannerSessionStateStopRequest,
  13. } NfcMagicScannerSessionState;
  14. struct NfcMagicScanner {
  15. Nfc* nfc;
  16. NfcMagicScannerSessionState session_state;
  17. NfcMagicProtocol current_protocol;
  18. Gen4Password gen4_password;
  19. Gen4* gen4_data;
  20. bool magic_protocol_detected;
  21. NfcMagicScannerCallback callback;
  22. void* context;
  23. FuriThread* scan_worker;
  24. };
  25. static const NfcProtocol nfc_magic_scanner_not_magic_protocols[] = {
  26. NfcProtocolIso14443_3b,
  27. NfcProtocolIso15693_3,
  28. NfcProtocolFelica,
  29. };
  30. static void nfc_magic_scanner_reset(NfcMagicScanner* instance) {
  31. instance->session_state = NfcMagicScannerSessionStateIdle;
  32. instance->current_protocol = NfcMagicProtocolGen1;
  33. }
  34. NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc) {
  35. furi_assert(nfc);
  36. NfcMagicScanner* instance = malloc(sizeof(NfcMagicScanner));
  37. instance->nfc = nfc;
  38. instance->gen4_data = gen4_alloc();
  39. return instance;
  40. }
  41. void nfc_magic_scanner_free(NfcMagicScanner* instance) {
  42. furi_assert(instance);
  43. gen4_free(instance->gen4_data);
  44. free(instance);
  45. }
  46. void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, Gen4Password password) {
  47. furi_assert(instance);
  48. instance->gen4_password = password;
  49. }
  50. static int32_t nfc_magic_scanner_worker(void* context) {
  51. furi_assert(context);
  52. NfcMagicScanner* instance = context;
  53. furi_assert(instance->session_state == NfcMagicScannerSessionStateActive);
  54. while(instance->session_state == NfcMagicScannerSessionStateActive) {
  55. do {
  56. if(instance->current_protocol == NfcMagicProtocolGen1) {
  57. instance->magic_protocol_detected = gen1a_poller_detect(instance->nfc);
  58. if(instance->magic_protocol_detected) {
  59. break;
  60. }
  61. } else if(instance->current_protocol == NfcMagicProtocolGen4) {
  62. gen4_reset(instance->gen4_data);
  63. Gen4 gen4_data;
  64. Gen4PollerError error =
  65. gen4_poller_detect(instance->nfc, instance->gen4_password, &gen4_data);
  66. instance->magic_protocol_detected = (error == Gen4PollerErrorNone);
  67. if(instance->magic_protocol_detected) {
  68. gen4_copy(instance->gen4_data, &gen4_data);
  69. break;
  70. }
  71. } else if(instance->current_protocol == NfcMagicProtocolGen2) {
  72. Gen2PollerError error = gen2_poller_detect(instance->nfc);
  73. instance->magic_protocol_detected = (error == Gen2PollerErrorNone);
  74. if(instance->magic_protocol_detected) {
  75. break;
  76. }
  77. } else if(instance->current_protocol == NfcMagicProtocolClassic) {
  78. NfcPoller* poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
  79. instance->magic_protocol_detected = nfc_poller_detect(poller);
  80. nfc_poller_free(poller);
  81. if(instance->magic_protocol_detected) {
  82. break;
  83. }
  84. }
  85. } while(false);
  86. if(instance->magic_protocol_detected) {
  87. NfcMagicScannerEvent event = {
  88. .type = NfcMagicScannerEventTypeDetected,
  89. .data.protocol = instance->current_protocol,
  90. };
  91. instance->callback(event, instance->context);
  92. break;
  93. }
  94. if(instance->current_protocol == NfcMagicProtocolNum - 1) {
  95. bool not_magic_protocol_detected = false;
  96. for(size_t i = 0; i < COUNT_OF(nfc_magic_scanner_not_magic_protocols); i++) {
  97. NfcProtocol protocol = nfc_magic_scanner_not_magic_protocols[i];
  98. NfcPoller* poller = nfc_poller_alloc(instance->nfc, protocol);
  99. not_magic_protocol_detected = nfc_poller_detect(poller);
  100. nfc_poller_free(poller);
  101. if(not_magic_protocol_detected) {
  102. break;
  103. }
  104. }
  105. if(not_magic_protocol_detected) {
  106. NfcMagicScannerEvent event = {
  107. .type = NfcMagicScannerEventTypeDetectedNotMagic,
  108. };
  109. instance->callback(event, instance->context);
  110. break;
  111. }
  112. }
  113. instance->current_protocol = (instance->current_protocol + 1) % NfcMagicProtocolNum;
  114. }
  115. nfc_magic_scanner_reset(instance);
  116. return 0;
  117. }
  118. void nfc_magic_scanner_start(
  119. NfcMagicScanner* instance,
  120. NfcMagicScannerCallback callback,
  121. void* context) {
  122. furi_assert(instance);
  123. furi_assert(callback);
  124. instance->callback = callback;
  125. instance->context = context;
  126. instance->scan_worker = furi_thread_alloc();
  127. furi_thread_set_name(instance->scan_worker, "NfcMagicScanWorker");
  128. furi_thread_set_context(instance->scan_worker, instance);
  129. furi_thread_set_stack_size(instance->scan_worker, 4 * 1024);
  130. furi_thread_set_callback(instance->scan_worker, nfc_magic_scanner_worker);
  131. furi_thread_start(instance->scan_worker);
  132. instance->session_state = NfcMagicScannerSessionStateActive;
  133. }
  134. void nfc_magic_scanner_stop(NfcMagicScanner* instance) {
  135. furi_assert(instance);
  136. instance->session_state = NfcMagicScannerSessionStateStopRequest;
  137. furi_thread_join(instance->scan_worker);
  138. instance->session_state = NfcMagicScannerSessionStateIdle;
  139. furi_thread_free(instance->scan_worker);
  140. instance->scan_worker = NULL;
  141. instance->callback = NULL;
  142. instance->context = NULL;
  143. }
  144. const Gen4* nfc_magic_scanner_get_gen4_data(NfcMagicScanner* instance) {
  145. furi_assert(instance);
  146. return instance->gen4_data;
  147. }