Skip to content

Commit

Permalink
Added historical spoofing implementation to the hardcoded emulation t…
Browse files Browse the repository at this point in the history
…est ground
  • Loading branch information
zacharyweiss committed Dec 27, 2022
1 parent f23ac31 commit ef1cb1b
Showing 1 changed file with 167 additions and 4 deletions.
171 changes: 167 additions & 4 deletions scenes/mag_scene_emulate_test.c
Original file line number Diff line number Diff line change
@@ -1,20 +1,183 @@
#include "../mag_i.h"

#define PIN_A 0
#define PIN_B 1 // currently unused
#define CLOCK_US 250 // typically set between 200-500us

uint8_t magspoof_bit_dir = 0;

void mag_scene_emulate_test_dialog_callback(DialogExResult result, void* context) {
Mag* mag = context;

view_dispatcher_send_custom_event(mag->view_dispatcher, result);
}

void gpio_item_set_rfid_pin(uint8_t index, bool level) {
if(index == 0) {
furi_hal_gpio_write(&gpio_rfid_carrier_out, level);
// A7 GPIO pin for debugging purposes
//furi_hal_gpio_write(&gpio_ext_pa7, level);
}
}

static void play_bit(uint8_t send_bit) {
magspoof_bit_dir ^= 1;
gpio_item_set_rfid_pin(PIN_A, magspoof_bit_dir);
// PIN_B goes unused in current LF modulation.
// Leaving legacy here in event we attempt downstream modulation,
// rather than just modulating RFID_OUT upstream for signal forming
gpio_item_set_rfid_pin(PIN_B, !magspoof_bit_dir);
furi_delay_us(CLOCK_US);

if(send_bit) {
magspoof_bit_dir ^= 1;
gpio_item_set_rfid_pin(PIN_A, magspoof_bit_dir);
gpio_item_set_rfid_pin(PIN_B, !magspoof_bit_dir);
}
furi_delay_us(CLOCK_US);
}

static void mag_spoof(FuriString* track_str, uint8_t track) {
furi_hal_power_enable_otg();

size_t from;
size_t to;

// TODO ';' in first track case
if(track == 0) {
from = furi_string_search_char(track_str, '%');
to = furi_string_search_char(track_str, '?', from);
} else if(track == 1) {
from = furi_string_search_char(track_str, ';');
to = furi_string_search_char(track_str, '?', from);
} else {
from = 0;
to = furi_string_size(track_str);
}
if(from >= to) {
return;
}
furi_string_mid(track_str, from, to - from + 1);

const char* data = furi_string_get_cstr(track_str);

printf("%s", data);

furi_hal_ibutton_start_drive();
furi_hal_ibutton_pin_low();

// this doesn't seem to make a difference, leaving it in
furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_rfid_data_in, false);

// false->ground RFID antenna; true->don't ground
// skotopes (RFID dev) say normally you'd want RFID_PULL in high for signal forming, while modulating RFID_OUT
// dunaevai135 had it low in their old code. Leaving low, as it doesn't seem to make a difference on my janky antenna
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);

furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);

// A7 GPIO pin for debugging purposes
//furi_hal_gpio_init(&gpio_ext_pa7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);

furi_delay_ms(300);

FURI_CRITICAL_ENTER();

const uint8_t bitlen[] = {7, 5, 5};
const int sublen[] = {32, 48, 48};
int tmp, crc, lrc = 0;
magspoof_bit_dir = 0;

// First put out a bunch of leading zeros.
for(uint8_t i = 0; i < 25; i++) {
play_bit(0);
}

for(uint8_t i = 0; data[i] != '\0'; i++) {
crc = 1;
tmp = data[i] - sublen[track];

for(uint8_t j = 0; j < bitlen[track] - 1; j++) {
crc ^= tmp & 1;
lrc ^= (tmp & 1) << j;
play_bit(tmp & 1);
tmp >>= 1;
}
play_bit(crc);
}

// finish calculating and send last "byte" (LRC)
tmp = lrc;
crc = 1;
for(uint8_t j = 0; j < bitlen[track] - 1; j++) {
crc ^= tmp & 1;
play_bit(tmp & 1);
tmp >>= 1;
}
play_bit(crc);

// finish with 0's
for(uint8_t i = 0; i < 5 * 5; i++) {
play_bit(0);
}

gpio_item_set_rfid_pin(PIN_A, 0);
gpio_item_set_rfid_pin(PIN_B, 0);

FURI_CRITICAL_EXIT();

furi_hal_rfid_pins_reset();
furi_hal_power_disable_otg();
}

void mag_scene_emulate_test_on_enter(void* context) {
Mag* mag = context;
UNUSED(mag);
Widget* widget = mag->widget;

FuriString* tmp_string;
tmp_string = furi_string_alloc();

widget_add_button_element(widget, GuiButtonTypeLeft, "Back", mag_widget_callback, mag);
widget_add_button_element(widget, GuiButtonTypeCenter, "Emulate", mag_widget_callback, mag);

furi_string_printf(tmp_string, "Emulate?");
widget_add_string_element(
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp_string));
furi_string_reset(tmp_string);

view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);
furi_string_free(tmp_string);
}

bool mag_scene_emulate_test_on_event(void* context, SceneManagerEvent event) {
Mag* mag = context;
UNUSED(mag);
UNUSED(event);
SceneManager* scene_manager = mag->scene_manager;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DialogExResultCenter) {
consumed = true;

// Hardcoding a test string for the time being, while we debug/improve LF RFID TX
FuriString* v = furi_string_alloc();
furi_string_set_str(
v,
"%B123456781234567^LASTNAME/FIRST^YYMMSSSDDDDDDDDDDDDDDDDDDDDDDDDD?;1234567812?");
mag_spoof(v, 0);
furi_string_free(v);
} else if(event.event == GuiButtonTypeLeft) {
consumed = true;

scene_manager_previous_scene(scene_manager);
}
}

return consumed;
}

void mag_scene_emulate_test_on_exit(void* context) {
Mag* mag = context;
UNUSED(mag);
widget_reset(mag->widget);
}

0 comments on commit ef1cb1b

Please sign in to comment.