Add view showing gpio traffic

This commit is contained in:
Eric Betts
2023-07-16 17:04:37 -07:00
parent 6351e2c00a
commit 6982b4533b
14 changed files with 321 additions and 8 deletions
+1
View File
@@ -19,6 +19,7 @@ App(
"seader_worker.c",
"seader_credential.c",
"seader_icons.c",
"views/*.c",
],
fap_icon="icons/logo.png",
fap_category="NFC",
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -0,0 +1,5 @@
#pragma once
typedef enum {
SeaderStartEventNone = 0,
} SeaderCustomEvent;
+5
View File
@@ -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
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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);