mag_scene_emulate_test.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "../mag_i.h"
  2. #define PIN_A 0
  3. #define PIN_B 1 // currently unused
  4. #define CLOCK_US 500 // typically set between 200-500us
  5. #define TEST_STR "%%B123456781234567^LASTNAME/FIRST^YYMMSSSDDDDDDDDDDDDDDDDDDDDDDDDD?\0"
  6. #define TEST_TRACK 0
  7. // TODO: better way of setting temp test str,
  8. // text wrapping on screen? (Will be relevant for any loaded data too)
  9. uint8_t magspoof_bit_dir = 0;
  10. const char* test_str = TEST_STR;
  11. void gpio_item_set_rfid_pin(uint8_t index, bool level) {
  12. if(index == 0) {
  13. furi_hal_gpio_write(&gpio_rfid_carrier_out, level);
  14. // A7 GPIO pin for debugging purposes
  15. // furi_hal_gpio_write(&gpio_ext_pa7, level);
  16. }
  17. }
  18. static void play_bit(uint8_t send_bit) {
  19. magspoof_bit_dir ^= 1;
  20. gpio_item_set_rfid_pin(PIN_A, magspoof_bit_dir);
  21. // PIN_B goes unused in current LF modulation.
  22. // Leaving legacy here in event we attempt downstream modulation,
  23. // rather than just modulating RFID_OUT upstream for signal forming
  24. gpio_item_set_rfid_pin(PIN_B, !magspoof_bit_dir);
  25. furi_delay_us(CLOCK_US);
  26. // NFC TEST
  27. //(magspoof_bit_dir) ? furi_hal_nfc_ll_txrx_on() : furi_hal_nfc_ll_txrx_off();
  28. if(send_bit) {
  29. magspoof_bit_dir ^= 1;
  30. gpio_item_set_rfid_pin(PIN_A, magspoof_bit_dir);
  31. gpio_item_set_rfid_pin(PIN_B, !magspoof_bit_dir);
  32. //(magspoof_bit_dir) ? furi_hal_nfc_ll_txrx_on() : furi_hal_nfc_ll_txrx_off();
  33. }
  34. furi_delay_us(CLOCK_US);
  35. }
  36. static void mag_spoof(FuriString* track_str, uint8_t track) {
  37. furi_hal_power_enable_otg();
  38. size_t from;
  39. size_t to;
  40. // TODO ';' in first track case
  41. if(track == 0) {
  42. from = furi_string_search_char(track_str, '%');
  43. to = furi_string_search_char(track_str, '?', from);
  44. } else if(track == 1) {
  45. from = furi_string_search_char(track_str, ';');
  46. to = furi_string_search_char(track_str, '?', from);
  47. } else {
  48. from = 0;
  49. to = furi_string_size(track_str);
  50. }
  51. if(from >= to) {
  52. return;
  53. }
  54. furi_string_mid(track_str, from, to - from + 1);
  55. const char* data = furi_string_get_cstr(track_str);
  56. printf("%s", data);
  57. furi_hal_ibutton_start_drive();
  58. furi_hal_ibutton_pin_low();
  59. // NFC TEST
  60. //furi_hal_nfc_exit_sleep();
  61. // Initializing at GpioSpeedLow seems sufficient for our needs; no improvements seen by increasing speed setting
  62. // this doesn't seem to make a difference, leaving it in
  63. furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  64. furi_hal_gpio_write(&gpio_rfid_data_in, false);
  65. // false->ground RFID antenna; true->don't ground
  66. // skotopes (RFID dev) say normally you'd want RFID_PULL in high for signal forming, while modulating RFID_OUT
  67. // dunaevai135 had it low in their old code. Leaving low, as it doesn't seem to make a difference on my janky antenna
  68. furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  69. furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
  70. furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  71. // A7 GPIO pin for debugging purposes
  72. // furi_hal_gpio_init(&gpio_ext_pa7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  73. // TODO: initialize pins on scene enter, perhaps, so as to avoid this delay each time the button is pressed?
  74. // Also, why is such a long delay needed?
  75. furi_delay_ms(300);
  76. // prevents interrupts &c. from impacting critical timings
  77. FURI_CRITICAL_ENTER();
  78. const uint8_t bitlen[] = {7, 5, 5};
  79. const int sublen[] = {32, 48, 48};
  80. int tmp, crc, lrc = 0;
  81. magspoof_bit_dir = 0;
  82. // First put out a bunch of leading zeros.
  83. for(uint8_t i = 0; i < 25; i++) {
  84. play_bit(0);
  85. }
  86. for(uint8_t i = 0; data[i] != '\0'; i++) {
  87. crc = 1;
  88. tmp = data[i] - sublen[track];
  89. for(uint8_t j = 0; j < bitlen[track] - 1; j++) {
  90. crc ^= tmp & 1;
  91. lrc ^= (tmp & 1) << j;
  92. play_bit(tmp & 1);
  93. tmp >>= 1;
  94. }
  95. play_bit(crc);
  96. }
  97. // finish calculating and send last "byte" (LRC)
  98. tmp = lrc;
  99. crc = 1;
  100. for(uint8_t j = 0; j < bitlen[track] - 1; j++) {
  101. crc ^= tmp & 1;
  102. play_bit(tmp & 1);
  103. tmp >>= 1;
  104. }
  105. play_bit(crc);
  106. // finish with 0's
  107. for(uint8_t i = 0; i < 5 * 5; i++) {
  108. play_bit(0);
  109. }
  110. gpio_item_set_rfid_pin(PIN_A, 0);
  111. gpio_item_set_rfid_pin(PIN_B, 0);
  112. // NFC TEST
  113. //furi_hal_nfc_ll_txrx_off();
  114. // end critical timing section
  115. FURI_CRITICAL_EXIT();
  116. // NFC TEST
  117. //furi_hal_nfc_start_sleep();
  118. furi_hal_rfid_pins_reset();
  119. furi_hal_power_disable_otg();
  120. }
  121. void mag_scene_emulate_test_on_enter(void* context) {
  122. Mag* mag = context;
  123. Widget* widget = mag->widget;
  124. //FuriString *tmp_string;
  125. //tmp_string = furi_string_alloc();
  126. widget_add_button_element(widget, GuiButtonTypeLeft, "Back", mag_widget_callback, mag);
  127. widget_add_button_element(widget, GuiButtonTypeRight, "Emulate", mag_widget_callback, mag);
  128. //widget_add_button_element(widget, GuiButtonTypeRight, "Re", mag_widget_callback, mag);
  129. //widget_add_button_element(widget, GuiButtonTypeCenter, "Two", mag_widget_callback, mag);
  130. //furi_string_printf(tmp_string, test_str);
  131. //widget_add_string_element(
  132. // widget, 64, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp_string));
  133. //furi_string_reset(tmp_string);
  134. view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);
  135. //furi_string_free(tmp_string);
  136. }
  137. bool mag_scene_emulate_test_on_event(void* context, SceneManagerEvent event) {
  138. Mag* mag = context;
  139. SceneManager* scene_manager = mag->scene_manager;
  140. bool consumed = false;
  141. if(event.type == SceneManagerEventTypeCustom) {
  142. if(event.event == GuiButtonTypeRight) {
  143. consumed = true;
  144. // Hardcoding a test string for the time being, while we debug/improve LF RFID TX
  145. FuriString* v = furi_string_alloc();
  146. furi_string_set_str(v, test_str);
  147. // blink led while spoofing
  148. notification_message(mag->notifications, &sequence_blink_start_cyan);
  149. mag_spoof(v, TEST_TRACK);
  150. // mag_spoof_single_track_rfid(v, TEST_TRACK);
  151. notification_message(mag->notifications, &sequence_blink_stop);
  152. furi_string_free(v);
  153. } else if(event.event == GuiButtonTypeLeft) {
  154. consumed = true;
  155. scene_manager_previous_scene(scene_manager);
  156. }
  157. }
  158. return consumed;
  159. }
  160. void mag_scene_emulate_test_on_exit(void* context) {
  161. Mag* mag = context;
  162. notification_message(mag->notifications, &sequence_blink_stop);
  163. widget_reset(mag->widget);
  164. }