فهرست منبع

Add view showing gpio traffic

Eric Betts 2 سال پیش
والد
کامیت
6982b4533b

+ 1 - 0
application.fam

@@ -19,6 +19,7 @@ App(
       "seader_worker.c",
       "seader_credential.c",
       "seader_icons.c",
+      "views/*.c",
     ],
     fap_icon="icons/logo.png",
     fap_category="NFC",

BIN
icons/ArrowUpEmpty_14x15.png


BIN
icons/ArrowUpFilled_14x15.png


+ 1 - 0
scenes/seader_scene_config.h

@@ -14,3 +14,4 @@ ADD_SCENE(seader, delete, Delete)
 ADD_SCENE(seader, delete_success, DeleteSuccess)
 ADD_SCENE(seader, credential_info, CredentialInfo)
 ADD_SCENE(seader, sam_info, SamInfo)
+ADD_SCENE(seader, uart, Uart)

+ 20 - 6
scenes/seader_scene_sam_present.c

@@ -66,14 +66,28 @@ bool seader_scene_sam_present_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SubmenuIndexReadPicopass) {
-            scene_manager_set_scene_state(
-                seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadPicopass);
-            scene_manager_next_scene(seader->scene_manager, SeaderSceneReadPicopass);
+            if(seader->is_debug_enabled) {
+                seader->credential->type = SeaderCredentialTypePicopass;
+                scene_manager_set_scene_state(
+                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadPicopass);
+                scene_manager_next_scene(seader->scene_manager, SeaderSceneUart);
+            } else {
+                scene_manager_set_scene_state(
+                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadPicopass);
+                scene_manager_next_scene(seader->scene_manager, SeaderSceneReadPicopass);
+            }
             consumed = true;
         } else if(event.event == SubmenuIndexRead14a) {
-            scene_manager_set_scene_state(
-                seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a);
-            scene_manager_next_scene(seader->scene_manager, SeaderSceneRead14a);
+            if(seader->is_debug_enabled) {
+                seader->credential->type = SeaderCredentialType14A;
+                scene_manager_set_scene_state(
+                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a);
+                scene_manager_next_scene(seader->scene_manager, SeaderSceneUart);
+            } else {
+                scene_manager_set_scene_state(
+                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a);
+                scene_manager_next_scene(seader->scene_manager, SeaderSceneRead14a);
+            }
             consumed = true;
         } else if(event.event == SubmenuIndexSamInfo) {
             scene_manager_set_scene_state(

+ 101 - 0
scenes/seader_scene_uart.c

@@ -0,0 +1,101 @@
+#include "../seader_i.h"
+#include "../seader_bridge.h"
+#define TAG "SeaderSceneUart"
+
+typedef struct {
+    SeaderUartConfig cfg;
+    SeaderUartState state;
+} SceneUartBridge;
+
+static SceneUartBridge* scene_uart;
+
+void seader_uart_worker_callback(SeaderWorkerEvent event, void* context) {
+    UNUSED(event);
+    Seader* seader = context;
+    view_dispatcher_send_custom_event(seader->view_dispatcher, SeaderCustomEventWorkerExit);
+}
+
+void seader_scene_uart_callback(SeaderCustomEvent event, void* context) {
+    furi_assert(context);
+    Seader* app = context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, event);
+}
+
+void seader_scene_uart_on_enter(void* context) {
+    Seader* app = context;
+    uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, SeaderViewUart);
+    if(prev_state == 0) {
+        scene_uart = malloc(sizeof(SceneUartBridge));
+        scene_uart->cfg.uart_ch = 0;
+        scene_uart->cfg.flow_pins = 0;
+        scene_uart->cfg.baudrate_mode = 0;
+        scene_uart->cfg.baudrate = 0;
+    }
+
+    seader_uart_get_config(app->uart, &scene_uart->cfg);
+    seader_uart_get_state(app->uart, &scene_uart->state);
+
+    seader_uart_view_set_callback(app->seader_uart_view, seader_scene_uart_callback, app);
+    scene_manager_set_scene_state(app->scene_manager, SeaderSceneUart, 0);
+    view_dispatcher_switch_to_view(app->view_dispatcher, SeaderViewUart);
+    notification_message(app->notifications, &sequence_display_backlight_enforce_on);
+
+    Seader* seader = app;
+
+    if(seader->credential->type == SeaderCredentialTypePicopass) {
+        seader_worker_start(
+            seader->worker,
+            SeaderWorkerStateReadPicopass,
+            seader->uart,
+            seader->credential,
+            seader_uart_worker_callback,
+            seader);
+    } else if(seader->credential->type == SeaderCredentialType14A) {
+        seader_worker_start(
+            seader->worker,
+            SeaderWorkerStateRead14a,
+            seader->uart,
+            seader->credential,
+            seader_uart_worker_callback,
+            seader);
+    }
+}
+
+bool seader_scene_uart_on_event(void* context, SceneManagerEvent event) {
+    Seader* app = context;
+    Seader* seader = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SeaderCustomEventWorkerExit) {
+            scene_manager_next_scene(seader->scene_manager, SeaderSceneReadCardSuccess);
+            consumed = true;
+        } else if(event.type == SceneManagerEventTypeTick) {
+            scene_manager_set_scene_state(app->scene_manager, SeaderSceneUart, 1);
+            consumed = true;
+        }
+    } else if(event.type == SceneManagerEventTypeTick) {
+        uint32_t tx_cnt_last = scene_uart->state.tx_cnt;
+        uint32_t rx_cnt_last = scene_uart->state.rx_cnt;
+        seader_uart_get_state(app->uart, &scene_uart->state);
+        if(seader->credential->type == SeaderCredentialTypePicopass) {
+            scene_uart->state.protocol = FrameProtocol_iclass;
+        } else if(seader->credential->type == SeaderCredentialType14A) {
+            scene_uart->state.protocol = FrameProtocol_nfc;
+        }
+        seader_uart_view_update_state(app->seader_uart_view, &scene_uart->cfg, &scene_uart->state);
+        if(tx_cnt_last != scene_uart->state.tx_cnt) {
+            notification_message(app->notifications, &sequence_blink_blue_10);
+        }
+        if(rx_cnt_last != scene_uart->state.rx_cnt) {
+            notification_message(app->notifications, &sequence_blink_green_10);
+        }
+    }
+    return consumed;
+}
+
+void seader_scene_uart_on_exit(void* context) {
+    Seader* app = context;
+    seader_worker_stop(app->worker);
+    notification_message(app->notifications, &sequence_display_backlight_enforce_auto);
+}

+ 9 - 0
seader.c

@@ -78,6 +78,12 @@ Seader* seader_alloc() {
     view_dispatcher_add_view(
         seader->view_dispatcher, SeaderViewWidget, widget_get_view(seader->widget));
 
+    seader->seader_uart_view = seader_uart_view_alloc();
+    view_dispatcher_add_view(
+        seader->view_dispatcher,
+        SeaderViewUart,
+        seader_uart_view_get_view(seader->seader_uart_view));
+
     return seader;
 }
 
@@ -114,6 +120,9 @@ void seader_free(Seader* seader) {
     view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewWidget);
     widget_free(seader->widget);
 
+    view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewUart);
+    seader_uart_view_free(seader->seader_uart_view);
+
     // Worker
     seader_worker_stop(seader->worker);
     seader_worker_free(seader->worker);

+ 1 - 1
seader_bridge.h

@@ -21,7 +21,7 @@ typedef struct {
 typedef struct {
     uint32_t rx_cnt;
     uint32_t tx_cnt;
-    uint32_t baudrate_cur;
+    uint8_t protocol;
 } SeaderUartState;
 
 struct SeaderUartBridge {

+ 5 - 0
seader_custom_event.h

@@ -0,0 +1,5 @@
+#pragma once
+
+typedef enum {
+    SeaderStartEventNone = 0,
+} SeaderCustomEvent;

+ 5 - 0
seader_i.h

@@ -33,6 +33,7 @@
 #include <FrameProtocol.h>
 
 #include "scenes/seader_scene.h"
+#include "views/seader_uart_view.h"
 
 #include "seader_bridge.h"
 #include "seader.h"
@@ -93,6 +94,9 @@ struct Seader {
     Loading* loading;
     TextInput* text_input;
     Widget* widget;
+
+    //Custom views
+    SeaderUartView* seader_uart_view;
 };
 
 typedef enum {
@@ -101,6 +105,7 @@ typedef enum {
     SeaderViewLoading,
     SeaderViewTextInput,
     SeaderViewWidget,
+    SeaderViewUart,
 } SeaderView;
 
 void seader_text_store_set(Seader* seader, const char* text, ...);

+ 2 - 0
seader_worker.c

@@ -871,6 +871,7 @@ int32_t seader_worker_task(void* context) {
         FURI_LOG_D(TAG, "Read Picopass");
         requestPacs = true;
         seader_credential_clear(seader_worker->credential);
+        seader_worker->credential->type = SeaderCredentialTypePicopass;
         seader_worker_enable_field();
         if(picopass_card_read(seader_worker) != ERR_NONE) {
             // Turn off if cancelled / no card found
@@ -880,6 +881,7 @@ int32_t seader_worker_task(void* context) {
         FURI_LOG_D(TAG, "Read 14a");
         requestPacs = true;
         seader_credential_clear(seader_worker->credential);
+        seader_worker->credential->type = SeaderCredentialType14A;
         nfc_scene_field_on_enter();
         if(!detect_nfc(seader_worker)) {
             // Turn off if cancelled / no card found

+ 0 - 1
uart.c

@@ -33,7 +33,6 @@ void seader_uart_serial_deinit(SeaderUartBridge* seader_uart, uint8_t uart_ch) {
 void seader_uart_set_baudrate(SeaderUartBridge* seader_uart, uint32_t baudrate) {
     if(baudrate != 0) {
         furi_hal_uart_set_br(seader_uart->cfg.uart_ch, baudrate);
-        seader_uart->st.baudrate_cur = baudrate;
     } else {
         FURI_LOG_I(TAG, "No baudrate specified");
     }

+ 152 - 0
views/seader_uart_view.c

@@ -0,0 +1,152 @@
+#include "../seader_bridge.h"
+#include "../seader_i.h"
+#include <furi_hal.h>
+#include <gui/elements.h>
+
+struct SeaderUartView {
+    View* view;
+    SeaderUartViewCallback callback;
+    void* context;
+};
+
+typedef struct {
+    uint32_t tx_cnt;
+    uint32_t rx_cnt;
+    bool tx_active;
+    bool rx_active;
+    uint8_t protocol;
+} SeaderUartViewModel;
+
+static void seader_uart_view_draw_callback(Canvas* canvas, void* _model) {
+    SeaderUartViewModel* model = _model;
+    char temp_str[18];
+
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "PICC <=> SAM");
+    canvas_draw_str(canvas, 3, 25, "TX:");
+    canvas_draw_str(canvas, 3, 42, "RX:");
+
+    if(model->protocol == FrameProtocol_iclass) {
+        canvas_draw_str_aligned(canvas, 64, 62, AlignCenter, AlignBottom, "Detecting picopass");
+    } else if(model->protocol == FrameProtocol_nfc) {
+        canvas_draw_str_aligned(canvas, 64, 62, AlignCenter, AlignBottom, "Detecting 14a");
+    }
+
+    if(model->tx_cnt < 100000000) {
+        canvas_set_font(canvas, FontSecondary);
+        canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "B.");
+        canvas_set_font(canvas, FontKeyboard);
+        snprintf(temp_str, 18, "%lu", model->tx_cnt);
+        canvas_draw_str_aligned(canvas, 116, 24, AlignRight, AlignBottom, temp_str);
+    } else {
+        canvas_set_font(canvas, FontSecondary);
+        canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, "KiB.");
+        canvas_set_font(canvas, FontKeyboard);
+        snprintf(temp_str, 18, "%lu", model->tx_cnt / 1024);
+        canvas_draw_str_aligned(canvas, 111, 24, AlignRight, AlignBottom, temp_str);
+    }
+
+    if(model->rx_cnt < 100000000) {
+        canvas_set_font(canvas, FontSecondary);
+        canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "B.");
+        canvas_set_font(canvas, FontKeyboard);
+        snprintf(temp_str, 18, "%lu", model->rx_cnt);
+        canvas_draw_str_aligned(canvas, 116, 41, AlignRight, AlignBottom, temp_str);
+    } else {
+        canvas_set_font(canvas, FontSecondary);
+        canvas_draw_str_aligned(canvas, 127, 41, AlignRight, AlignBottom, "KiB.");
+        canvas_set_font(canvas, FontKeyboard);
+        snprintf(temp_str, 18, "%lu", model->rx_cnt / 1024);
+        canvas_draw_str_aligned(canvas, 111, 41, AlignRight, AlignBottom, temp_str);
+    }
+
+    if(model->tx_active) {
+        canvas_draw_icon(canvas, 48, 14, &I_ArrowUpFilled_14x15);
+    } else {
+        canvas_draw_icon(canvas, 48, 14, &I_ArrowUpEmpty_14x15);
+    }
+
+    if(model->rx_active) {
+        canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpFilled_14x15, IconRotation180);
+    } else {
+        canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpEmpty_14x15, IconRotation180);
+    }
+}
+
+static bool seader_uart_view_input_callback(InputEvent* event, void* context) {
+    furi_assert(context);
+    SeaderUartView* seader_uart_view = context;
+    bool consumed = false;
+
+    if(event->type == InputTypeShort) {
+        if(event->key == InputKeyLeft) {
+            consumed = true;
+            furi_assert(seader_uart_view->callback);
+            // seader_uart_view->callback(SeaderUartViewEventConfig, seader_uart_view->context);
+        }
+    }
+
+    return consumed;
+}
+
+SeaderUartView* seader_uart_view_alloc() {
+    SeaderUartView* seader_uart_view = malloc(sizeof(SeaderUartView));
+
+    seader_uart_view->view = view_alloc();
+    view_allocate_model(seader_uart_view->view, ViewModelTypeLocking, sizeof(SeaderUartViewModel));
+    view_set_context(seader_uart_view->view, seader_uart_view);
+    view_set_draw_callback(seader_uart_view->view, seader_uart_view_draw_callback);
+    view_set_input_callback(seader_uart_view->view, seader_uart_view_input_callback);
+
+    return seader_uart_view;
+}
+
+void seader_uart_view_free(SeaderUartView* seader_uart_view) {
+    furi_assert(seader_uart_view);
+    view_free(seader_uart_view->view);
+    free(seader_uart_view);
+}
+
+View* seader_uart_view_get_view(SeaderUartView* seader_uart_view) {
+    furi_assert(seader_uart_view);
+    return seader_uart_view->view;
+}
+
+void seader_uart_view_set_callback(
+    SeaderUartView* seader_uart_view,
+    SeaderUartViewCallback callback,
+    void* context) {
+    furi_assert(seader_uart_view);
+    furi_assert(callback);
+
+    with_view_model(
+        seader_uart_view->view,
+        SeaderUartViewModel * model,
+        {
+            UNUSED(model);
+            seader_uart_view->callback = callback;
+            seader_uart_view->context = context;
+        },
+        false);
+}
+
+void seader_uart_view_update_state(
+    SeaderUartView* instance,
+    SeaderUartConfig* cfg,
+    SeaderUartState* st) {
+    furi_assert(instance);
+    furi_assert(cfg);
+    furi_assert(st);
+
+    with_view_model(
+        instance->view,
+        SeaderUartViewModel * model,
+        {
+            model->tx_active = (model->tx_cnt != st->tx_cnt);
+            model->rx_active = (model->rx_cnt != st->rx_cnt);
+            model->tx_cnt = st->tx_cnt;
+            model->rx_cnt = st->rx_cnt;
+            model->protocol = st->protocol;
+        },
+        true);
+}

+ 24 - 0
views/seader_uart_view.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include <gui/view.h>
+#include "../seader_custom_event.h"
+#include "../seader_bridge.h"
+
+typedef struct SeaderUartView SeaderUartView;
+typedef void (*SeaderUartViewCallback)(SeaderCustomEvent event, void* context);
+
+SeaderUartView* seader_uart_view_alloc();
+
+void seader_uart_view_free(SeaderUartView* seader_uart_view);
+
+View* seader_uart_view_get_view(SeaderUartView* seader_uart_view);
+
+void seader_uart_view_set_callback(
+    SeaderUartView* seader_uart_view,
+    SeaderUartViewCallback callback,
+    void* context);
+
+void seader_uart_view_update_state(
+    SeaderUartView* instance,
+    SeaderUartConfig* cfg,
+    SeaderUartState* st);