Skip to content

Commit

Permalink
upd magspoof
Browse files Browse the repository at this point in the history
  • Loading branch information
xMasterX committed May 15, 2024
1 parent 85e9525 commit a15380b
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 104 deletions.
2 changes: 1 addition & 1 deletion non_catalog_apps/magspoof_flipper/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ App(
fap_category="GPIO",
fap_icon_assets="icons",
fap_icon_assets_symbol="mag",
fap_version=(0, 7), # major, minor
fap_version=(0, 9), # major, minor
fap_description="Enables wireless transmission of magstripe data",
fap_author="Zachary Weiss",
fap_weburl="https://github.com/zacharyweiss/magspoof_flipper",
Expand Down
62 changes: 36 additions & 26 deletions non_catalog_apps/magspoof_flipper/helpers/mag_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define ZERO_PREFIX 25 // n zeros prefix
#define ZERO_BETWEEN 53 // n zeros between tracks
#define ZERO_SUFFIX 25 // n zeros suffix
#define REPEAT_DELAY_MS 50

// bits per char on a given track
const uint8_t bitlen[] = {7, 5, 5};
Expand Down Expand Up @@ -331,40 +332,49 @@ void mag_spoof(Mag* mag) {

if(!tx_init(state)) return;

FURI_CRITICAL_ENTER();
for(uint16_t i = 0; i < (ZERO_PREFIX * 2); i++) {
// is this right?
if(!!(i % 2)) bit ^= 1;
play_halfbit(bit, state);
furi_delay_us(state->us_clock);
}
uint8_t i = 0;
do {
FURI_CRITICAL_ENTER();
for(uint16_t i = 0; i < (ZERO_PREFIX * 2); i++) {
// is this right?
if(!!(i % 2)) bit ^= 1;
play_halfbit(bit, state);
furi_delay_us(state->us_clock);
}

if((state->track == MagTrackStateOneAndTwo) || (state->track == MagTrackStateOne))
play_track((uint8_t*)bits_t1_manchester, bits_t1_count, state, false);

if((state->track == MagTrackStateOneAndTwo) || (state->track == MagTrackStateOne))
play_track((uint8_t*)bits_t1_manchester, bits_t1_count, state, false);
if((state->track == MagTrackStateOneAndTwo))
for(uint16_t i = 0; i < (ZERO_BETWEEN * 2); i++) {
if(!!(i % 2)) bit ^= 1;
play_halfbit(bit, state);
furi_delay_us(state->us_clock);
}

if((state->track == MagTrackStateOneAndTwo))
for(uint16_t i = 0; i < (ZERO_BETWEEN * 2); i++) {
if((state->track == MagTrackStateOneAndTwo) || (state->track == MagTrackStateTwo))
play_track(
(uint8_t*)bits_t2_manchester,
bits_t2_count,
state,
(state->reverse == MagReverseStateOn));

if((state->track == MagTrackStateThree))
play_track((uint8_t*)bits_t3_manchester, bits_t3_count, state, false);

for(uint16_t i = 0; i < (ZERO_SUFFIX * 2); i++) {
if(!!(i % 2)) bit ^= 1;
play_halfbit(bit, state);
furi_delay_us(state->us_clock);
}
FURI_CRITICAL_EXIT();

if((state->track == MagTrackStateOneAndTwo) || (state->track == MagTrackStateTwo))
play_track(
(uint8_t*)bits_t2_manchester,
bits_t2_count,
state,
(state->reverse == MagReverseStateOn));

if((state->track == MagTrackStateThree))
play_track((uint8_t*)bits_t3_manchester, bits_t3_count, state, false);
i++;
FURI_LOG_D(
TAG, "TX %u (n_repeats: %u, repeat_mode: %u)", i, state->n_repeats, state->repeat_mode);
furi_delay_ms(REPEAT_DELAY_MS);

for(uint16_t i = 0; i < (ZERO_SUFFIX * 2); i++) {
if(!!(i % 2)) bit ^= 1;
play_halfbit(bit, state);
furi_delay_us(state->us_clock);
}
FURI_CRITICAL_EXIT();
} while((i < state->n_repeats) && state->repeat_mode);

free(data1);
free(data2);
Expand Down
2 changes: 2 additions & 0 deletions non_catalog_apps/magspoof_flipper/helpers/mag_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef enum {
#define MAG_STATE_DEFAULT_PIN_OUTPUT MagPinA6
#define MAG_STATE_DEFAULT_PIN_ENABLE MagPinA4
#define MAG_STATE_DEFAULT_ALLOW_UART false
#define MAG_STATE_DEFAULT_N_REPEATS 3
#define MAG_STATE_DEFAULT_REPEAT_MODE true

typedef enum {
MagViewSubmenu,
Expand Down
1 change: 1 addition & 0 deletions non_catalog_apps/magspoof_flipper/mag_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ enum MagCustomEvent {
MagEventNext = 100,
MagEventExit,
MagEventPopupClosed,
MagEventConfirmDialog,
};

typedef struct {
Expand Down
63 changes: 47 additions & 16 deletions non_catalog_apps/magspoof_flipper/mag_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,32 +50,60 @@ bool mag_state_load(MagState* out_state) {
if(!flipper_format_file_open_existing(file, MAG_STATE_PATH)) break;
if(!flipper_format_read_header(file, str, &tmp)) break;
if(furi_string_cmp_str(str, MAG_STATE_HEADER)) break;
if(tmp != MAG_STATE_VER) break;

if(!flipper_format_read_uint32(file, "pin_input", &tmp, 1)) break;
state.pin_input = tmp;
if(!flipper_format_read_uint32(file, "pin_output", &tmp, 1)) break;
state.pin_output = tmp;
if(!flipper_format_read_uint32(file, "pin_enable", &tmp, 1)) break;
state.pin_enable = tmp;
if(!flipper_format_read_bool(file, "allow_uart", &state.allow_uart, 1)) break;
// if(tmp != MAG_STATE_VER) break;

if(!flipper_format_read_uint32(file, "pin_input", &tmp, 1)) {
flipper_format_rewind(file);
tmp = MAG_STATE_DEFAULT_PIN_INPUT;
}
state.pin_input = (MagPin)tmp;

if(!flipper_format_read_uint32(file, "pin_output", &tmp, 1)) {
flipper_format_rewind(file);
tmp = MAG_STATE_DEFAULT_PIN_OUTPUT;
}
state.pin_output = (MagPin)tmp;

if(!flipper_format_read_uint32(file, "pin_enable", &tmp, 1)) {
flipper_format_rewind(file);
tmp = MAG_STATE_DEFAULT_PIN_ENABLE;
}
state.pin_enable = (MagPin)tmp;

if(!flipper_format_read_bool(file, "allow_uart", &state.allow_uart, 1)) {
flipper_format_rewind(file);
state.allow_uart = MAG_STATE_DEFAULT_ALLOW_UART;
}

if(!flipper_format_read_uint32(file, "n_repeats", &tmp, 1)) {
flipper_format_rewind(file);
tmp = MAG_STATE_DEFAULT_N_REPEATS;
}
state.n_repeats = (uint8_t)tmp;

if(!flipper_format_read_bool(file, "repeat_mode", &state.repeat_mode, 1)) {
flipper_format_rewind(file);
state.repeat_mode = MAG_STATE_DEFAULT_REPEAT_MODE;
}

loaded_from_file = true;
} while(0);
flipper_format_free(file);
}
furi_record_close(RECORD_STORAGE);

// If could not be read from file
// Or file GPIO config is invalid (pins overlap)
// Set defaults
// If file's GPIO config is invalid (pins overlap)
// Reset to defaults
// Additionally raise message to user?
if(!loaded_from_file || !mag_state_gpio_is_valid(&state)) {
if(!mag_state_gpio_is_valid(&state)) {
mag_state_gpio_reset(&state);
}

if(!loaded_from_file) {
mag_state_gpio_reset(&state);
state.allow_uart = MAG_STATE_DEFAULT_ALLOW_UART;
state.n_repeats = MAG_STATE_DEFAULT_N_REPEATS;
state.repeat_mode = MAG_STATE_DEFAULT_REPEAT_MODE;
}

// set defaults we don't save
Expand All @@ -102,13 +130,16 @@ void mag_state_save(MagState* state) {
if(!flipper_format_file_open_always(file, MAG_STATE_PATH)) break;
if(!flipper_format_write_header_cstr(file, MAG_STATE_HEADER, MAG_STATE_VER)) break;

tmp = state->pin_input;
tmp = (uint32_t)state->pin_input;
if(!flipper_format_write_uint32(file, "pin_input", &tmp, 1)) break;
tmp = state->pin_output;
tmp = (uint32_t)state->pin_output;
if(!flipper_format_write_uint32(file, "pin_output", &tmp, 1)) break;
tmp = state->pin_enable;
tmp = (uint32_t)state->pin_enable;
if(!flipper_format_write_uint32(file, "pin_enable", &tmp, 1)) break;
if(!flipper_format_write_bool(file, "allow_uart", &state->allow_uart, 1)) break;
tmp = (uint32_t)state->n_repeats;
if(!flipper_format_write_uint32(file, "n_repeats", &tmp, 1)) break;
if(!flipper_format_write_bool(file, "repeat_mode", &state->repeat_mode, 1)) break;

} while(0);
flipper_format_free(file);
Expand Down
4 changes: 3 additions & 1 deletion non_catalog_apps/magspoof_flipper/mag_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "helpers/mag_types.h"

#define MAG_STATE_HEADER "Mag State"
#define MAG_STATE_VER 1
#define MAG_STATE_VER 2
#define MAG_STATE_DIR STORAGE_APP_DATA_PATH_PREFIX
#define MAG_STATE_PATH MAG_STATE_DIR "/mag_state.txt"

Expand All @@ -29,6 +29,8 @@ typedef struct {
MagPin pin_enable;
bool allow_uart;
bool is_debug;
uint8_t n_repeats;
bool repeat_mode;
} MagState;

const GpioPin* mag_state_enum_to_pin(MagPin pin);
Expand Down
43 changes: 32 additions & 11 deletions non_catalog_apps/magspoof_flipper/scenes/mag_scene_emulate_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
#define TAG "MagSceneEmulateConfig"

enum MagEmulateConfigIndex {
MagEmulateConfigIndexTx,
MagEmulateConfigIndexClock,
MagEmulateConfigIndexTrack,
MagEmulateConfigIndexReverse,
MagEmulateConfigIndexClock,
MagEmulateConfigIndexInterpacket,
MagEmulateConfigIndexRepeat,
MagEmulateConfigIndexTx,
// MagEmulateConfigIndexInterpacket,
};

#define TX_COUNT 7
Expand Down Expand Up @@ -163,6 +164,14 @@ static void mag_scene_emulate_config_set_reverse(VariableItem* item) {
}
};

static void mag_scene_emulate_config_set_repeat_mode(VariableItem* item) {
Mag* mag = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, reverse_text[index]);

mag->state.repeat_mode = (bool)index;
}

static void mag_scene_emulate_config_set_clock(VariableItem* item) {
Mag* mag = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
Expand All @@ -182,8 +191,6 @@ static void mag_scene_emulate_config_set_interpacket(VariableItem* item) {
};

void mag_scene_emulate_config_on_enter(void* context) {
// TODO: retrieve current values from struct, rather than setting to default on setup

Mag* mag = context;
VariableItem* item;
uint8_t value_index;
Expand All @@ -192,15 +199,15 @@ void mag_scene_emulate_config_on_enter(void* context) {
item = variable_item_list_add(
mag->variable_item_list, "Clock:", CLOCK_COUNT, mag_scene_emulate_config_set_clock, mag);
value_index = value_index_uint32(mag->state.us_clock, clock_value, CLOCK_COUNT);
scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
// scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, clock_text[value_index]);

// Track
item = variable_item_list_add(
mag->variable_item_list, "Track:", TRACK_COUNT, mag_scene_emulate_config_set_track, mag);
value_index = value_index_uint32(mag->state.track, track_value, TRACK_COUNT);
scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
//scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, track_text[value_index]);

Expand All @@ -213,7 +220,19 @@ void mag_scene_emulate_config_on_enter(void* context) {
mag_scene_emulate_config_set_reverse,
mag);
value_index = value_index_uint32(mag->state.reverse, reverse_value, REVERSE_COUNT);
scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
//scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, reverse_text[value_index]);

// Repeated TX
item = variable_item_list_add(
mag->variable_item_list,
"Repeat:",
REVERSE_COUNT,
mag_scene_emulate_config_set_repeat_mode,
mag);
value_index = (uint32_t)mag->state.repeat_mode;
//scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, reverse_text[value_index]);

Expand All @@ -224,7 +243,7 @@ void mag_scene_emulate_config_on_enter(void* context) {
item = variable_item_list_add(
mag->variable_item_list, "TX via:", TX_COUNT, mag_scene_emulate_config_set_tx, mag);
value_index = value_index_uint32(mag->state.tx, tx_value, TX_COUNT);
scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
//scene_manager_set_scene_state(mag->scene_manager, MagSceneEmulateConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, tx_text[value_index]);
#ifdef FW_ORIGIN_Official
Expand All @@ -247,6 +266,10 @@ void mag_scene_emulate_config_on_enter(void* context) {
variable_item_set_current_value_text(item, interpacket_text[value_index]);*/
UNUSED(mag_scene_emulate_config_set_interpacket);

variable_item_list_set_selected_item(
mag->variable_item_list,
scene_manager_get_scene_state(mag->scene_manager, MagSceneEmulateConfig));

view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewVariableItemList);
}

Expand All @@ -266,6 +289,4 @@ void mag_scene_emulate_config_on_exit(void* context) {
Mag* mag = context;
variable_item_list_set_selected_item(mag->variable_item_list, 0);
variable_item_list_reset(mag->variable_item_list);
// mag_last_settings_save?
// scene_manager_set_scene_state? Using subghz_scene_reciever_config as framework/inspo
}
16 changes: 0 additions & 16 deletions non_catalog_apps/magspoof_flipper/scenes/mag_scene_saved_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@ void mag_scene_saved_menu_on_enter(void* context) {
Mag* mag = context;
Submenu* submenu = mag->submenu;

// messy code to quickly check which tracks are available for emulation/display
// there's likely a better spot to do this, but the MagDevice functions don't have access to the full mag struct...
bool is_empty_t1 = furi_string_empty(mag->mag_dev->dev_data.track[0].str);
bool is_empty_t2 = furi_string_empty(mag->mag_dev->dev_data.track[1].str);
bool is_empty_t3 = furi_string_empty(mag->mag_dev->dev_data.track[2].str);

if(!is_empty_t1 && !is_empty_t2) {
mag->state.track = MagTrackStateOneAndTwo;
} else if(!is_empty_t1) {
mag->state.track = MagTrackStateOne;
} else if(!is_empty_t2) {
mag->state.track = MagTrackStateTwo;
} else if(!is_empty_t3) {
mag->state.track = MagTrackStateThree;
} // TODO: what happens if no track data present?

submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, mag_scene_saved_menu_submenu_callback, mag);
//submenu_add_item(
Expand Down
Loading

0 comments on commit a15380b

Please sign in to comment.