Skip to content

Commit

Permalink
Saved emulate 90% functional
Browse files Browse the repository at this point in the history
Config settings now modify emulation
- RFID / GPIO option working
- Track selection option working (unconfirmed)
- Interpacket and clock delay modification working

Upcoming TODO
- Reverse track setting + emulation code
- Rework displayed card data (currently just displays Track 2)
- Redo "Add Manually" process for new file format (currently just sets & saves Track 2)
  • Loading branch information
zacharyweiss committed Jan 22, 2023
1 parent d0faf35 commit ecf253a
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 46 deletions.
155 changes: 129 additions & 26 deletions helpers/mag_helpers.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "mag_helpers.h"
#include "../mag_i.h"

#define GPIO_PIN_A &gpio_ext_pa6
#define GPIO_PIN_B &gpio_ext_pa7
Expand All @@ -7,48 +8,61 @@
#define ZERO_PREFIX 25 // n zeros prefix
#define ZERO_BETWEEN 53 // n zeros between tracks
#define ZERO_SUFFIX 25 // n zeros suffix
#define US_CLOCK 240
#define US_INTERPACKET 10
//#define US_CLOCK 240
//#define US_INTERPACKET 10

// bits per char on a given track
const uint8_t bitlen[] = {7, 5, 5};
// char offset by track
const int sublen[] = {32, 48, 48};
uint8_t bit_dir = 0;

void play_bit_rfid(uint8_t send_bit) {
void play_bit_rfid(uint8_t send_bit, MagSetting* setting) {
// internal TX over RFID coil
bit_dir ^= 1;
furi_hal_gpio_write(RFID_PIN, bit_dir);
furi_delay_us(US_CLOCK);
furi_delay_us(setting->us_clock);

if(send_bit) {
bit_dir ^= 1;
furi_hal_gpio_write(RFID_PIN, bit_dir);
}
furi_delay_us(US_CLOCK);
furi_delay_us(setting->us_clock);

furi_delay_us(US_INTERPACKET);
furi_delay_us(setting->us_interpacket);
}

/*static void play_bit_gpio(uint8_t send_bit) {
void play_bit_gpio(uint8_t send_bit, MagSetting* setting) {
// external TX over motor driver wired to PIN_A and PIN_B
bit_dir ^= 1;
furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
furi_delay_us(US_CLOCK);
furi_delay_us(setting->us_clock);

if(send_bit) {
bit_dir ^= 1;
furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
}
furi_delay_us(US_CLOCK);
furi_delay_us(setting->us_clock);

furi_delay_us(US_INTERPACKET);
}*/
furi_delay_us(setting->us_interpacket);
}

bool play_bit(uint8_t send_bit, MagSetting* setting) {
// Initialize configured TX method
if(setting->tx == MagTxStateRFID) {
play_bit_rfid(send_bit, setting);
} else if(setting->tx == MagTxStateGPIOA6A7) {
play_bit_gpio(send_bit, setting);
} else {
return false;
}

void rfid_tx_init() {
return true;
}

void tx_init_rfid() {
// initialize RFID system for TX
furi_hal_power_enable_otg();

Expand All @@ -73,29 +87,54 @@ void rfid_tx_init() {
furi_delay_ms(300);
}

void rfid_tx_reset() {
void tx_reset_rfid() {
// reset RFID system
furi_hal_gpio_write(RFID_PIN, 0);

furi_hal_rfid_pins_reset();
furi_hal_power_disable_otg();
}

/*
static void gpio_tx_init() {
void tx_init_gpio() {
furi_hal_power_enable_otg();
gpio_item_configure_all_pins(GpioModeOutputPushPull);
// gpio_item_configure_all_pins(GpioModeOutputPushPull);
furi_hal_gpio_init(GPIO_PIN_A, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(GPIO_PIN_B, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
}

static void gpio_tx_reset() {
gpio_item_set_pin(PIN_A, 0);
gpio_item_set_pin(PIN_B, 0);
gpio_item_set_pin(ENABLE_PIN, 0);
void tx_reset_gpio() {
furi_hal_gpio_write(GPIO_PIN_A, 0);
furi_hal_gpio_write(GPIO_PIN_B, 0);

gpio_item_configure_all_pins(GpioModeAnalog);
//gpio_item_configure_all_pins(GpioModeAnalog);
furi_hal_power_disable_otg();
}
*/

bool tx_init(MagSetting* setting) {
// Initialize configured TX method
if(setting->tx == MagTxStateRFID) {
tx_init_rfid();
} else if(setting->tx == MagTxStateGPIOA6A7) {
tx_init_gpio();
} else {
return false;
}

return true;
}

bool tx_reset(MagSetting* setting) {
// Reset configured TX method
if(setting->tx == MagTxStateRFID) {
tx_reset_rfid();
} else if(setting->tx == MagTxStateGPIOA6A7) {
tx_reset_gpio();
} else {
return false;
}

return true;
}

void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_index) {
// convert individual track to bits
Expand Down Expand Up @@ -139,10 +178,11 @@ void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_ind
//furi_assert(is_correct_length);
}

/*
void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index) {
// Quick testing...
rfid_tx_init();
tx_init_rfid();
size_t from;
size_t to;
Expand Down Expand Up @@ -173,13 +213,13 @@ void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index) {
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
FURI_CRITICAL_EXIT();
rfid_tx_reset();
tx_reset_rfid();
}
void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2) {
// Quick testing...
rfid_tx_init();
tx_init_rfid();
const char* data1 = furi_string_get_cstr(track1);
uint8_t bit_array1[(strlen(data1) * bitlen[0]) + 1];
Expand All @@ -197,7 +237,70 @@ void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2) {
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
FURI_CRITICAL_EXIT();
rfid_tx_reset();
tx_reset_rfid();
}*/

void mag_spoof(Mag* mag) {
MagSetting* setting = mag->setting;

// precompute tracks (WIP; ignores reverse and 3rd track)
// likely will be reworked to Samy's bitmap method anyway...
const char* data1 = furi_string_get_cstr(mag->mag_dev->dev_data.track[0].str);
const char* data2 = furi_string_get_cstr(mag->mag_dev->dev_data.track[0].str);
uint8_t bit_array1[(strlen(data1) * bitlen[0]) + 1];
uint8_t bit_array2[(strlen(data2) * bitlen[1]) + 1];
track_to_bits(bit_array1, data1, 0);
track_to_bits(bit_array2, data2, 1);

bool spoofed = false;
do {
// Initialize configured TX method
if(!tx_init(setting)) break;

// Critical timing section (need to eliminate ifs? does this impact timing?)
FURI_CRITICAL_ENTER();
// Prefix of zeros
for(uint8_t i = 0; i < ZERO_PREFIX; i++) {
if(!play_bit(0, setting)) break;
}

// Track 1
if((setting->track == MagTrackStateAll) || (setting->track == MagTrackStateOne)) {
for(uint8_t i = 0; bit_array1[i] != 2; i++) {
if(!play_bit((bit_array1[i] & 1), setting)) break;
}
}

// Zeros between tracks
if(setting->track == MagTrackStateAll) {
for(uint8_t i = 0; i < ZERO_BETWEEN; i++) {
if(!play_bit(0, setting)) break;
}
}

// Track 2 (TODO: Reverse track)
if((setting->track == MagTrackStateAll) || (setting->track == MagTrackStateTwo)) {
for(uint8_t i = 0; bit_array2[i] != 2; i++) {
if(!play_bit((bit_array2[i] & 1), setting)) break;
}
}

// Suffix of zeros
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) {
if(!play_bit(0, setting)) break;
}
FURI_CRITICAL_EXIT();

// Reset configured TX method
if(!tx_reset(setting)) break;
spoofed = true;
} while(0);

UNUSED(spoofed);
/*if(!spoofed) {
// error handling?
// cleanup?
}*/
}

//// @antirez's code from protoview for bitmapping. May want to refactor to use this...
Expand Down
18 changes: 12 additions & 6 deletions helpers/mag_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
#include <stdio.h>
#include <string.h>

void play_bit_rfid(uint8_t send_bit);
// void play_bit_gpio(uint8_t send_bit);
void rfid_tx_init();
void rfid_tx_reset();
void play_bit_rfid(uint8_t send_bit, MagSetting* setting);
void play_bit_gpio(uint8_t send_bit, MagSetting* setting);
bool play_bit(uint8_t send_bit, MagSetting* setting);
void tx_init_rfid();
void tx_init_gpio();
void tx_reset_rfid();
void tx_reset_gpio();
bool tx_init(MagSetting* setting);
bool tx_reset(MagSetting* setting);
void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_index);
void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index);
void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2);
//void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index);
//void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2);
void mag_spoof(Mag* mag);
void set_bit(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val);
bool get_bit(uint8_t* b, uint32_t blen, uint32_t bitpos);
2 changes: 1 addition & 1 deletion mag_i.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "mag_device.h"
#include "helpers/mag_helpers.h"
//#include "helpers/mag_helpers.h"
#include "helpers/mag_text_input.h"
#include "helpers/mag_types.h"

Expand Down
12 changes: 7 additions & 5 deletions scenes/mag_scene_emulate.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "../mag_i.h"
#include "../helpers/mag_helpers.h"

void mag_scene_emulate_on_enter(void* context) {
Mag* mag = context;
Expand Down Expand Up @@ -39,17 +40,18 @@ bool mag_scene_emulate_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == GuiButtonTypeRight) {
consumed = true;

FuriString* tmp_str;
tmp_str = furi_string_alloc_set_str(
furi_string_get_cstr(mag->mag_dev->dev_data.track[1].str));
//FuriString* tmp_str;
//tmp_str = furi_string_alloc_set_str(
// furi_string_get_cstr(mag->mag_dev->dev_data.track[1].str));

// Assumes track 2 for temporary testing.
// Will overhaul alongside file format and config system
notification_message(mag->notifications, &sequence_blink_start_cyan);
mag_spoof_single_track_rfid(tmp_str, 1);
mag_spoof(mag);
//mag_spoof_single_track_rfid(tmp_str, 1);
notification_message(mag->notifications, &sequence_blink_stop);

furi_string_free(tmp_str);
//furi_string_free(tmp_str);
}
}

Expand Down
2 changes: 1 addition & 1 deletion scenes/mag_scene_emulate_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ void mag_scene_emulate_config_on_enter(void* context) {
// Reverse
item = variable_item_list_add(
mag->variable_item_list,
"Reverse:",
"Reverse (WIP):",
REVERSE_COUNT,
mag_scene_emulate_config_set_reverse,
mag);
Expand Down
4 changes: 2 additions & 2 deletions scenes/mag_scene_emulate_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static void play_bit(uint8_t send_bit) {
furi_delay_us(CLOCK_US);
}

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

size_t from;
Expand Down Expand Up @@ -186,7 +186,7 @@ bool mag_scene_emulate_test_on_event(void* context, SceneManagerEvent event) {

// blink led while spoofing
notification_message(mag->notifications, &sequence_blink_start_cyan);
mag_spoof(v, TEST_TRACK);
mag_spoof_test(v, TEST_TRACK);
// mag_spoof_single_track_rfid(v, TEST_TRACK);
notification_message(mag->notifications, &sequence_blink_stop);

Expand Down
11 changes: 6 additions & 5 deletions scenes/mag_scene_start.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "../mag_i.h"

typedef enum {
SubmenuIndexEmulateTest,
//SubmenuIndexEmulateTest,
SubmenuIndexSaved,
SubmenuIndexAddManually,
} SubmenuIndex;
Expand All @@ -16,12 +16,12 @@ void mag_scene_start_on_enter(void* context) {
Mag* mag = context;
Submenu* submenu = mag->submenu;

submenu_add_item(
/*submenu_add_item(
submenu,
"Emulate (Hardcoded)",
SubmenuIndexEmulateTest,
mag_scene_start_submenu_callback,
mag);
mag);*/
submenu_add_item(submenu, "Saved", SubmenuIndexSaved, mag_scene_start_submenu_callback, mag);
submenu_add_item(
submenu, "Add Manually", SubmenuIndexAddManually, mag_scene_start_submenu_callback, mag);
Expand All @@ -40,10 +40,11 @@ bool mag_scene_start_on_event(void* context, SceneManagerEvent event) {
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexEmulateTest) {
/*if(event.event == SubmenuIndexEmulateTest) {
scene_manager_next_scene(mag->scene_manager, MagSceneEmulateTest);
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
} else */
if(event.event == SubmenuIndexSaved) {
furi_string_set(mag->file_path, MAG_APP_FOLDER);
scene_manager_next_scene(mag->scene_manager, MagSceneFileSelect);
consumed = true;
Expand Down

0 comments on commit ecf253a

Please sign in to comment.