nfc_magic_scanner.c 4.7 KB

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