magic.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "magic.h"
  2. #include <furi_hal_nfc.h>
  3. #define TAG "Magic"
  4. #define MAGIC_CMD_WUPA (0x40)
  5. #define MAGIC_CMD_WIPE (0x41)
  6. #define MAGIC_CMD_ACCESS (0x43)
  7. #define MAGIC_MIFARE_READ_CMD (0x30)
  8. #define MAGIC_MIFARE_WRITE_CMD (0xA0)
  9. #define MAGIC_ACK (0x0A)
  10. #define MAGIC_BUFFER_SIZE (32)
  11. bool magic_wupa() {
  12. bool magic_activated = false;
  13. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  14. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  15. uint16_t rx_len = 0;
  16. FuriHalNfcReturn ret = 0;
  17. do {
  18. // Setup nfc poller
  19. furi_hal_nfc_exit_sleep();
  20. furi_hal_nfc_ll_txrx_on();
  21. furi_hal_nfc_ll_poll();
  22. ret = furi_hal_nfc_ll_set_mode(
  23. FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106);
  24. if(ret != FuriHalNfcReturnOk) break;
  25. furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER);
  26. furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER);
  27. furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc);
  28. furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA);
  29. // Start communication
  30. tx_data[0] = MAGIC_CMD_WUPA;
  31. ret = furi_hal_nfc_ll_txrx_bits(
  32. tx_data,
  33. 7,
  34. rx_data,
  35. sizeof(rx_data),
  36. &rx_len,
  37. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
  38. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
  39. furi_hal_nfc_ll_ms2fc(20));
  40. if(ret != FuriHalNfcReturnIncompleteByte) break;
  41. if(rx_len != 4) break;
  42. if(rx_data[0] != MAGIC_ACK) break;
  43. magic_activated = true;
  44. } while(false);
  45. if(!magic_activated) {
  46. furi_hal_nfc_ll_txrx_off();
  47. furi_hal_nfc_start_sleep();
  48. }
  49. return magic_activated;
  50. }
  51. bool magic_data_access_cmd() {
  52. bool write_cmd_success = false;
  53. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  54. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  55. uint16_t rx_len = 0;
  56. FuriHalNfcReturn ret = 0;
  57. do {
  58. tx_data[0] = MAGIC_CMD_ACCESS;
  59. ret = furi_hal_nfc_ll_txrx_bits(
  60. tx_data,
  61. 8,
  62. rx_data,
  63. sizeof(rx_data),
  64. &rx_len,
  65. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
  66. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
  67. furi_hal_nfc_ll_ms2fc(20));
  68. if(ret != FuriHalNfcReturnIncompleteByte) break;
  69. if(rx_len != 4) break;
  70. if(rx_data[0] != MAGIC_ACK) break;
  71. write_cmd_success = true;
  72. } while(false);
  73. if(!write_cmd_success) {
  74. furi_hal_nfc_ll_txrx_off();
  75. furi_hal_nfc_start_sleep();
  76. }
  77. return write_cmd_success;
  78. }
  79. bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
  80. furi_assert(data);
  81. bool read_success = false;
  82. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  83. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  84. uint16_t rx_len = 0;
  85. FuriHalNfcReturn ret = 0;
  86. do {
  87. tx_data[0] = MAGIC_MIFARE_READ_CMD;
  88. tx_data[1] = block_num;
  89. ret = furi_hal_nfc_ll_txrx_bits(
  90. tx_data,
  91. 2 * 8,
  92. rx_data,
  93. sizeof(rx_data),
  94. &rx_len,
  95. FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON,
  96. furi_hal_nfc_ll_ms2fc(20));
  97. if(ret != FuriHalNfcReturnOk) break;
  98. if(rx_len != 16 * 8) break;
  99. memcpy(data->value, rx_data, sizeof(data->value));
  100. read_success = true;
  101. } while(false);
  102. if(!read_success) {
  103. furi_hal_nfc_ll_txrx_off();
  104. furi_hal_nfc_start_sleep();
  105. }
  106. return read_success;
  107. }
  108. bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
  109. furi_assert(data);
  110. bool write_success = false;
  111. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  112. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  113. uint16_t rx_len = 0;
  114. FuriHalNfcReturn ret = 0;
  115. do {
  116. tx_data[0] = MAGIC_MIFARE_WRITE_CMD;
  117. tx_data[1] = block_num;
  118. ret = furi_hal_nfc_ll_txrx_bits(
  119. tx_data,
  120. 2 * 8,
  121. rx_data,
  122. sizeof(rx_data),
  123. &rx_len,
  124. FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
  125. furi_hal_nfc_ll_ms2fc(20));
  126. if(ret != FuriHalNfcReturnIncompleteByte) break;
  127. if(rx_len != 4) break;
  128. if(rx_data[0] != MAGIC_ACK) break;
  129. memcpy(tx_data, data->value, sizeof(data->value));
  130. ret = furi_hal_nfc_ll_txrx_bits(
  131. tx_data,
  132. 16 * 8,
  133. rx_data,
  134. sizeof(rx_data),
  135. &rx_len,
  136. FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
  137. furi_hal_nfc_ll_ms2fc(20));
  138. if(ret != FuriHalNfcReturnIncompleteByte) break;
  139. if(rx_len != 4) break;
  140. if(rx_data[0] != MAGIC_ACK) break;
  141. write_success = true;
  142. } while(false);
  143. if(!write_success) {
  144. furi_hal_nfc_ll_txrx_off();
  145. furi_hal_nfc_start_sleep();
  146. }
  147. return write_success;
  148. }
  149. bool magic_wipe() {
  150. bool wipe_success = false;
  151. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  152. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  153. uint16_t rx_len = 0;
  154. FuriHalNfcReturn ret = 0;
  155. do {
  156. tx_data[0] = MAGIC_CMD_WIPE;
  157. ret = furi_hal_nfc_ll_txrx_bits(
  158. tx_data,
  159. 8,
  160. rx_data,
  161. sizeof(rx_data),
  162. &rx_len,
  163. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
  164. FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
  165. furi_hal_nfc_ll_ms2fc(2000));
  166. if(ret != FuriHalNfcReturnIncompleteByte) break;
  167. if(rx_len != 4) break;
  168. if(rx_data[0] != MAGIC_ACK) break;
  169. wipe_success = true;
  170. } while(false);
  171. return wipe_success;
  172. }
  173. void magic_deactivate() {
  174. furi_hal_nfc_ll_txrx_off();
  175. furi_hal_nfc_sleep();
  176. }