mirror of
https://github.com/bettse/seader.git
synced 2026-07-18 09:38:01 +00:00
Add view showing gpio traffic
This commit is contained in:
@@ -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 |
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
SeaderStartEventNone = 0,
|
||||
} SeaderCustomEvent;
|
||||
@@ -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, ...);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user