nfc_magic_worker.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "nfc_magic_worker_i.h"
  2. #include "lib/magic/magic.h"
  3. #define TAG "NfcMagicWorker"
  4. static void
  5. nfc_magic_worker_change_state(NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state) {
  6. furi_assert(nfc_magic_worker);
  7. nfc_magic_worker->state = state;
  8. }
  9. NfcMagicWorker* nfc_magic_worker_alloc() {
  10. NfcMagicWorker* nfc_magic_worker = malloc(sizeof(NfcMagicWorker));
  11. // Worker thread attributes
  12. nfc_magic_worker->thread =
  13. furi_thread_alloc_ex("NfcMagicWorker", 8192, nfc_magic_worker_task, nfc_magic_worker);
  14. nfc_magic_worker->callback = NULL;
  15. nfc_magic_worker->context = NULL;
  16. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
  17. return nfc_magic_worker;
  18. }
  19. void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) {
  20. furi_assert(nfc_magic_worker);
  21. furi_thread_free(nfc_magic_worker->thread);
  22. free(nfc_magic_worker);
  23. }
  24. void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
  25. furi_assert(nfc_magic_worker);
  26. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop);
  27. furi_thread_join(nfc_magic_worker->thread);
  28. }
  29. void nfc_magic_worker_start(
  30. NfcMagicWorker* nfc_magic_worker,
  31. NfcMagicWorkerState state,
  32. NfcDeviceData* dev_data,
  33. NfcMagicWorkerCallback callback,
  34. void* context) {
  35. furi_assert(nfc_magic_worker);
  36. furi_assert(dev_data);
  37. nfc_magic_worker->callback = callback;
  38. nfc_magic_worker->context = context;
  39. nfc_magic_worker->dev_data = dev_data;
  40. nfc_magic_worker_change_state(nfc_magic_worker, state);
  41. furi_thread_start(nfc_magic_worker->thread);
  42. }
  43. int32_t nfc_magic_worker_task(void* context) {
  44. NfcMagicWorker* nfc_magic_worker = context;
  45. if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
  46. nfc_magic_worker_check(nfc_magic_worker);
  47. } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
  48. nfc_magic_worker_write(nfc_magic_worker);
  49. } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
  50. nfc_magic_worker_wipe(nfc_magic_worker);
  51. }
  52. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
  53. return 0;
  54. }
  55. void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
  56. bool card_found_notified = false;
  57. FuriHalNfcDevData nfc_data = {};
  58. MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data;
  59. while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
  60. if(furi_hal_nfc_detect(&nfc_data, 200)) {
  61. if(!card_found_notified) {
  62. nfc_magic_worker->callback(
  63. NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
  64. card_found_notified = true;
  65. }
  66. furi_hal_nfc_sleep();
  67. if(!magic_wupa()) {
  68. FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
  69. nfc_magic_worker->callback(
  70. NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
  71. break;
  72. }
  73. furi_hal_nfc_sleep();
  74. }
  75. if(magic_wupa()) {
  76. if(!magic_data_access_cmd()) {
  77. FURI_LOG_E(TAG, "No card response to data access command (not a magic card)");
  78. nfc_magic_worker->callback(
  79. NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
  80. break;
  81. }
  82. for(size_t i = 0; i < 64; i++) {
  83. FURI_LOG_D(TAG, "Writing block %d", i);
  84. if(!magic_write_blk(i, &src_data->block[i])) {
  85. FURI_LOG_E(TAG, "Failed to write %d block", i);
  86. nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context);
  87. break;
  88. }
  89. }
  90. nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
  91. break;
  92. } else {
  93. if(card_found_notified) {
  94. nfc_magic_worker->callback(
  95. NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
  96. card_found_notified = false;
  97. }
  98. }
  99. furi_delay_ms(300);
  100. }
  101. magic_deactivate();
  102. }
  103. void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
  104. bool card_found_notified = false;
  105. while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
  106. if(magic_wupa()) {
  107. if(!card_found_notified) {
  108. nfc_magic_worker->callback(
  109. NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
  110. card_found_notified = true;
  111. }
  112. nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
  113. break;
  114. } else {
  115. if(card_found_notified) {
  116. nfc_magic_worker->callback(
  117. NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
  118. card_found_notified = false;
  119. }
  120. }
  121. furi_delay_ms(300);
  122. }
  123. magic_deactivate();
  124. }
  125. void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
  126. MfClassicBlock block;
  127. memset(&block, 0, sizeof(MfClassicBlock));
  128. block.value[0] = 0x01;
  129. block.value[1] = 0x02;
  130. block.value[2] = 0x03;
  131. block.value[3] = 0x04;
  132. block.value[4] = 0x04;
  133. block.value[5] = 0x08;
  134. block.value[6] = 0x04;
  135. while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
  136. magic_deactivate();
  137. furi_delay_ms(300);
  138. if(!magic_wupa()) continue;
  139. if(!magic_wipe()) continue;
  140. if(!magic_data_access_cmd()) continue;
  141. if(!magic_write_blk(0, &block)) continue;
  142. nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
  143. break;
  144. }
  145. magic_deactivate();
  146. }