nfc_magic_worker.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 = furi_thread_alloc();
  13. furi_thread_set_name(nfc_magic_worker->thread, "NfcMagicWorker");
  14. furi_thread_set_stack_size(nfc_magic_worker->thread, 8192);
  15. furi_thread_set_callback(nfc_magic_worker->thread, nfc_magic_worker_task);
  16. furi_thread_set_context(nfc_magic_worker->thread, nfc_magic_worker);
  17. nfc_magic_worker->callback = NULL;
  18. nfc_magic_worker->context = NULL;
  19. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
  20. return nfc_magic_worker;
  21. }
  22. void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) {
  23. furi_assert(nfc_magic_worker);
  24. furi_thread_free(nfc_magic_worker->thread);
  25. free(nfc_magic_worker);
  26. }
  27. void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
  28. furi_assert(nfc_magic_worker);
  29. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop);
  30. furi_thread_join(nfc_magic_worker->thread);
  31. }
  32. void nfc_magic_worker_start(
  33. NfcMagicWorker* nfc_magic_worker,
  34. NfcMagicWorkerState state,
  35. NfcDeviceData* dev_data,
  36. NfcMagicWorkerCallback callback,
  37. void* context) {
  38. furi_assert(nfc_magic_worker);
  39. furi_assert(dev_data);
  40. nfc_magic_worker->callback = callback;
  41. nfc_magic_worker->context = context;
  42. nfc_magic_worker->dev_data = dev_data;
  43. nfc_magic_worker_change_state(nfc_magic_worker, state);
  44. furi_thread_start(nfc_magic_worker->thread);
  45. }
  46. int32_t nfc_magic_worker_task(void* context) {
  47. NfcMagicWorker* nfc_magic_worker = context;
  48. if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
  49. nfc_magic_worker_check(nfc_magic_worker);
  50. } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
  51. nfc_magic_worker_write(nfc_magic_worker);
  52. } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
  53. nfc_magic_worker_wipe(nfc_magic_worker);
  54. }
  55. nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady);
  56. return 0;
  57. }
  58. void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
  59. bool card_found_notified = false;
  60. FuriHalNfcDevData nfc_data = {};
  61. MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data;
  62. while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
  63. if(furi_hal_nfc_detect(&nfc_data, 200)) {
  64. if(!card_found_notified) {
  65. nfc_magic_worker->callback(
  66. NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
  67. card_found_notified = true;
  68. }
  69. furi_hal_nfc_sleep();
  70. if(!magic_wupa()) {
  71. FURI_LOG_E(TAG, "Not Magic card");
  72. nfc_magic_worker->callback(
  73. NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
  74. break;
  75. }
  76. if(!magic_data_access_cmd()) {
  77. FURI_LOG_E(TAG, "Not 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. }