Procházet zdrojové kódy

Saved emulate 90% functional

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)
Zachary Weiss před 3 roky
rodič
revize
ecf253af53

+ 129 - 26
helpers/mag_helpers.c

@@ -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
@@ -7,8 +8,8 @@
 #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};
@@ -16,39 +17,52 @@ const uint8_t bitlen[] = {7, 5, 5};
 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();
 
@@ -73,7 +87,7 @@ 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);
 
@@ -81,21 +95,46 @@ void rfid_tx_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
@@ -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;
@@ -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];
@@ -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...

+ 12 - 6
helpers/mag_helpers.h

@@ -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);

+ 1 - 1
mag_i.h

@@ -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"
 

+ 7 - 5
scenes/mag_scene_emulate.c

@@ -1,4 +1,5 @@
 #include "../mag_i.h"
+#include "../helpers/mag_helpers.h"
 
 void mag_scene_emulate_on_enter(void* context) {
     Mag* mag = context;
@@ -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);
         }
     }
 

+ 1 - 1
scenes/mag_scene_emulate_config.c

@@ -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);

+ 2 - 2
scenes/mag_scene_emulate_test.c

@@ -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;
@@ -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);
 

+ 6 - 5
scenes/mag_scene_start.c

@@ -1,7 +1,7 @@
 #include "../mag_i.h"
 
 typedef enum {
-    SubmenuIndexEmulateTest,
+    //SubmenuIndexEmulateTest,
     SubmenuIndexSaved,
     SubmenuIndexAddManually,
 } SubmenuIndex;
@@ -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);
@@ -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;