MX 2 лет назад
Родитель
Сommit
6758a55591

+ 2 - 2
ReadMe.md

@@ -20,7 +20,7 @@ Sources of "integrated/bundled" apps are added now in this repo too, to allow pu
 
 The Flipper and its community wouldn't be as rich as it is without your contributions and support. Thank you for all you have done.
 
-### Apps checked & updated at `5 Jul 19:55 GMT +3`
+### Apps checked & updated at `6 Jul 01:40 GMT +3`
 
 ## Games
 - [Pong (By nmrr)](https://github.com/nmrr/flipperzero-pong) - Modified by [SimplyMinimal](https://github.com/SimplyMinimal/FlipperZero-Pong)
@@ -72,6 +72,7 @@ The Flipper and its community wouldn't be as rich as it is without your contribu
 - [NRF24 Scanner (By vad7)](https://github.com/vad7/nrf24scan)
 - [GPIO Reader (By aureli1c)](https://github.com/aureli1c/flipperzero_GPIO_read)
 - [GPIO Reader 2 (By biotinker)](https://github.com/biotinker/flipperzero-gpioreader)
+- [MagSpoof (WIP) (By zacharyweiss)](https://github.com/zacharyweiss/magspoof_flipper) - Read mode [(by hummusec)](https://github.com/hummusec/magspoof_flipper) - + GPIO & Power fixes
 - [Timelapse (zeitraffer) (By theageoflove)](https://github.com/theageoflove/flipperzero-zeitraffer)
 - [Geiger Counter (By nmrr)](https://github.com/nmrr/flipperzero-geigercounter) - works with external module!
 - [Pwnagotchi->Flipper interface (By Matt-London)](https://github.com/Matt-London/pwnagotchi-flipper)
@@ -121,7 +122,6 @@ The Flipper and its community wouldn't be as rich as it is without your contribu
 - [Brainfuck interpreter (By nymda)](https://github.com/nymda/FlipperZeroBrainfuck)
 - [NightStand Clock (By nymda)](https://github.com/nymda/FlipperNightStand) - Fixes by [Willy-JL](https://github.com/Willy-JL)
 - [BT Camera Trigger (By Nem0oo)](https://github.com/Nem0oo/flipper-zero-bluetooth-trigger)
-- [MagSpoof (WIP) (By zacharyweiss)](https://github.com/zacharyweiss/magspoof_flipper)
 - [IR Xbox Controller (By gebeto)](https://github.com/gebeto/flipper-xbox-controller)
 - [EM4100 universal keys generator (for RFID Fuzzer) (By Milk-Cool)](https://github.com/Milk-Cool/fz-em4100-generator)
 - [FlipBIP Crypto Tool (By xtruan)](https://github.com/xtruan/FlipBIP)

BIN
apps/GPIO/air_mouse.fap


BIN
apps/GPIO/mag.fap


+ 0 - 3
apps_source_code/airmouse/air_mouse.c

@@ -1,8 +1,6 @@
 #include "air_mouse.h"
 
 #include <furi.h>
-#include <dolphin/dolphin.h>
-
 #include "tracking/imu/imu.h"
 
 #define TAG "AirMouseApp"
@@ -146,7 +144,6 @@ int32_t air_mouse_app(void* p) {
         return -1;
     }
 
-    dolphin_deed(DolphinDeedPluginStart);
     view_dispatcher_run(app->view_dispatcher);
 
     imu_end();

+ 2 - 2
apps_source_code/magspoof_flipper/application.fam

@@ -1,6 +1,6 @@
 App(
     appid="mag",
-    name="MagSpoof WIP",
+    name="MagSpoof",
     apptype=FlipperAppType.EXTERNAL,
     entry_point="mag_app",
     cdefines=["APP_MAG"],
@@ -11,7 +11,7 @@ App(
         "dialogs",
     ],
     provides=[],
-    stack_size=5 * 1024,
+    stack_size=6 * 1024,
     order=64,  # keep it at the bottom of the list while still WIP
     fap_icon="icons/mag_10px.png",
     fap_category="GPIO",

+ 10 - 9
apps_source_code/magspoof_flipper/helpers/mag_helpers.c

@@ -2,8 +2,9 @@
 
 #define TAG "MagHelpers"
 
-#define GPIO_PIN_A &gpio_ext_pa6
-#define GPIO_PIN_B &gpio_ext_pa7
+// Haviv Board - pins gpio_ext_pa7 & gpio_ext_pa6 was swapped.
+#define GPIO_PIN_A &gpio_ext_pa7
+#define GPIO_PIN_B &gpio_ext_pa6
 #define GPIO_PIN_ENABLE &gpio_ext_pa4
 #define RFID_PIN_OUT &gpio_rfid_carrier_out
 
@@ -125,10 +126,9 @@ void play_track(uint8_t* bits_manchester, uint16_t n_bits, MagSetting* setting,
 void tx_init_rfid() {
     // initialize RFID system for TX
 
-    // OTG needed for RFID? Or just legacy from GPIO?
-    furi_hal_power_enable_otg();
-
     furi_hal_ibutton_pin_configure();
+
+    // furi_hal_ibutton_start_drive();
     furi_hal_ibutton_pin_write(false);
 
     // Initializing at GpioSpeedLow seems sufficient for our needs; no improvements seen by increasing speed setting
@@ -153,7 +153,6 @@ void tx_deinit_rfid() {
     furi_hal_gpio_write(RFID_PIN_OUT, 0);
 
     furi_hal_rfid_pins_reset();
-    furi_hal_power_disable_otg();
 }
 
 void tx_init_rf(int hz) {
@@ -187,7 +186,6 @@ bool tx_init(MagSetting* setting) {
         tx_init_rfid();
         break;
     case MagTxStateGPIO:
-        furi_hal_power_enable_otg();
         // 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);
@@ -232,9 +230,12 @@ bool tx_deinit(MagSetting* setting) {
         furi_hal_gpio_write(GPIO_PIN_B, 0);
         furi_hal_gpio_write(GPIO_PIN_ENABLE, 0);
 
-        // set back to analog output mode?
+        // set back to analog output mode? - YES
+        furi_hal_gpio_init(GPIO_PIN_A, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+        furi_hal_gpio_init(GPIO_PIN_B, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+        furi_hal_gpio_init(GPIO_PIN_ENABLE, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+
         //gpio_item_configure_all_pins(GpioModeAnalog);
-        furi_hal_power_disable_otg();
         break;
     case MagTxStatePiezo:
         tx_deinit_piezo();

+ 7 - 0
apps_source_code/magspoof_flipper/helpers/mag_types.h

@@ -36,3 +36,10 @@ typedef enum {
     MagTxCC1101_434,
     MagTxCC1101_868,
 } MagTxState;
+
+
+typedef enum {
+    UART_TerminalEventRefreshConsoleOutput = 0,
+    UART_TerminalEventStartConsole,
+    UART_TerminalEventStartKeyboard,
+} UART_TerminalCustomEvent;

+ 71 - 0
apps_source_code/magspoof_flipper/mag_device.c

@@ -230,6 +230,77 @@ bool mag_device_delete(MagDevice* mag_dev, bool use_load_path) {
     return deleted;
 }
 
+bool mag_device_parse_card_string(MagDevice* mag_dev, FuriString* f_card_str) {
+    furi_assert(mag_dev);
+    FURI_LOG_D(TAG, "mag_device_parse_card_string");
+
+    const char* card_str = furi_string_get_cstr(f_card_str);
+
+    FURI_LOG_D(TAG, "Parsing card string: %s", card_str);
+
+    // Track 1
+    const char* track1_start = strchr(card_str, '%');
+    if(!track1_start) {
+        FURI_LOG_D(TAG, "Could not find track 1 start");
+        return false;
+    }
+    track1_start++;
+    const char* track1_end = strchr(track1_start, '?');
+    if(!track1_end) {
+        FURI_LOG_D(TAG, "Could not find track 1 end");
+        return false;
+    }
+    size_t track1_len = track1_end - track1_start;
+    
+    FURI_LOG_D(TAG, "Track 1: %.*s", track1_len, track1_start);
+
+    mag_dev->dev_data.track[0].len = track1_len;
+    furi_string_printf(mag_dev->dev_data.track[0].str, "%%%.*s?", track1_len, track1_start);
+
+    // Track 2
+    const char* track2_start = strchr(track1_end, ';');
+    if (!track2_start) {
+        FURI_LOG_D(TAG, "Could not find track 2 start");
+        return true;
+    }
+
+    track2_start++;
+    const char* track2_end = strchr(track2_start, '?');
+    if(!track2_end) {
+        FURI_LOG_D(TAG, "Could not find track 2 end");
+        return true;
+    }
+    size_t track2_len = track2_end - track2_start;
+
+    FURI_LOG_D(TAG, "Track 2: %.*s", track2_len, track2_start);
+
+    mag_dev->dev_data.track[1].len = track2_len;
+    furi_string_printf(mag_dev->dev_data.track[1].str, "%%%.*s?", track2_len, track2_start);
+
+    // Track 3
+    const char* track3_start = strchr(track2_end, ';');
+    if (!track3_start) {
+        FURI_LOG_D(TAG, "Could not find track 3 start");
+        return true;
+    }
+
+    track3_start++;
+    const char* track3_end = strchr(track3_start, '?');
+    if(!track3_end) {
+        FURI_LOG_D(TAG, "Could not find track 3 end");
+        return true;
+    }
+    size_t track3_len = track3_end - track3_start;
+
+    FURI_LOG_D(TAG, "Track 3: %.*s", track3_len, track3_start);
+
+    mag_dev->dev_data.track[2].len = track3_len;
+    furi_string_printf(mag_dev->dev_data.track[2].str, "%%%.*s?", track3_len, track3_start);
+    
+    return true;
+}
+
+
 void mag_device_set_loading_callback(
     MagDevice* mag_dev,
     MagLoadingCallback callback,

+ 3 - 0
apps_source_code/magspoof_flipper/mag_device.h

@@ -17,6 +17,7 @@ typedef void (*MagLoadingCallback)(void* context, bool state);
 
 typedef struct {
     FuriString* str;
+    size_t len;
 } MagTrack;
 
 typedef struct {
@@ -49,6 +50,8 @@ void mag_device_clear(MagDevice* mag_dev);
 
 bool mag_device_delete(MagDevice* mag_dev, bool use_load_path);
 
+bool mag_device_parse_card_string(MagDevice* mag_dev, FuriString* card_str);
+
 void mag_device_set_loading_callback(
     MagDevice* mag_dev,
     MagLoadingCallback callback,

+ 13 - 0
apps_source_code/magspoof_flipper/mag_i.h

@@ -33,6 +33,7 @@
 #include <toolbox/value_index.h>
 
 #include "scenes/mag_scene.h"
+#include "scenes/mag_scene_read.h"
 
 #define MAG_TEXT_STORE_SIZE 150
 
@@ -50,6 +51,7 @@ typedef struct {
     uint32_t us_interpacket;
 } MagSetting;
 
+
 typedef struct {
     ViewDispatcher* view_dispatcher;
     Gui* gui;
@@ -76,6 +78,17 @@ typedef struct {
 
     // Custom views
     Mag_TextInput* mag_text_input;
+
+    // UART
+    FuriThread* uart_rx_thread;
+    FuriStreamBuffer* uart_rx_stream;
+    uint8_t uart_rx_buf[UART_RX_BUF_SIZE + 1];
+    void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
+    
+    char uart_text_input_store[UART_TERMINAL_TEXT_INPUT_STORE_SIZE + 1];
+    FuriString* uart_text_box_store;
+    size_t uart_text_box_store_strlen;
+    // UART_TextInput* text_input;
 } Mag;
 
 void mag_text_store_set(Mag* mag, const char* text, ...);

+ 1 - 0
apps_source_code/magspoof_flipper/scenes/mag_scene_config.h

@@ -12,3 +12,4 @@ ADD_SCENE(mag, delete_success, DeleteSuccess)
 ADD_SCENE(mag, delete_confirm, DeleteConfirm)
 ADD_SCENE(mag, exit_confirm, ExitConfirm)
 ADD_SCENE(mag, under_construction, UnderConstruction)
+ADD_SCENE(mag, read, Read)

+ 178 - 0
apps_source_code/magspoof_flipper/scenes/mag_scene_read.c

@@ -0,0 +1,178 @@
+// Creator: Hummus@FlipperGang
+
+#include "../mag_i.h"
+#include "../helpers/mag_helpers.h"
+
+#include "mag_scene_read.h"
+
+#define TAG "MagSceneRead"
+
+void uart_callback(UartIrqEvent event, uint8_t data, void *context) {
+    Mag* mag = context;
+    if(event == UartIrqEventRXNE) {
+        furi_stream_buffer_send(mag->uart_rx_stream, &data, 1, 0);
+        furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtRxDone);
+    }
+}
+
+static int32_t uart_worker(void* context) {
+    Mag* mag = context;
+    mag->uart_rx_stream = furi_stream_buffer_alloc(UART_RX_BUF_SIZE, 1);
+    mag->uart_text_box_store_strlen = 0;
+
+    while (1) {
+        uint32_t events = furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
+        // furi_check((events & FuriFlagError) == 0);
+        
+        if(events & WorkerEvtStop) break;
+        if(events & WorkerEvtRxDone) {
+            FURI_LOG_D(TAG, "WorkerEvtRxDone");
+            // notification_message(mag->notifications, &sequence_success);
+            size_t len = furi_stream_buffer_receive(mag->uart_rx_stream, mag->uart_rx_buf, UART_RX_BUF_SIZE, 200);
+            FURI_LOG_D(TAG, "UART RX len: %d", len);
+            
+            if (len > 0) {
+                // If text box store gets too big, then truncate it
+                mag->uart_text_box_store_strlen += len;
+
+                if(mag->uart_text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
+                    furi_string_right(mag->uart_text_box_store, mag->uart_text_box_store_strlen / 2);
+                    mag->uart_text_box_store_strlen = furi_string_size(mag->uart_text_box_store) + len;
+                }
+
+                // Add '\0' to the end of the string, and then add the new data
+                mag->uart_rx_buf[len] = '\0';
+                furi_string_cat_printf(mag->uart_text_box_store, "%s", mag->uart_rx_buf);
+
+                FURI_LOG_D(TAG, "UART RX buf: %*.s", len, mag->uart_rx_buf);
+                FURI_LOG_D(TAG, "UART RX store: %s", furi_string_get_cstr(mag->uart_text_box_store));
+
+            }
+
+            FURI_LOG_D(TAG, "UARTEventRxData");
+            
+            view_dispatcher_send_custom_event(
+                mag->view_dispatcher, UARTEventRxData);
+            
+        }
+    }
+    
+    furi_stream_buffer_free(mag->uart_rx_stream);
+
+    return 0;
+}
+
+void update_widgets(Mag* mag) {
+    // Clear widget from all elements
+    widget_reset(mag->widget);
+
+    // Titlebar
+    widget_add_icon_element(mag->widget, 38, -1, &I_mag_file_10px);
+    widget_add_string_element(mag->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "READ");
+    widget_add_icon_element(mag->widget, 81, -1, &I_mag_file_10px);
+
+    // Text box
+    widget_add_text_scroll_element(mag->widget, 0, 10, 128, 40, furi_string_get_cstr(mag->uart_text_box_store));
+
+    // Buttons
+    widget_add_button_element(mag->widget, GuiButtonTypeLeft, "Clear", mag_widget_callback, mag);
+    widget_add_button_element(mag->widget, GuiButtonTypeRight, "Parse", mag_widget_callback, mag);
+}
+
+void mag_scene_read_on_enter(void* context) {
+    Mag* mag = context;
+    FuriString* message = furi_string_alloc();
+    furi_string_printf(message, "Please swipe a card!\n");
+    mag->uart_text_box_store = message;
+    furi_string_free(message);
+    view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);
+    
+    update_widgets(mag);
+    
+    
+    // Initialize UART
+    // furi_hal_console_disable();
+    furi_hal_uart_deinit(FuriHalUartIdUSART1);
+    furi_hal_uart_init(FuriHalUartIdUSART1, 9600);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_callback, mag);
+    FURI_LOG_D(TAG, "UART initialized");
+
+    mag->uart_rx_thread = furi_thread_alloc();
+    furi_thread_set_name(mag->uart_rx_thread, "UartRx");
+    furi_thread_set_stack_size(mag->uart_rx_thread, 1024);
+    furi_thread_set_context(mag->uart_rx_thread, mag);
+    furi_thread_set_callback(mag->uart_rx_thread, uart_worker);
+
+    furi_thread_start(mag->uart_rx_thread);
+    FURI_LOG_D(TAG, "UART worker started");
+}
+
+bool mag_scene_read_on_event(void* context, SceneManagerEvent event) {
+    Mag* mag = context;
+    
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        FURI_LOG_D(TAG, "Custom event: %ld", event.event);
+
+        switch(event.event) {
+        case GuiButtonTypeLeft: // Clear
+            consumed = true;
+            // Clear text box store
+            furi_string_reset(mag->uart_text_box_store);
+            mag->uart_text_box_store_strlen = 0;
+            break;
+
+        case GuiButtonTypeRight: // Parse
+            consumed = true;
+            FURI_LOG_D(TAG, "Trying to parse");
+            MagDevice* mag_dev = mag->mag_dev;
+
+            bool res = mag_device_parse_card_string(mag_dev, mag->uart_text_box_store);
+            furi_string_reset(mag->uart_text_box_store);
+            if(res) {
+                notification_message(mag->notifications, &sequence_success);
+                
+                furi_string_printf(mag->uart_text_box_store, "Track 1: %.*s\nTrack 2: %.*s\nTrack 3: %.*s",
+                    mag_dev->dev_data.track[0].len, furi_string_get_cstr(mag_dev->dev_data.track[0].str),
+                    mag_dev->dev_data.track[1].len, furi_string_get_cstr(mag_dev->dev_data.track[1].str),
+                    mag_dev->dev_data.track[2].len, furi_string_get_cstr(mag_dev->dev_data.track[2].str));
+
+                // Switch to saved menu scene
+                scene_manager_next_scene(mag->scene_manager, MagSceneSavedMenu);
+
+            } else {
+                furi_string_printf(mag->uart_text_box_store, "Failed to parse! Try again\n");
+                notification_message(mag->notifications, &sequence_error);
+            }
+
+            break;
+        }
+
+        update_widgets(mag);
+    }
+
+    return consumed;
+}
+
+void mag_scene_read_on_exit(void* context) {
+    Mag* mag = context;
+    // notification_message(mag->notifications, &sequence_blink_stop);
+    widget_reset(mag->widget);
+    // view_dispatcher_remove_view(mag->view_dispatcher, MagViewWidget);
+    
+    // Stop UART worker
+    FURI_LOG_D(TAG, "Stopping UART worker");
+    furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtStop);
+    furi_thread_join(mag->uart_rx_thread);
+    furi_thread_free(mag->uart_rx_thread);
+    FURI_LOG_D(TAG, "UART worker stopped");
+
+    furi_string_free(mag->uart_text_box_store);
+
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
+    furi_hal_uart_deinit(FuriHalUartIdUSART1);
+    // furi_hal_console_enable();
+    
+    notification_message(mag->notifications, &sequence_blink_stop);
+}

+ 21 - 0
apps_source_code/magspoof_flipper/scenes/mag_scene_read.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <gui/modules/text_box.h>
+
+#define UART_RX_BUF_SIZE (320)
+#define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096)
+#define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512)
+#define UART_CH (FuriHalUartIdUSART1)
+#define UART_BAUDRATE (9600)
+
+typedef enum {
+    WorkerEvtStop = (1 << 0),
+    WorkerEvtRxDone = (1 << 1),
+} WorkerEvtFlags;
+
+typedef enum {
+    UARTEventRxData = 100,
+} UARTEvents;
+
+
+#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)

+ 7 - 0
apps_source_code/magspoof_flipper/scenes/mag_scene_start.c

@@ -2,6 +2,7 @@
 
 typedef enum {
     SubmenuIndexSaved,
+    SubmenuIndexRead,
     //SubmenuIndexAddManually,
     SubmenuIndexAbout,
 } SubmenuIndex;
@@ -17,6 +18,7 @@ void mag_scene_start_on_enter(void* context) {
     Submenu* submenu = mag->submenu;
 
     submenu_add_item(submenu, "Saved", SubmenuIndexSaved, mag_scene_start_submenu_callback, mag);
+    submenu_add_item(submenu, "Read", SubmenuIndexRead, mag_scene_start_submenu_callback, mag);
     //submenu_add_item(
     //    submenu, "Add Manually", SubmenuIndexAddManually, mag_scene_start_submenu_callback, mag);
     submenu_add_item(submenu, "About", SubmenuIndexAbout, mag_scene_start_submenu_callback, mag);
@@ -41,6 +43,11 @@ bool mag_scene_start_on_event(void* context, SceneManagerEvent event) {
             scene_manager_next_scene(mag->scene_manager, MagSceneFileSelect);
             consumed = true;
             break;
+
+        case SubmenuIndexRead:
+            scene_manager_next_scene(mag->scene_manager, MagSceneRead);
+            consumed = true;
+            break;
         //case SubmenuIndexAddManually:
         //    scene_manager_next_scene(mag->scene_manager, MagSceneInputValue);
         //    consumed = true;