From aeb02500deaf2448343c818a58c019f737930e13 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sat, 24 Sep 2022 21:47:21 +0400 Subject: [PATCH 01/29] Deep refactor of SubBrute was made, but it doesn't start. Debug device needed --- applications/plugins/subbrute/application.fam | 2 +- .../subbrute/helpers/subbrute_worker.c | 203 ++++++ .../subbrute/helpers/subbrute_worker.h | 32 + .../scene/subbrute_scene_entrypoint.c | 197 ------ .../scene/subbrute_scene_entrypoint.h | 8 - .../subbrute/scene/subbrute_scene_load_file.c | 222 ------- .../subbrute/scene/subbrute_scene_load_file.h | 8 - .../scene/subbrute_scene_run_attack.c | 384 ------------ .../scene/subbrute_scene_run_attack.h | 8 - .../subbrute/scene/subbrute_scene_save_name.c | 222 ------- .../subbrute/scene/subbrute_scene_save_name.h | 6 - .../scene/subbrute_scene_select_field.c | 121 ---- .../scene/subbrute_scene_select_field.h | 8 - .../plugins/subbrute/scenes/subbrute_scene.h | 29 + .../subbrute/scenes/subbrute_scene_config.h | 6 + .../scenes/subbrute_scene_load_file.c | 61 ++ .../scenes/subbrute_scene_run_attack.c | 158 +++++ .../scenes/subbrute_scene_save_name.c | 75 +++ .../scenes/subbrute_scene_save_success.c | 59 ++ .../scenes/subbrute_scene_setup_attack.c | 96 +++ .../subbrute/scenes/subbrute_scene_start.c | 50 ++ .../plugins/subbrute/scenes/subbute_scene.c | 30 + applications/plugins/subbrute/subbrute.c | 426 ++++++------- applications/plugins/subbrute/subbrute.h | 109 +--- .../plugins/subbrute/subbrute_custom_event.h | 25 + .../plugins/subbrute/subbrute_device.c | 582 ++++++++++++++++++ .../plugins/subbrute/subbrute_device.h | 103 ++++ applications/plugins/subbrute/subbrute_i.h | 87 +++ .../plugins/subbrute/subbrute_utils.c | 13 - .../plugins/subbrute/subbrute_utils.h | 4 - .../subbrute/views/subbrute_attack_view.c | 321 ++++++++++ .../subbrute/views/subbrute_attack_view.h | 36 ++ .../subbrute/views/subbrute_main_view.c | 152 +++++ .../subbrute/views/subbrute_main_view.h | 28 + 34 files changed, 2334 insertions(+), 1537 deletions(-) create mode 100644 applications/plugins/subbrute/helpers/subbrute_worker.c create mode 100644 applications/plugins/subbrute/helpers/subbrute_worker.h delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_entrypoint.c delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_entrypoint.h delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_load_file.c delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_load_file.h delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_run_attack.c delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_run_attack.h delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_save_name.c delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_save_name.h delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_select_field.c delete mode 100644 applications/plugins/subbrute/scene/subbrute_scene_select_field.h create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene.h create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_config.h create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_load_file.c create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_save_name.c create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_save_success.c create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_start.c create mode 100644 applications/plugins/subbrute/scenes/subbute_scene.c create mode 100644 applications/plugins/subbrute/subbrute_custom_event.h create mode 100644 applications/plugins/subbrute/subbrute_device.c create mode 100644 applications/plugins/subbrute/subbrute_device.h create mode 100644 applications/plugins/subbrute/subbrute_i.h delete mode 100644 applications/plugins/subbrute/subbrute_utils.c delete mode 100644 applications/plugins/subbrute/subbrute_utils.h create mode 100644 applications/plugins/subbrute/views/subbrute_attack_view.c create mode 100644 applications/plugins/subbrute/views/subbrute_attack_view.h create mode 100644 applications/plugins/subbrute/views/subbrute_main_view.c create mode 100644 applications/plugins/subbrute/views/subbrute_main_view.h diff --git a/applications/plugins/subbrute/application.fam b/applications/plugins/subbrute/application.fam index 752b0e0e6..1afdc539f 100644 --- a/applications/plugins/subbrute/application.fam +++ b/applications/plugins/subbrute/application.fam @@ -2,7 +2,7 @@ App( appid="subbrute", name="Sub-GHz Bruteforcer", apptype=FlipperAppType.EXTERNAL, - entry_point="subbrute_start", + entry_point="subbrute_app", cdefines=["APP_SUB_BRUTE"], requires=["gui","dialogs"], stack_size=2 * 1024, diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c new file mode 100644 index 000000000..e947aaf2a --- /dev/null +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -0,0 +1,203 @@ +#include +#include + +#include +#include + +#include "subbrute_worker.h" + +#define TAG "SubBruteWorker" + +struct SubBruteWorker { + FuriThread* thread; + volatile bool worker_running; + + SubGhzEnvironment* environment; + SubGhzReceiver* receiver; + SubGhzTransmitter* transmitter; + SubGhzProtocolDecoderBase* decoder_result; + FlipperFormat* flipper_format; + + uint32_t last_time_tx_data; + FuriMessageQueue* event_queue; + + // Preset and frequency needed + FuriHalSubGhzPreset preset; + uint32_t frequency; + string_t protocol_name; + + //SubBruteWorkerCallback callback; + //void* context; +}; + +/** Taken from subghz_tx_rx_worker.c */ +#define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048 +#define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60 +#define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 +#define SUBBRUTE_TX_TIMEOUT 200 +#define SUBBRUTE_SEND_DELAY 260 + +/** + * Entrypoint for worker + * + * @param context SubBruteWorker* + * @return 0 if ok + */ +int32_t subbrute_worker_thread(void* context) { + furi_assert(context); + SubBruteWorker* instance = (SubBruteWorker*)context; + + if(!instance->worker_running) { + FURI_LOG_W(TAG, "Worker is not set to running state!"); + return -1; + } +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Worker start"); +#endif + + instance->environment = subghz_environment_alloc(); + instance->transmitter = subghz_transmitter_alloc_init( + instance->environment, string_get_cstr(instance->protocol_name)); + + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(instance->preset); + instance->frequency = furi_hal_subghz_set_frequency_and_path(instance->frequency); + + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_cc1101_g0, true); + + furi_hal_power_suppress_charge_enter(); + + // Set ready to transmit value + instance->last_time_tx_data = furi_get_tick() - SUBBRUTE_SEND_DELAY; + + while(instance->worker_running) { + // Transmit + if(!furi_hal_subghz_tx()) { + FURI_LOG_E(TAG, "Cannot transmit!"); + break; + } + furi_delay_ms(250); + } + + furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); + furi_hal_subghz_sleep(); + + furi_hal_power_suppress_charge_exit(); + + subghz_transmitter_free(instance->transmitter); + subghz_environment_free(instance->environment); + +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Worker stop"); +#endif + return 0; +} + +SubBruteWorker* subbrute_worker_alloc() { + SubBruteWorker* instance = malloc(sizeof(SubBruteWorker)); + + instance->thread = furi_thread_alloc(); + furi_thread_set_name(instance->thread, "SubBruteAttackWorker"); + furi_thread_set_stack_size(instance->thread, 2048); + furi_thread_set_context(instance->thread, instance); + furi_thread_set_callback(instance->thread, subbrute_worker_thread); + + //instance->status = SubBruteWorkerStatusIDLE; + instance->worker_running = false; + + instance->flipper_format = flipper_format_string_alloc(); + string_init(instance->protocol_name); + + return instance; +} + +void subbrute_worker_free(SubBruteWorker* instance) { + furi_assert(instance); + furi_assert(!instance->worker_running); + + furi_thread_free(instance->thread); + flipper_format_free(instance->flipper_format); + string_clear(instance->protocol_name); + + free(instance); +} + +bool subbrute_worker_start( + SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + string_t protocol_name) { + furi_assert(instance); + furi_assert(!instance->worker_running); + + instance->frequency = frequency; + instance->preset = preset; + string_init_move(instance->protocol_name, protocol_name); + + bool res = false; + + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_preset(instance->preset); + + furi_hal_subghz_set_frequency_and_path(instance->frequency); + furi_hal_subghz_flush_rx(); + + if(furi_hal_subghz_is_tx_allowed(frequency)) { + instance->frequency = frequency; + res = true; + } + instance->worker_running = res; + +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Frequency: %d", frequency); +#endif + instance->preset = preset; + + furi_thread_start(instance->thread); + + return res; +} + +void subbrute_worker_stop(SubBruteWorker* instance) { + furi_assert(instance); + + instance->worker_running = false; + + furi_thread_join(instance->thread); + + furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); + furi_hal_subghz_sleep(); +} + +bool subbrute_worker_is_running(SubBruteWorker* instance) { + furi_assert(instance); + + return instance->worker_running; +} + +bool subbrute_worker_can_transmit(SubBruteWorker* instance) { + furi_assert(instance); + + return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY; +} + +bool subbrute_worker_transmit(SubBruteWorker* instance, string_t payload) { + furi_assert(instance); + furi_assert(instance->worker_running); + + if(!subbrute_worker_can_transmit(instance)) { + FURI_LOG_E(TAG, "Too early to transmit"); + + return false; + } + instance->last_time_tx_data = furi_get_tick(); + + Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); + stream_clean(stream); + stream_write_cstring(stream, string_get_cstr(payload)); + subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); + + return true; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h new file mode 100644 index 000000000..d0ed3cbf7 --- /dev/null +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +typedef struct SubBruteWorker SubBruteWorker; +/** + * Same like SubGhzTxRxWorkerStatus in subghz_tx_rx_worker.h + * using just to not include that file + +typedef enum { + SubBruteWorkerStatusIDLE, + SubBruteWorkerStatusTx, + // SubBruteWorkerStatusRx, +} SubBruteWorkerStatus; + +//typedef void (*SubBruteWorkerCallback)(SubBruteWorkerStatus event, void* context); +*/ +SubBruteWorker* subbrute_worker_alloc(); +void subbrute_worker_free(SubBruteWorker* instance); +bool subbrute_worker_start( + SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + string_t protocol_name); +void subbrute_worker_stop(SubBruteWorker* instance); +//bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size); +bool subbrute_worker_is_running(SubBruteWorker* instance); +bool subbrute_worker_can_transmit(SubBruteWorker* instance); +bool subbrute_worker_transmit(SubBruteWorker* instance, string_t payload); \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.c b/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.c deleted file mode 100644 index 6f8497b9f..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.c +++ /dev/null @@ -1,197 +0,0 @@ -#include "subbrute_scene_entrypoint.h" -#include "../subbrute_utils.h" - -string_t subbrute_menu_items[10]; - -void subbrute_scene_entrypoint_menu_callback(SubBruteState* context, uint32_t index) { - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - string_set_str(context->protocol, "RAW"); - context->repeat = 5; - context->te = 0; - context->attack = index; - switch(index) { - case SubBruteAttackLoadFile: - context->current_scene = SceneSelectFile; - break; - case SubBruteAttackCAME12bit307: - case SubBruteAttackCAME12bit433: - case SubBruteAttackCAME12bit868: - if(index == SubBruteAttackCAME12bit307) { - context->frequency = 307800000; - } else if(index == SubBruteAttackCAME12bit433) { - context->frequency = 433920000; - } else if(index == SubBruteAttackCAME12bit868) { - context->frequency = 868350000; - } - context->bit = 12; - string_set_str(context->protocol, "CAME"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackChamberlain9bit315: - context->frequency = 315000000; - context->bit = 9; - string_set_str(context->protocol, "Cham_Code"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackChamberlain9bit390: - context->frequency = 390000000; - context->bit = 9; - string_set_str(context->protocol, "Cham_Code"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackLinear10bit300: - context->frequency = 300000000; - context->bit = 10; - string_set_str(context->protocol, "Linear"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackLinear10bit310: - context->frequency = 310000000; - context->bit = 10; - string_set_str(context->protocol, "Linear"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackNICE12bit433: - context->frequency = 433920000; - context->bit = 12; - string_set_str(context->protocol, "Nice FLO"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - case SubBruteAttackNICE12bit868: - context->frequency = 868350000; - context->bit = 12; - string_set_str(context->protocol, "Nice FLO"); - string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); - if(!subbrute_is_frequency_allowed(context)) { - return; - } - context->current_scene = SceneAttack; - break; - default: - break; - } -} - -void subbrute_scene_entrypoint_on_enter(SubBruteState* context) { - // Clear the previous payload - context->menu_index = 0; - for(uint32_t i = 0; i < 10; i++) { - string_init(subbrute_menu_items[i]); - } - - string_set(subbrute_menu_items[0], "BF existing dump"); - string_set(subbrute_menu_items[1], "CAME 12bit 307mhz"); - string_set(subbrute_menu_items[2], "CAME 12bit 433mhz"); - string_set(subbrute_menu_items[3], "CAME 12bit 868mhz"); - string_set(subbrute_menu_items[4], "Chamberlain 9bit 315mhz"); - string_set(subbrute_menu_items[5], "Chamberlain 9bit 390mhz"); - string_set(subbrute_menu_items[6], "Linear 10bit 300mhz"); - string_set(subbrute_menu_items[7], "Linear 10bit 310mhz"); - string_set(subbrute_menu_items[8], "NICE 12bit 433mhz"); - string_set(subbrute_menu_items[9], "NICE 12bit 868mhz"); -} - -void subbrute_scene_entrypoint_on_exit(SubBruteState* context) { - UNUSED(context); - for(uint32_t i = 0; i < 10; i++) { - string_clear(subbrute_menu_items[i]); - } -} - -void subbrute_scene_entrypoint_on_tick(SubBruteState* context) { - UNUSED(context); -} - -void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context) { - if(event.evt_type == EventTypeKey) { - if(event.input_type == InputTypeShort) { - switch(event.key) { - case InputKeyDown: - if(context->menu_index < SubBruteAttackNICE12bit868) { - context->menu_index++; - } - break; - case InputKeyUp: - if(context->menu_index > SubBruteAttackLoadFile) { - context->menu_index--; - } - break; - case InputKeyLeft: - case InputKeyRight: - break; - case InputKeyOk: - subbrute_scene_entrypoint_menu_callback(context, context->menu_index); - break; - case InputKeyBack: - context->is_running = false; - break; - } - } - } -} - -void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // Title - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); - - if(context->menu_index > SubBruteAttackLoadFile) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, - 64, - 24, - AlignCenter, - AlignTop, - string_get_cstr(subbrute_menu_items[context->menu_index - 1])); - } - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - 64, - 36, - AlignCenter, - AlignTop, - string_get_cstr(subbrute_menu_items[context->menu_index])); - - if(context->menu_index < SubBruteAttackNICE12bit868) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, - 64, - 48, - AlignCenter, - AlignTop, - string_get_cstr(subbrute_menu_items[context->menu_index + 1])); - } -} \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.h b/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.h deleted file mode 100644 index af6b3bc49..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_entrypoint.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../subbrute.h" - -void subbrute_scene_entrypoint_on_enter(SubBruteState* context); -void subbrute_scene_entrypoint_on_exit(SubBruteState* context); -void subbrute_scene_entrypoint_on_tick(SubBruteState* context); -void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context); -void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_load_file.c b/applications/plugins/subbrute/scene/subbrute_scene_load_file.c deleted file mode 100644 index e2c99c9cd..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_load_file.c +++ /dev/null @@ -1,222 +0,0 @@ -#include "subbrute_scene_load_file.h" -#include "subbrute_scene_entrypoint.h" -#include "../subbrute_utils.h" -#include - -#define SUBGHZ_APP_PATH_FOLDER "/ext/subghz" - -bool subbrute_load(SubBruteState* context, const char* file_path) { - bool result = false; - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - - string_t temp_str; - string_init(temp_str); - uint32_t temp_data32; - - do { - if(!flipper_format_file_open_existing(fff_data_file, file_path)) { - FURI_LOG_E(TAG, "Error open file %s", file_path); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Error open file"); - break; - } - if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Missing or incorrect header"); - break; - } - // Frequency - if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - FURI_LOG_I(TAG, "Frequency: %d", temp_data32); - context->frequency = temp_data32; - if(!subbrute_is_frequency_allowed(context)) { - break; - } - } else { - FURI_LOG_E(TAG, "Missing or incorrect Frequency"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Missing or incorrect Frequency"); - break; - } - // Preset - if(!flipper_format_read_string(fff_data_file, "Preset", context->preset)) { - FURI_LOG_E(TAG, "Preset FAIL"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Preset FAIL"); - } - // Protocol - if(!flipper_format_read_string(fff_data_file, "Protocol", context->protocol)) { - FURI_LOG_E(TAG, "Missing Protocol"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Missing Protocol"); - break; - } else { - FURI_LOG_I(TAG, "Protocol: %s", string_get_cstr(context->protocol)); - } - - if(strcmp(string_get_cstr(context->protocol), "RAW") == 0) { - FURI_LOG_E(TAG, "RAW unsupported"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "RAW unsupported"); - break; - } - - const SubGhzProtocol* registry = - subghz_protocol_registry_get_by_name(string_get_cstr(context->protocol)); - - if(registry && registry->type == SubGhzProtocolTypeDynamic) { - FURI_LOG_D(TAG, "Protocol is dynamic - not supported"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Dynamic protocol unsupported"); - break; - } - - context->decoder_result = subghz_receiver_search_decoder_base_by_name( - context->receiver, string_get_cstr(context->protocol)); - - if(context->decoder_result) { - FURI_LOG_I(TAG, "Found decoder"); - } else { - FURI_LOG_E(TAG, "Protocol not found"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Protocol not found"); - break; - } - - // Bit - if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) { - FURI_LOG_E(TAG, "Missing or incorrect Bit"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Missing or incorrect Bit"); - break; - } else { - FURI_LOG_I(TAG, "Bit: %d", temp_data32); - context->bit = temp_data32; - } - - // Key - if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { - FURI_LOG_E(TAG, "Missing or incorrect Key"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "Missing or incorrect Key"); - break; - } else { - FURI_LOG_I(TAG, "Key: %s", string_get_cstr(temp_str)); - string_set(context->key, string_get_cstr(temp_str)); - } - - // TE - if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { - FURI_LOG_E(TAG, "Missing or incorrect TE"); - //string_reset(context->notification_msg); - //string_set_str(context->notification_msg, "Missing or incorrect TE"); - //break; - } else { - FURI_LOG_I(TAG, "TE: %d", temp_data32); - context->te = temp_data32; - } - - // Repeat - if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) { - FURI_LOG_I(TAG, "Repeat: %d", temp_data32); - context->repeat = temp_data32; - } else { - FURI_LOG_I(TAG, "Repeat: 3 (default)"); - context->repeat = 3; - } - - result = true; - } while(0); - - string_clear(temp_str); - flipper_format_file_close(fff_data_file); - flipper_format_free(fff_data_file); - furi_record_close(RECORD_STORAGE); - if(result) { - FURI_LOG_I(TAG, "Loaded successfully"); - string_reset(context->notification_msg); - string_set_str(context->notification_msg, "File looks ok."); - } - - return result; -} - -void subbrute_scene_load_file_on_enter(SubBruteState* context) { - if(subbrute_load_protocol_from_file(context)) { - context->current_scene = SceneSelectField; - } else { - subbrute_scene_entrypoint_on_enter(context); - context->current_scene = SceneEntryPoint; - } -} - -void subbrute_scene_load_file_on_exit(SubBruteState* context) { - UNUSED(context); -} - -void subbrute_scene_load_file_on_tick(SubBruteState* context) { - UNUSED(context); -} - -void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context) { - UNUSED(context); - if(event.evt_type == EventTypeKey) { - if(event.input_type == InputTypeShort) { - switch(event.key) { - case InputKeyDown: - case InputKeyUp: - case InputKeyLeft: - case InputKeyRight: - case InputKeyOk: - break; - case InputKeyBack: - context->current_scene = SceneEntryPoint; - break; - } - } - } -} - -void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context) { - UNUSED(context); - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // Frame - //canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Title - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignTop, "SubGHz Fuzzer"); - canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "Error: Press back"); -} - -bool subbrute_load_protocol_from_file(SubBruteState* context) { - string_t file_path; - string_init(file_path); - string_set_str(file_path, SUBGHZ_APP_PATH_FOLDER); - context->environment = subghz_environment_alloc(); - context->receiver = subghz_receiver_alloc_init(context->environment); - subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable); - - // Input events and views are managed by file_select - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); - - bool res = dialog_file_browser_show(context->dialogs, file_path, file_path, &browser_options); - - if(res) { - res = subbrute_load(context, string_get_cstr(file_path)); - } - - subghz_environment_free(context->environment); - subghz_receiver_free(context->receiver); - - string_clear(file_path); - - return res; -} \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_load_file.h b/applications/plugins/subbrute/scene/subbrute_scene_load_file.h deleted file mode 100644 index 9e186b1c9..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_load_file.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "../subbrute.h" - -void subbrute_scene_load_file_on_enter(SubBruteState* context); -void subbrute_scene_load_file_on_exit(SubBruteState* context); -void subbrute_scene_load_file_on_tick(SubBruteState* context); -void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context); -void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context); -bool subbrute_load_protocol_from_file(SubBruteState* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scene/subbrute_scene_run_attack.c deleted file mode 100644 index 4b4507882..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_run_attack.c +++ /dev/null @@ -1,384 +0,0 @@ -#include "subbrute_scene_run_attack.h" -#include -#include - -//uint64_t subbrute_counter = 0; -uint64_t max_value; -bool locked = false; -bool toSave = false; -char subbrute_payload_byte[4]; -#define SUBBRUTE_DELAY 1 - -FuriHalSubGhzPreset str_to_preset(string_t preset) { - if(string_cmp_str(preset, "FuriHalSubGhzPresetOok270Async") == 0) { - return FuriHalSubGhzPresetOok270Async; - } - if(string_cmp_str(preset, "FuriHalSubGhzPresetOok650Async") == 0) { - return FuriHalSubGhzPresetOok650Async; - } - if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev238Async") == 0) { - return FuriHalSubGhzPreset2FSKDev238Async; - } - if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev476Async") == 0) { - return FuriHalSubGhzPreset2FSKDev476Async; - } - if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - return FuriHalSubGhzPresetCustom; -} - -void subbrute_emit(SubBruteState* context) { - //FURI_LOG_D(TAG, string_get_cstr(context->flipper_format_string)); - - context->transmitter = - subghz_transmitter_alloc_init(context->environment, string_get_cstr(context->protocol)); - - subghz_transmitter_deserialize(context->transmitter, context->flipper_format); - furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(str_to_preset(context->preset)); - - context->frequency_cal = furi_hal_subghz_set_frequency_and_path(context->frequency); - - furi_hal_subghz_start_async_tx(subghz_transmitter_yield, context->transmitter); - while(!(furi_hal_subghz_is_async_tx_complete())) { - furi_delay_ms(1); - } - - furi_hal_subghz_stop_async_tx(); - subghz_transmitter_stop(context->transmitter); - furi_hal_subghz_idle(); - subghz_transmitter_free(context->transmitter); -} - -void prepare_emit(SubBruteState* context) { - UNUSED(context); - - furi_hal_subghz_init(); -} - -void clear_emit(SubBruteState* context) { - UNUSED(context); - - //furi_hal_subghz_stop_async_tx(); - //furi_hal_subghz_idle(); - furi_hal_subghz_sleep(); -} -/* -void subbrute_send_raw_packet(SubBruteState* context) { - string_reset(context->candidate); - - // Payload to padded binary string - int* binaryNum = (int*)malloc(sizeof(int) * context->bit); - uint32_t i = 0; - for(i = 0; i < context->bit; i++) { - binaryNum[i] = 0; - } - i = 0; - uint64_t counter = context->payload; - while(counter > 0) { - binaryNum[i] = counter % 2; - counter = counter / 2; - i++; - } - - // printing binary array in reverse order and build raw payload - for(uint32_t loop = 0; loop < context->repeat; loop++) { - for(int j = (int)context->bit - 1; j >= 0; j--) { - if(binaryNum[j] == 1) { - string_cat(context->candidate, context->subbrute_raw_one); - } else { - string_cat(context->candidate, context->subbrute_raw_zero); - } - } - string_cat(context->candidate, context->subbrute_raw_stop); - } - - free(binaryNum); - - string_init_printf( - context->flipper_format_string, - "Filetype: Flipper SubGhz RAW File\n" - "Version: 1\n" - "Frequency: %d\n" - "Preset: %s\n" - "Protocol: RAW\n" - "RAW_Data: %s", - context->frequency, - string_get_cstr(context->preset), - string_get_cstr(context->candidate)); - - subbrute_emit(context); -} -*/ -void subbrute_send_packet_parsed(SubBruteState* context) { - if(context->attack == SubBruteAttackLoadFile) { - snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)context->payload); - string_replace_at(context->candidate, context->str_index, 3, subbrute_payload_byte); - } else { - string_t buffer; - string_init(buffer); - string_init_printf(buffer, "%16X", context->payload); - int j = 0; - string_set_str(context->candidate, " "); - for(uint8_t i = 0; i < 16; i++) { - if(string_get_char(buffer, i) != ' ') { - string_set_char(context->candidate, i + j, string_get_char(buffer, i)); - } else { - string_set_char(context->candidate, i + j, '0'); - } - if(i % 2 != 0) { - j++; - } - } - string_clear(buffer); - } - if(strcmp(string_get_cstr(context->protocol), "Princeton") == 0) { - string_init_printf( - context->flipper_format_string, - "Filetype: Flipper SubGhz Key File\n" - "Version: 1\n" - "Frequency: %u\n" - "Preset: %s\n" - "Protocol: %s\n" - "Bit: %d\n" - "Key: %s\n" - "TE: %d\n", - context->frequency, - string_get_cstr(context->preset), - string_get_cstr(context->protocol), - context->bit, - string_get_cstr(context->candidate), - context->te); - } else { - string_init_printf( - context->flipper_format_string, - "Filetype: Flipper SubGhz Key File\n" - "Version: 1\n" - "Frequency: %u\n" - "Preset: %s\n" - "Protocol: %s\n" - "Bit: %d\n" - "Key: %s\n", - context->frequency, - string_get_cstr(context->preset), - string_get_cstr(context->protocol), - context->bit, - string_get_cstr(context->candidate)); - } - - stream_clean(context->stream); - stream_write_string(context->stream, context->flipper_format_string); -} - -void subbrute_send_packet(SubBruteState* context) { - ///if(string_cmp_str(context->protocol, "RAW") == 0) { - // subbrute_send_raw_packet(context); - //} else { - subbrute_send_packet_parsed(context); - subbrute_emit(context); - //} - string_clear(context->flipper_format_string); -} - -void subbrute_scene_run_attack_on_exit(SubBruteState* context) { - if(!toSave) { - clear_emit(context); - furi_thread_free(context->bruthread); - flipper_format_free(context->flipper_format); - subghz_receiver_free(context->receiver); - subghz_environment_free(context->environment); - } -} - -void subbrute_scene_run_attack_on_tick(SubBruteState* context) { - if(!context->is_attacking || locked) { - return; - } - //if(0 != subbrute_counter) { - locked = true; - subbrute_send_packet(context); - - if(context->payload == max_value) { - //context->payload = 0x00; - //subbrute_counter = 0; - context->is_attacking = false; - notification_message(context->notify, &sequence_blink_stop); - notification_message(context->notify, &sequence_single_vibro); - } else { - context->payload++; - } - locked = false; - //} - /*if(subbrute_counter > SUBBRUTE_DELAY) { - subbrute_counter = 0; - } else { - subbrute_counter++; - }*/ -} -void subbrute_run_timer(SubBruteState* context) { - while(true) { - if(!context->is_attacking) { - context->is_thread_running = false; - break; - } - //furi_delay_ms(10); - subbrute_scene_run_attack_on_tick(context); - } -} - -// entrypoint for worker -static int32_t subbrute_worker_thread(void* ctx) { - SubBruteState* app = ctx; - subbrute_run_timer(app); - return 0; -} - -void start_bruthread(SubBruteState* app) { - if(!app->is_thread_running) { - furi_thread_start(app->bruthread); - app->is_thread_running = true; - } -} - -void subbrute_scene_run_attack_on_enter(SubBruteState* context) { - if(!toSave) { - if(context->attack == SubBruteAttackLoadFile) { - max_value = 0xFF; - } else { - string_t max_value_s; - string_init(max_value_s); - for(uint8_t i = 0; i < context->bit; i++) { - string_cat_printf(max_value_s, "1"); - } - max_value = (uint64_t)strtol(string_get_cstr(max_value_s), NULL, 2); - string_clear(max_value_s); - } - context->str_index = (context->key_index * 3); - string_init_set(context->candidate, context->key); - context->flipper_format = flipper_format_string_alloc(); - context->stream = flipper_format_get_raw_stream(context->flipper_format); - context->environment = subghz_environment_alloc(); - context->receiver = subghz_receiver_alloc_init(context->environment); - subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable); - - prepare_emit(context); - context->bruthread = furi_thread_alloc(); - furi_thread_set_name(context->bruthread, "SubBrute Worker"); - furi_thread_set_stack_size(context->bruthread, 2048); - furi_thread_set_context(context->bruthread, context); - furi_thread_set_callback(context->bruthread, subbrute_worker_thread); - } else { - toSave = false; - } -} - -void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context) { - if(event.evt_type == EventTypeKey) { - if(event.input_type == InputTypeShort) { - switch(event.key) { - case InputKeyDown: - break; - case InputKeyUp: - if(!context->is_attacking) { - subbrute_send_packet_parsed(context); - string_clear(context->flipper_format_string); - toSave = true; - context->current_scene = SceneSaveName; - } - break; - case InputKeyLeft: - if(!context->is_attacking && context->payload > 0x00) { - context->payload--; - subbrute_send_packet(context); - notification_message(context->notify, &sequence_blink_blue_10); - } else if(!context->is_attacking && context->payload == 0x00) { - context->payload = max_value; - subbrute_send_packet(context); - notification_message(context->notify, &sequence_blink_blue_10); - } - break; - case InputKeyRight: - if(!context->is_attacking && context->payload < max_value) { - context->payload++; - subbrute_send_packet(context); - notification_message(context->notify, &sequence_blink_blue_10); - } else if(!context->is_attacking && context->payload == max_value) { - context->payload = 0x00; - subbrute_send_packet(context); - notification_message(context->notify, &sequence_blink_blue_10); - } - break; - case InputKeyOk: - if(!context->is_attacking) { - if(context->payload == max_value) { - context->payload = 0x00; - //subbrute_counter = 0; - } - context->is_attacking = true; - start_bruthread(context); - notification_message(context->notify, &sequence_blink_start_blue); - } else { - context->is_attacking = false; - //context->close_thread_please = true; - if(context->is_thread_running && context->bruthread) { - furi_thread_join(context->bruthread); // wait until thread is finished - } - //context->close_thread_please = false; - notification_message(context->notify, &sequence_blink_stop); - notification_message(context->notify, &sequence_single_vibro); - } - break; - case InputKeyBack: - locked = false; - //context->close_thread_please = true; - context->is_attacking = false; - if(context->is_thread_running && context->bruthread) { - furi_thread_join(context->bruthread); // wait until thread is finished - } - //context->close_thread_please = false; - string_reset(context->notification_msg); - context->payload = 0x00; - //subbrute_counter = 0; - notification_message(context->notify, &sequence_blink_stop); - if(context->attack == SubBruteAttackLoadFile) { - context->current_scene = SceneSelectField; - } else { - context->current_scene = SceneEntryPoint; - } - break; - } - } - } -} - -void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // Frame - //canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Title - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignTop, "Fire in the hole!"); - - char msg_index[26]; - snprintf( - msg_index, sizeof(msg_index), "< %04d / %04d >", (int)context->payload, (int)max_value); - - canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, msg_index); - - canvas_set_font(canvas, FontSecondary); - char start_stop_msg[20]; - snprintf(start_stop_msg, sizeof(start_stop_msg), " Press (^) to save "); - if(context->is_attacking) { - elements_button_center(canvas, "Stop"); - } else { - elements_button_center(canvas, "Start"); - } - canvas_draw_str_aligned(canvas, 64, 39, AlignCenter, AlignTop, start_stop_msg); -} diff --git a/applications/plugins/subbrute/scene/subbrute_scene_run_attack.h b/applications/plugins/subbrute/scene/subbrute_scene_run_attack.h deleted file mode 100644 index 1eb9637d0..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_run_attack.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "../subbrute.h" - -void subbrute_scene_run_attack_on_enter(SubBruteState* context); -void subbrute_scene_run_attack_on_exit(SubBruteState* context); -void subbrute_scene_run_attack_on_tick(SubBruteState* context); -void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context); -void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context); -void send_packet(); \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_save_name.c b/applications/plugins/subbrute/scene/subbrute_scene_save_name.c deleted file mode 100644 index e79cf70ed..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_save_name.c +++ /dev/null @@ -1,222 +0,0 @@ -#include "../subbrute.h" -#include "m-string.h" -#include "subghz/types.h" -#include -#include -#include - -#define MAX_TEXT_INPUT_LEN 22 - -bool backpressed = false; - -bool subbrute_path_is_file(string_t path) { - return string_end_with_str_p(path, ".sub"); -} -// method modified from subghz_i.c -// https://github.com/flipperdevices/flipperzero-firmware/blob/b0daa601ad5b87427a45f9089c8b403a01f72c2a/applications/subghz/subghz_i.c#L417-L456 -bool subbrute_save_protocol_to_file(Stream* flipper_format_stream, const char* dev_file_name) { - furi_assert(dev_file_name); - - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool saved = false; - string_t file_dir; - string_init(file_dir); - - path_extract_dirname(dev_file_name, file_dir); - do { - if(!storage_simply_mkdir(storage, string_get_cstr(file_dir))) { - FURI_LOG_E(TAG, "(save) Cannot mkdir"); - break; - } - - if(!storage_simply_remove(storage, dev_file_name)) { - FURI_LOG_E(TAG, "(save) Cannot remove"); - break; - } - - stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); - - saved = true; - FURI_LOG_D(TAG, "(save) OK Save"); - } while(0); - string_clear(file_dir); - furi_record_close(RECORD_STORAGE); - return saved; -} - -void custom_callback(SubBruteState* context) { - if(strcmp(context->file_name_tmp, "")) { - string_cat_printf(context->file_path, "/%s%s", context->file_name_tmp, ".sub"); - if(subbrute_path_is_file(context->file_path_tmp)) { - context->current_scene = SceneAttack; - return; //false; - - } else { - subbrute_save_protocol_to_file(context->stream, string_get_cstr(context->file_path)); - } - - string_set_str(context->file_path, EXT_PATH("subghz")); - string_reset(context->file_path_tmp); - - //scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); - context->current_scene = SceneAttack; - return; //true; - } else { - //error no file name - context->current_scene = SceneAttack; - return; //true; - } -} - -void subbrute_scene_save_name_text_input_callback(void* context) { - furi_assert(context); - SubBruteState* statee = context; - custom_callback(statee); -} - -void subbrute_scene_save_name_on_tick(SubBruteState* context) { - if(backpressed) { - void* validator_context = text_input_get_validator_callback_context(context->text_input); - text_input_set_validator(context->text_input, NULL, NULL); - validator_is_file_free(validator_context); - - // Clear view - text_input_reset(context->text_input); - - // TextInput - view_dispatcher_remove_view(context->view_dispatcher, 0); - text_input_free(context->text_input); - - // Popup - view_dispatcher_remove_view(context->view_dispatcher, 1); - popup_free(context->popup); - - context->current_scene = SceneAttack; - } -} - -bool subbrute_back_event_callback(void* context) { - UNUSED(context); - backpressed = true; - return true; -} - -void subbrute_scene_save_name_on_enter(SubBruteState* context) { - // Text Input - context->text_input = text_input_alloc(); - view_dispatcher_add_view( - context->view_dispatcher, 0, text_input_get_view(context->text_input)); - - // Popup - context->popup = popup_alloc(); - view_dispatcher_add_view(context->view_dispatcher, 1, popup_get_view(context->popup)); - - // Setup view - TextInput* text_input = context->text_input; - bool dev_name_empty = false; - - string_t file_name; - string_t dir_name; - string_init(file_name); - string_init(dir_name); - - if(!subbrute_path_is_file(context->file_path)) { - char file_name_buf[64] = {0}; - set_random_name(file_name_buf, 64); - string_set_str(file_name, file_name_buf); - string_set_str(context->file_path, EXT_PATH("subghz")); - //highlighting the entire filename by default - dev_name_empty = true; - } else { - string_set(context->file_path_tmp, context->file_path); - path_extract_dirname(string_get_cstr(context->file_path), dir_name); - path_extract_filename(context->file_path, file_name, true); - string_set(context->file_path, dir_name); - } - - strncpy(context->file_name_tmp, string_get_cstr(file_name), 64); - text_input_set_header_text(text_input, "Name signal"); - text_input_set_result_callback( - text_input, - subbrute_scene_save_name_text_input_callback, - context, - context->file_name_tmp, - MAX_TEXT_INPUT_LEN, // buffer size - dev_name_empty); - - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(string_get_cstr(context->file_path), ".sub", ""); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - string_clear(file_name); - string_clear(dir_name); - - view_dispatcher_set_navigation_event_callback( - context->view_dispatcher, subbrute_back_event_callback); - - view_dispatcher_switch_to_view(context->view_dispatcher, 0); -} - -void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context) { - UNUSED(context); - if(event.evt_type == EventTypeKey) { - if(event.input_type == InputTypeShort) { - switch(event.key) { - case InputKeyDown: - case InputKeyUp: - case InputKeyLeft: - case InputKeyRight: - case InputKeyOk: - break; - case InputKeyBack: - //context->current_scene = SceneAttack; - break; - } - } - } -} - -void subbrute_scene_save_name_on_exit(SubBruteState* context) { - if(!backpressed) { - // Clear validator - void* validator_context = text_input_get_validator_callback_context(context->text_input); - text_input_set_validator(context->text_input, NULL, NULL); - validator_is_file_free(validator_context); - - // Clear view - text_input_reset(context->text_input); - - // Setup view - Popup* popup = context->popup; - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); - popup_set_timeout(popup, 1500); - popup_set_context(popup, context); - popup_set_callback(popup, NULL); - popup_enable_timeout(popup); - view_dispatcher_switch_to_view(context->view_dispatcher, 1); - - furi_delay_ms(1050); - // Clear view - //Popup* popup = subghz->popup; - popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); - popup_set_icon(popup, 0, 0, NULL); - popup_set_callback(popup, NULL); - popup_set_context(popup, NULL); - popup_set_timeout(popup, 0); - popup_disable_timeout(popup); - - // TextInput - view_dispatcher_remove_view(context->view_dispatcher, 0); - text_input_free(context->text_input); - - // Popup - view_dispatcher_remove_view(context->view_dispatcher, 1); - popup_free(context->popup); - } else { - backpressed = false; - } -} \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_save_name.h b/applications/plugins/subbrute/scene/subbrute_scene_save_name.h deleted file mode 100644 index 18a931ad8..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_save_name.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "../subbrute.h" - -void subbrute_scene_save_name_on_enter(SubBruteState* context); -void subbrute_scene_save_name_on_exit(SubBruteState* context); -void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context); -void subbrute_scene_save_name_on_tick(SubBruteState* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/scene/subbrute_scene_select_field.c b/applications/plugins/subbrute/scene/subbrute_scene_select_field.c deleted file mode 100644 index c65cd1663..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_select_field.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "subbrute_scene_select_field.h" - -void center_displayed_key(SubBruteState* context, uint8_t index) { - const char* key_cstr = string_get_cstr(context->key); - uint8_t str_index = (index * 3); - - char display_menu[17] = { - 'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'}; - - if(index > 1) { - display_menu[0] = key_cstr[str_index - 6]; - display_menu[1] = key_cstr[str_index - 5]; - } else { - display_menu[0] = ' '; - display_menu[1] = ' '; - } - - if(index > 0) { - display_menu[3] = key_cstr[str_index - 3]; - display_menu[4] = key_cstr[str_index - 2]; - } else { - display_menu[3] = ' '; - display_menu[4] = ' '; - } - - display_menu[7] = key_cstr[str_index]; - display_menu[8] = key_cstr[str_index + 1]; - - if((str_index + 4) <= (uint8_t)strlen(key_cstr)) { - display_menu[11] = key_cstr[str_index + 3]; - display_menu[12] = key_cstr[str_index + 4]; - } else { - display_menu[11] = ' '; - display_menu[12] = ' '; - } - - if((str_index + 8) <= (uint8_t)strlen(key_cstr)) { - display_menu[14] = key_cstr[str_index + 6]; - display_menu[15] = key_cstr[str_index + 7]; - } else { - display_menu[14] = ' '; - display_menu[15] = ' '; - } - - string_reset(context->notification_msg); - string_set_str(context->notification_msg, display_menu); -} - -void subbrute_scene_select_field_on_enter(SubBruteState* context) { - string_clear(context->notification_msg); -} - -void subbrute_scene_select_field_on_exit(SubBruteState* context) { - UNUSED(context); -} - -void subbrute_scene_select_field_on_tick(SubBruteState* context) { - UNUSED(context); -} - -void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context) { - if(event.evt_type == EventTypeKey) { - if(event.input_type == InputTypeShort) { - //const char* key_cstr = string_get_cstr(context->key); - - // don't look, it's ugly but I'm a python dev so... - /*uint8_t nb_bytes = 0; - for(uint8_t i = 0; i < strlen(key_cstr); i++) { - if(' ' == key_cstr[i]) { - nb_bytes++; - } - }*/ - - switch(event.key) { - case InputKeyDown: - case InputKeyUp: - break; - case InputKeyLeft: - if(context->key_index > 0) { - context->key_index--; - } - break; - case InputKeyRight: - if(context->key_index < 7) { - context->key_index++; - } - break; - case InputKeyOk: - string_reset(context->notification_msg); - context->current_scene = SceneAttack; - break; - case InputKeyBack: - string_reset(context->notification_msg); - context->current_scene = SceneSelectFile; - break; - } - //FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes); - } - } -} - -void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // Frame - //canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Title - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "use < > to select field"); - - char msg_index[18]; - snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index); - canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index); - - center_displayed_key(context, context->key_index); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg)); -} diff --git a/applications/plugins/subbrute/scene/subbrute_scene_select_field.h b/applications/plugins/subbrute/scene/subbrute_scene_select_field.h deleted file mode 100644 index e02a07ee0..000000000 --- a/applications/plugins/subbrute/scene/subbrute_scene_select_field.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "../subbrute.h" - -void subbrute_scene_select_field_on_enter(SubBruteState* context); -void subbrute_scene_select_field_on_exit(SubBruteState* context); -void subbrute_scene_select_field_on_tick(SubBruteState* context); -void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context); -void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context); -void center_displayed_key(SubBruteState* context, uint8_t index); \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene.h b/applications/plugins/subbrute/scenes/subbrute_scene.h new file mode 100644 index 000000000..c048985e2 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) SubBruteScene##id, +typedef enum { +#include "subbrute_scene_config.h" + SubBruteSceneNum, +} SubBruteScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers subbrute_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "subbrute_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "subbrute_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "subbrute_scene_config.h" +#undef ADD_SCENE diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_config.h b/applications/plugins/subbrute/scenes/subbrute_scene_config.h new file mode 100644 index 000000000..40806279f --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_config.h @@ -0,0 +1,6 @@ +ADD_SCENE(subbrute, load_file, LoadFile) +ADD_SCENE(subbrute, run_attack, RunAttack) +ADD_SCENE(subbrute, save_name, SaveName) +ADD_SCENE(subbrute, save_success, SaveSuccess) +ADD_SCENE(subbrute, setup_attack, SetupAttack) +ADD_SCENE(subbrute, start, Start) \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c new file mode 100644 index 000000000..0fecb5b6e --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c @@ -0,0 +1,61 @@ +#include +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_main_view.h" + +//void subbrute_scene_load_file_callback(SubBruteCustomEvent event, void* context) { +//// furi_assert(context); +//// +//// SubBruteState* instance = (SubBruteState*)context; +//// view_dispatcher_send_custom_event(instance->view_dispatcher, event); +//} + +void subbrute_scene_load_file_on_enter(void* context) { + furi_assert(context); + SubBruteState* instance = (SubBruteState*)context; + string_t file_path; + string_init(file_path); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px); + + // Input events and views are managed by file_select + bool res = dialog_file_browser_show( + instance->dialogs, + instance->device->load_path, + instance->device->load_path, + &browser_options); + + if(res) { + SubBruteFileResult load_result = subbrute_device_load_protocol_from_file(instance->device); + if(load_result == SubBruteFileResultOk) { + scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneSetupAttack); + } else { + string_t dialog_msg; + string_init(dialog_msg); + string_cat_printf( + dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result)); + dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg)); + string_clear(dialog_msg); + res = false; + } + } + + string_clear(file_path); + + if(!res) { + scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneLoadFile); + } +} + +void subbrute_scene_load_file_on_exit(void* context) { + UNUSED(context); +} + +bool subbrute_scene_load_file_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c new file mode 100644 index 000000000..59c5b8ef0 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -0,0 +1,158 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_attack_view.h" + +static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + view_dispatcher_send_custom_event(instance->view_dispatcher, event); +} + +void subbrute_scene_run_attack_on_exit(void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + notification_message(instance->notifications, &sequence_blink_stop); +} + +void subbrute_scene_run_attack_on_enter(void* context) { + furi_assert(context); + SubBruteState* instance = (SubBruteState*)context; + SubBruteAttackView* view = instance->view_attack; + + instance->current_view = SubBruteViewAttack; + subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance); + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); + + subbrute_attack_view_init_values( + view, + (uint8_t)instance->device->attack, + instance->device->max_value, + instance->device->key_index); + + // Start worker if not started + subbrute_attack_view_start_worker( + view, + instance->device->frequency, + instance->device->preset, + instance->device->protocol_name); +} + +bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + SubBruteAttackView* view = instance->view_attack; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubBruteCustomEventTypeTransmitNotStarted || + event.event == SubBruteCustomEventTypeTransmitFinished || + event.event == SubBruteCustomEventTypeBackPressed) { + // Stop transmit + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeTick) { + if(subbrute_attack_view_can_send(view)) { + // Blink + notification_message(instance->notifications, &sequence_blink_yellow_100); + + if(subbrute_attack_view_transmit(view, instance->device->payload)) { + // Make payload for new iteration or exit + if(instance->device->key_index + 1 > instance->device->max_value) { + // End of list + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + } else { + instance->device->key_index++; + subbrute_attack_view_set_current_step(view, instance->device->key_index); + subbrute_device_create_packet_parsed( + instance->device, instance->device->key_index); + } + } + + // Stop + notification_message(instance->notifications, &sequence_blink_stop); + } + + consumed = true; + } + + return consumed; + + // if(event.evt_type == EventTypeKey) { + // if(event.input_type == InputTypeShort) { + // switch(event.key) { + // case InputKeyDown: + // break; + // case InputKeyUp: + // if(!context->is_attacking) { + // subbrute_send_packet_parsed(context); + // string_clear(context->flipper_format_string); + // toSave = true; + // context->current_scene = SceneSaveName; + // } + // break; + // case InputKeyLeft: + // if(!context->is_attacking && context->payload > 0x00) { + // context->payload--; + // subbrute_send_packet(context); + // notification_message(context->notify, &sequence_blink_blue_10); + // } else if(!context->is_attacking && context->payload == 0x00) { + // context->payload = max_value; + // subbrute_send_packet(context); + // notification_message(context->notify, &sequence_blink_blue_10); + // } + // break; + // case InputKeyRight: + // if(!context->is_attacking && context->payload < max_value) { + // context->payload++; + // subbrute_send_packet(context); + // notification_message(context->notify, &sequence_blink_blue_10); + // } else if(!context->is_attacking && context->payload == max_value) { + // context->payload = 0x00; + // subbrute_send_packet(context); + // notification_message(context->notify, &sequence_blink_blue_10); + // } + // break; + // case InputKeyOk: + // if(!context->is_attacking) { + // if(context->payload == max_value) { + // context->payload = 0x00; + // //subbrute_counter = 0; + // } + // context->is_attacking = true; + // start_bruthread(context); + // notification_message(context->notify, &sequence_blink_start_blue); + // } else { + // context->is_attacking = false; + // //context->close_thread_please = true; + // if(context->is_thread_running && context->bruthread) { + // furi_thread_join(context->bruthread); // wait until thread is finished + // } + // //context->close_thread_please = false; + // notification_message(context->notify, &sequence_blink_stop); + // notification_message(context->notify, &sequence_single_vibro); + // } + // break; + // case InputKeyBack: + // locked = false; + // //context->close_thread_please = true; + // context->is_attacking = false; + // if(context->is_thread_running && context->bruthread) { + // furi_thread_join(context->bruthread); // wait until thread is finished + // } + // //context->close_thread_please = false; + // string_reset(context->notification_msg); + // context->payload = 0x00; + // //subbrute_counter = 0; + // notification_message(context->notify, &sequence_blink_stop); + // if(context->attack == SubBruteAttackLoadFile) { + // context->current_scene = SceneSelectField; + // } else { + // context->current_scene = SceneEntryPoint; + // } + // break; + // } + // } + // } +} diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c new file mode 100644 index 000000000..0400bbe5a --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_attack_view.h" + +#define TAG "SubBruteSceneSaveFile" + +void subbrute_scene_save_name_on_enter(void* context) { + SubBruteState* instance = (SubBruteState*)context; + + // Setup view + TextInput* text_input = instance->text_input; + set_random_name(instance->device->text_store, sizeof(instance->device->text_store)); + + text_input_set_header_text(text_input, "Name of file"); + text_input_set_result_callback( + text_input, + subbrute_text_input_callback, + instance, + instance->device->text_store, + SUBBRUTE_MAX_LEN_NAME, + true); + + string_t folder_path; + string_init(folder_path); + + SubBruteDevice* device = instance->device; + if(string_end_with_str_p(device->load_path, SUBBRUTE_FILE_EXT)) { + path_extract_dirname(string_get_cstr(device->load_path), folder_path); + } else { + string_set_str(folder_path, SUBBRUTE_PATH); + } + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(string_get_cstr(folder_path), SUBBRUTE_FILE_EXT, TAG); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewTextInput); + + string_clear(folder_path); +} + +bool subbrute_scene_save_name_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom && + event.event == SubBruteCustomEventTypeTextEditDone) { + if(subbrute_device_save_file(instance->device, instance->device->text_store)) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveSuccess); + consumed = true; + } else { + dialog_message_show_storage_error(instance->dialogs, "Error during saving!"); + consumed = scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneSetupAttack); + } + } + return consumed; +} + +void subbrute_scene_save_name_on_exit(void* context) { + SubBruteState* instance = (SubBruteState*)context; + + // Clear view + void* validator_context = text_input_get_validator_callback_context(instance->text_input); + text_input_set_validator(instance->text_input, NULL, NULL); + validator_is_file_free(validator_context); + + text_input_reset(instance->text_input); +} diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c new file mode 100644 index 000000000..5f12c23c6 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c @@ -0,0 +1,59 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_attack_view.h" + +void subbrute_scene_save_success_callback(void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeSaveSuccess); +} + +void subbrute_scene_save_success_on_enter(void* context) { + furi_assert(context); + SubBruteState* instance = context; + + // Setup view + Popup* popup = instance->popup; + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, instance); + popup_set_callback(popup, subbrute_scene_save_success_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewPopup); +} + +bool subbrute_scene_save_success_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + //SubBruteMainView* view = instance->view_main; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubBruteCustomEventTypeSaveSuccess) { + if(!scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneSetupAttack)) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); + } + return true; + } + } + return false; +} + +void subbrute_scene_save_success_on_exit(void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + + // Clear view + Popup* popup = instance->popup; + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + popup_set_callback(popup, NULL); + popup_set_context(popup, NULL); + popup_set_timeout(popup, 0); + popup_disable_timeout(popup); +} diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c new file mode 100644 index 000000000..cc764b6ec --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -0,0 +1,96 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_attack_view.h" + +static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + view_dispatcher_send_custom_event(instance->view_dispatcher, event); +} + +void subbrute_scene_setup_attack_on_enter(void* context) { + furi_assert(context); + SubBruteState* instance = (SubBruteState*)context; + SubBruteAttackView* view = instance->view_attack; + + instance->current_view = SubBruteViewAttack; + subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); + + instance->device->key_index = subbrute_attack_view_get_current_step(view); + subbrute_attack_view_init_values( + view, + (uint8_t)instance->device->attack, + instance->device->max_value, + instance->device->key_index); + + // Run worker anyway + subbrute_attack_view_start_worker( + view, + instance->device->frequency, + instance->device->preset, + instance->device->protocol_name); +} + +void subbrute_scene_setup_attack_on_exit(void* context) { + furi_assert(context); + SubBruteState* instance = (SubBruteState*)context; + notification_message(instance->notifications, &sequence_blink_stop); +} + +bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + SubBruteAttackView * view = instance->view_attack; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubBruteCustomEventTypeTransmitStarted) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); + } else if (event.event == SubBruteCustomEventTypeBackPressed) { + subbrute_attack_view_stop_worker(view); + scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); + } else if (event.event == SubBruteCustomEventTypeChangeStep) { + instance->device->key_index = subbrute_attack_view_get_current_step(view); + } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { + if(subbrute_attack_view_can_send(view)) { + // Blink + notification_message(instance->notifications, &sequence_blink_green_100); + + subbrute_device_create_packet_parsed( + instance->device, instance->device->key_index); + subbrute_attack_view_transmit(view, instance->device->payload); + + // Stop + notification_message(instance->notifications, &sequence_blink_stop); + } + } + + consumed = true; + } + + // if(event.type == SceneManagerEventTypeCustom) { + // switch(event.event) { + // case SubBruteCustomEventTypeMenuSelected: + // with_view_model( + // view, (SubBruteMainViewModel * model) { + // instance->menu_index = model->index; + // return false; + // }); + // scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); + // consumed = true; + // break; + // case SubBruteCustomEventTypeLoadFile: + // with_view_model( + // view, (SubBruteMainViewModel * model) { + // instance->menu_index = model->index; + // return false; + // }); + // scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + // consumed = true; + // break; + // } + // } + + return consumed; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c new file mode 100644 index 000000000..ffc976c61 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -0,0 +1,50 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_main_view.h" + +void subbrute_scene_start_callback(SubBruteCustomEvent event, void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + view_dispatcher_send_custom_event(instance->view_dispatcher, event); +} + +void subbrute_scene_start_on_enter(void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + SubBruteMainView* view = instance->view_main; + + instance->current_view = SubBruteViewMain; + subbrute_main_view_set_callback(view, + subbrute_scene_start_callback, + instance); + + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); + subbrute_main_view_set_index(view, (uint8_t)instance->device->attack); +} + +void subbrute_scene_start_on_exit(void* context) { + UNUSED(context); +} + +bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom && event.event == SubBruteCustomEventTypeMenuSelected) { + //subbrute_device_attack_set + SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main); + + if (attack == SubBruteAttackLoadFile) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); + } else { + subbrute_device_attack_set(instance->device, attack, NULL); + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + } + + consumed = true; + } + + return consumed; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbute_scene.c b/applications/plugins/subbrute/scenes/subbute_scene.c new file mode 100644 index 000000000..6d9ba9799 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbute_scene.c @@ -0,0 +1,30 @@ +#include "subbrute_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const subbrute_on_enter_handlers[])(void*) = { +#include "subbrute_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const subbrute_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "subbrute_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const subbrute_on_exit_handlers[])(void* context) = { +#include "subbrute_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers subbrute_scene_handlers = { + .on_enter_handlers = subbrute_on_enter_handlers, + .on_event_handlers = subbrute_on_event_handlers, + .on_exit_handlers = subbrute_on_exit_handlers, + .scene_num = SubBruteSceneNum, +}; diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index e8f447c5e..e2f19916a 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -1,267 +1,239 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include "subbrute.h" +#include "subbrute_i.h" +#include "subbrute_custom_event.h" -#include "scene/subbrute_scene_load_file.h" -#include "scene/subbrute_scene_select_field.h" -#include "scene/subbrute_scene_run_attack.h" -#include "scene/subbrute_scene_entrypoint.h" -#include "scene/subbrute_scene_save_name.h" +#define TAG "SubBruteApp" -static void draw_callback(Canvas* const canvas, void* ctx) { - SubBruteState* subbrute_state = (SubBruteState*)acquire_mutex((ValueMutex*)ctx, 100); +static const char* subbrute_menu_names[] = { + [SubBruteAttackNone] = "None", + [SubBruteAttackCAME12bit307] = "CAME 12bit 307mhz", + [SubBruteAttackCAME12bit433] = "CAME 12bit 433mhz", + [SubBruteAttackCAME12bit868] = "CAME 12bit 868mhz", + [SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315mhz", + [SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390mhz", + [SubBruteAttackLinear10bit300] = "Linear 10bit 300mhz", + [SubBruteAttackLinear10bit310] = "Linear 10bit 310mhz", + [SubBruteAttackNICE12bit433] = "NICE 12bit 433mhz", + [SubBruteAttackNICE12bit868] = "NICE 12bit 868mhz", + [SubBruteAttackLoadFile] = "BF existing dump", + [SubBruteAttackTotalCount] = "Total Count", +}; - if(subbrute_state == NULL) { - return; - } - - // Draw correct Canvas - switch(subbrute_state->current_scene) { - case NoneScene: - case SceneSelectFile: - subbrute_scene_load_file_on_draw(canvas, subbrute_state); - break; - case SceneSelectField: - subbrute_scene_select_field_on_draw(canvas, subbrute_state); - break; - case SceneAttack: - subbrute_scene_run_attack_on_draw(canvas, subbrute_state); - break; - case SceneEntryPoint: - subbrute_scene_entrypoint_on_draw(canvas, subbrute_state); - break; - case SceneSaveName: - break; - } - - release_mutex((ValueMutex*)ctx, subbrute_state); +bool subbrute_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + SubBruteState* instance = context; + return scene_manager_handle_custom_event(instance->scene_manager, event); } -void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SubBruteEvent event = { - .evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type}; - furi_message_queue_put(event_queue, &event, 100); +bool subbrute_back_event_callback(void* context) { + furi_assert(context); + SubBruteState* instance = context; + return scene_manager_handle_back_event(instance->scene_manager); } -static void timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - SubBruteEvent event = { - .evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease}; - furi_message_queue_put(event_queue, &event, 100); +void subbrute_tick_event_callback(void* context) { + furi_assert(context); + SubBruteState* instance = context; + scene_manager_handle_tick_event(instance->scene_manager); } SubBruteState* subbrute_alloc() { - SubBruteState* subbrute = malloc(sizeof(SubBruteState)); + SubBruteState* instance = malloc(sizeof(SubBruteState)); - string_init(subbrute->protocol); - string_init(subbrute->preset); - string_init(subbrute->file_path); - string_init(subbrute->file_path_tmp); - string_init_set(subbrute->notification_msg, ""); - string_init(subbrute->candidate); - string_init(subbrute->flipper_format_string); + instance->scene_manager = scene_manager_alloc(&subbrute_scene_handlers, instance); + instance->view_dispatcher = view_dispatcher_alloc(); - subbrute->previous_scene = NoneScene; - subbrute->current_scene = SceneSelectFile; - subbrute->is_running = true; - subbrute->is_attacking = false; - subbrute->key_index = 7; - subbrute->notify = furi_record_open(RECORD_NOTIFICATION); + view_dispatcher_enable_queue(instance->view_dispatcher); + view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance); + view_dispatcher_set_custom_event_callback( + instance->view_dispatcher, subbrute_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + instance->view_dispatcher, subbrute_back_event_callback); + view_dispatcher_set_tick_event_callback( + instance->view_dispatcher, subbrute_tick_event_callback, 100); - subbrute->view_dispatcher = view_dispatcher_alloc(); + // Devices + instance->device = subbrute_device_alloc(); + + instance->gui = furi_record_open(RECORD_GUI); + instance->dialogs = furi_record_open(RECORD_DIALOGS); + instance->notifications = furi_record_open(RECORD_NOTIFICATION); + instance->view_dispatcher = view_dispatcher_alloc(); //Dialog - subbrute->dialogs = furi_record_open(RECORD_DIALOGS); + instance->dialogs = furi_record_open(RECORD_DIALOGS); - subbrute->preset_def = malloc(sizeof(SubGhzPresetDefinition)); + // TextInput + instance->text_input = text_input_alloc(); + view_dispatcher_add_view( + instance->view_dispatcher, SubBruteViewTextInput, text_input_get_view(instance->text_input)); + + // Custom Widget + instance->widget = widget_alloc(); + view_dispatcher_add_view( + instance->view_dispatcher, SubBruteViewWidget, widget_get_view(instance->widget)); - //subbrute->flipper_format = flipper_format_string_alloc(); - //subbrute->environment = subghz_environment_alloc(); + // Popup + instance->popup = popup_alloc(); + view_dispatcher_add_view(instance->view_dispatcher, SubBruteViewPopup, popup_get_view(instance->popup)); - return subbrute; + // ViewStack + instance->view_stack = view_stack_alloc(); + view_dispatcher_add_view( + instance->view_dispatcher, SubBruteViewStack, view_stack_get_view(instance->view_stack)); + + // SubBruteMainView + instance->view_main = subbrute_main_view_alloc(); + view_dispatcher_add_view( + instance->view_dispatcher, + SubBruteViewMain, + subbrute_main_view_get_view(instance->view_main)); + + // SubBruteAttackView + instance->view_attack = subbrute_attack_view_alloc(); + view_dispatcher_add_view( + instance->view_dispatcher, + SubBruteViewAttack, + subbrute_attack_view_get_view(instance->view_attack)); + + // Loading + instance->loading = loading_alloc(); + //instance->flipper_format = flipper_format_string_alloc(); + //instance->environment = subghz_environment_alloc(); + + return instance; } -void subbrute_free(SubBruteState* subbrute) { +void subbrute_free(SubBruteState* instance) { + furi_assert(instance); + + // Notifications + notification_message(instance->notifications, &sequence_blink_stop); + furi_record_close(RECORD_NOTIFICATION); + instance->notifications = NULL; + + // Loading + loading_free(instance->loading); + + // View Main + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewMain); + subbrute_main_view_free(instance->view_main); + + // View Attack + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewAttack); + subbrute_attack_view_free(instance->view_attack); + + // TextInput + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewTextInput); + text_input_free(instance->text_input); + + // Custom Widget + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewWidget); + widget_free(instance->widget); + + // Popup + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewPopup); + popup_free(instance->popup); + + // ViewStack + view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewStack); + view_stack_free(instance->view_stack); + //Dialog furi_record_close(RECORD_DIALOGS); - notification_message(subbrute->notify, &sequence_blink_stop); + // Scene manager + scene_manager_free(instance->scene_manager); - furi_record_close(RECORD_NOTIFICATION); + // View Dispatcher + view_dispatcher_free(instance->view_dispatcher); - view_dispatcher_free(subbrute->view_dispatcher); + // GUI + furi_record_close(RECORD_GUI); + instance->gui = NULL; - string_clear(subbrute->preset); - string_clear(subbrute->candidate); - - // Path strings - string_clear(subbrute->file_path); - string_clear(subbrute->file_path_tmp); - string_clear(subbrute->notification_msg); - string_clear(subbrute->candidate); - string_clear(subbrute->flipper_format_string); - - //flipper_format_free(subbrute->flipper_format); - //subghz_environment_free(subbrute->environment); - //subghz_receiver_free(subbrute->receiver); - - free(subbrute->preset_def); + // SubBruteDevice + subbrute_device_free(instance->device); // The rest - free(subbrute); + free(instance); +} + +void subbrute_show_loading_popup(void* context, bool show) { + TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); + SubBruteState* instance = context; + ViewStack* view_stack = instance->view_stack; + Loading* loading = instance->loading; + + if(show) { + // Raise timer priority so that animations can play + vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + view_stack_add_view(view_stack, loading_get_view(loading)); + } else { + view_stack_remove_view(view_stack, loading_get_view(loading)); + // Restore default timer priority + vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + } +} + +void subbrute_text_input_callback(void* context) { + furi_assert(context); + SubBruteState* instance = context; + view_dispatcher_send_custom_event( + instance->view_dispatcher, SubBruteCustomEventTypeTextEditResult); +} + +void subbrute_popup_closed_callback(void* context) { + furi_assert(context); + SubBruteState* instance = context; + view_dispatcher_send_custom_event( + instance->view_dispatcher, SubBruteCustomEventTypePopupClosed); +} + +const char* subbrute_get_menu_name(SubBruteAttacks index) { + furi_assert(index < SubBruteAttackTotalCount - 1); + + return subbrute_menu_names[index]; } // ENTRYPOINT -int32_t subbrute_start(void* p) { +int32_t subbrute_app(void* p) { UNUSED(p); - // Input - FURI_LOG_I(TAG, "Initializing input"); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SubBruteEvent)); - SubBruteState* subbrute_state = subbrute_alloc(); - ValueMutex subbrute_state_mutex; - - // Mutex - FURI_LOG_I(TAG, "Initializing flipfrid mutex"); - if(!init_mutex(&subbrute_state_mutex, subbrute_state, sizeof(SubBruteState))) { - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - furi_message_queue_free(event_queue); - subbrute_free(subbrute_state); - return 255; - } - - furi_hal_power_suppress_charge_enter(); - - // Configure view port - FURI_LOG_I(TAG, "Initializing viewport"); - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, &subbrute_state_mutex); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Configure timer - FURI_LOG_I(TAG, "Initializing timer"); - FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second - - // Register view port in GUI - FURI_LOG_I(TAG, "Initializing gui"); - subbrute_state->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(subbrute_state->gui, view_port, GuiLayerFullscreen); + SubBruteState* instance = subbrute_alloc(); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Starting subbrute_alloc done"); +#endif view_dispatcher_attach_to_gui( - subbrute_state->view_dispatcher, subbrute_state->gui, ViewDispatcherTypeFullscreen); - - subbrute_state->current_scene = SceneEntryPoint; - - // Init values - SubBruteEvent event; - while(subbrute_state->is_running) { - // Get next event - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25); - if(event_status == FuriStatusOk) { - if(event.evt_type == EventTypeKey) { - //Handle event key - FURI_LOG_D(TAG, "EVENT ###"); - switch(subbrute_state->current_scene) { - case SceneSelectFile: - subbrute_scene_load_file_on_event(event, subbrute_state); - break; - case SceneSelectField: - subbrute_scene_select_field_on_event(event, subbrute_state); - break; - case SceneSaveName: - subbrute_scene_save_name_on_event(event, subbrute_state); - break; - case SceneAttack: - subbrute_scene_run_attack_on_event(event, subbrute_state); - break; - case NoneScene: - case SceneEntryPoint: - subbrute_scene_entrypoint_on_event(event, subbrute_state); - break; - } - - } else if(event.evt_type == EventTypeTick) { - //Handle event tick - if(subbrute_state->current_scene != subbrute_state->previous_scene) { - // Trigger Exit Scene - switch(subbrute_state->previous_scene) { - case SceneSelectFile: - subbrute_scene_load_file_on_exit(subbrute_state); - break; - case SceneSelectField: - subbrute_scene_select_field_on_exit(subbrute_state); - break; - case SceneAttack: - subbrute_scene_run_attack_on_exit(subbrute_state); - break; - case SceneEntryPoint: - subbrute_scene_entrypoint_on_exit(subbrute_state); - break; - case SceneSaveName: - subbrute_scene_save_name_on_exit(subbrute_state); - break; - case NoneScene: - break; - } - - // Trigger Entry Scene - switch(subbrute_state->current_scene) { - case NoneScene: - case SceneSelectFile: - subbrute_scene_load_file_on_enter(subbrute_state); - break; - case SceneSelectField: - subbrute_scene_select_field_on_enter(subbrute_state); - break; - case SceneAttack: - subbrute_scene_run_attack_on_enter(subbrute_state); - break; - case SceneSaveName: - subbrute_scene_save_name_on_enter(subbrute_state); - break; - case SceneEntryPoint: - subbrute_scene_entrypoint_on_enter(subbrute_state); - break; - } - subbrute_state->previous_scene = subbrute_state->current_scene; - } - - // Trigger Tick Scene - switch(subbrute_state->current_scene) { - case NoneScene: - case SceneSelectFile: - subbrute_scene_load_file_on_tick(subbrute_state); - break; - case SceneSelectField: - subbrute_scene_select_field_on_tick(subbrute_state); - break; - case SceneAttack: - //subbrute_scene_run_attack_on_tick(subbrute_state); - break; - case SceneEntryPoint: - subbrute_scene_entrypoint_on_tick(subbrute_state); - break; - case SceneSaveName: - subbrute_scene_save_name_on_tick(subbrute_state); - break; - } - view_port_update(view_port); - } - } - } - - // Cleanup - furi_timer_stop(timer); - furi_timer_free(timer); - + instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); + scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "scene_manager_next_scene set"); +#endif + furi_hal_power_suppress_charge_enter(); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "view_dispatcher_run"); +#endif + view_dispatcher_run(instance->view_dispatcher); furi_hal_power_suppress_charge_exit(); - FURI_LOG_I(TAG, "Cleaning up"); - gui_remove_view_port(subbrute_state->gui, view_port); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_record_close(RECORD_GUI); - subbrute_free(subbrute_state); + subbrute_free(instance); return 0; } \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute.h b/applications/plugins/subbrute/subbrute.h index 76dc45d4b..5fedb9158 100644 --- a/applications/plugins/subbrute/subbrute.h +++ b/applications/plugins/subbrute/subbrute.h @@ -1,110 +1,3 @@ #pragma once -#include -#include -#include -#include -#include "m-string.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "SUBBRUTE" - -typedef enum { - NoneScene, - SceneSelectFile, - SceneSelectField, - SceneAttack, - SceneEntryPoint, - SceneSaveName -} SubBruteScene; - -typedef enum { - SubBruteAttackLoadFile, - SubBruteAttackCAME12bit307, - SubBruteAttackCAME12bit433, - SubBruteAttackCAME12bit868, - SubBruteAttackChamberlain9bit315, - SubBruteAttackChamberlain9bit390, - SubBruteAttackLinear10bit300, - SubBruteAttackLinear10bit310, - SubBruteAttackNICE12bit433, - SubBruteAttackNICE12bit868, -} SubBruteAttacks; - -typedef enum { - EventTypeTick, - EventTypeKey, - EventTypeCustom, -} EventType; - -typedef struct { - EventType evt_type; - InputKey key; - InputType input_type; -} SubBruteEvent; - -// STRUCTS -typedef struct { - // Application stuff - bool is_running; - bool is_attacking; - bool is_thread_running; - bool close_thread_please; - SubBruteScene current_scene; - SubBruteScene previous_scene; - NotificationApp* notify; - Gui* gui; - ViewDispatcher* view_dispatcher; - TextInput* text_input; - Popup* popup; - - // SubGhz Stuff - FuriThread* bruthread; - FlipperFormat* flipper_format; - SubGhzEnvironment* environment; - SubGhzTransmitter* transmitter; - SubGhzReceiver* receiver; - SubGhzProtocolDecoderBase* decoder_result; - SubGhzPresetDefinition* preset_def; - string_t preset; - Stream* stream; - string_t protocol; - uint32_t frequency; - uint32_t frequency_cal; - uint32_t repeat; - uint32_t bit; - string_t key; - uint32_t te; - - // Context Stuff - DialogsApp* dialogs; - char file_name_tmp[64]; - string_t file_path; - string_t file_path_tmp; - string_t notification_msg; - uint8_t key_index; - uint64_t payload; - string_t candidate; - uint8_t str_index; - string_t flipper_format_string; - - SubBruteAttacks attack; - - //Menu stuff - uint8_t menu_index; - - // RAW stuff - string_t subbrute_raw_one; - string_t subbrute_raw_zero; - string_t subbrute_raw_stop; - -} SubBruteState; \ No newline at end of file +typedef struct SubBruteState SubBruteState; \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_custom_event.h b/applications/plugins/subbrute/subbrute_custom_event.h new file mode 100644 index 000000000..6a5a9f08e --- /dev/null +++ b/applications/plugins/subbrute/subbrute_custom_event.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +typedef enum { + // Reserve first 100 events for button types and indexes, starting from 0 + SubBruteCustomEventTypeReserved = 100, + + SubBruteCustomEventTypeBackPressed, + SubBruteCustomEventTypeTextEditResult, + SubBruteCustomEventTypeTransmitStarted, + SubBruteCustomEventTypeTransmitFinished, + SubBruteCustomEventTypeTransmitNotStarted, + SubBruteCustomEventTypeTransmitCustom, + SubBruteCustomEventTypeSaveFile, + SubBruteCustomEventTypeSaveSuccess, + SubBruteCustomEventTypeChangeStep, + + SubBruteCustomEventTypeMenuSelected, + SubBruteCustomEventTypeTextEditDone, + SubBruteCustomEventTypePopupClosed, + + SubBruteCustomEventTypeLoadFile, +} SubBruteCustomEvent; \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c new file mode 100644 index 000000000..df2a94cd7 --- /dev/null +++ b/applications/plugins/subbrute/subbrute_device.c @@ -0,0 +1,582 @@ +#include "subbrute_device.h" +#include "subbrute_i.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define TAG "SubBruteDevice" + +/** + * List of protocols + */ +static const char* protocol_came = "CAME"; +static const char* protocol_cham_code = "Cham_Code"; +static const char* protocol_linear = "Linear"; +static const char* protocol_nice_flo = "Nice FLO"; +static const char* protocol_princeton = "Princeton"; +static const char* protocol_raw = "RAW"; + +/** + * Values to not use less memory for packet parse operations + */ +static const char* subbrute_key_file_start = + "Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\n"; +static const char* subbrute_key_file_key = "Key: %s\n"; +static const char* subbrute_key_file_princeton_end = "TE: %d\n"; + +// Why nobody set in as const in all codebase? +static const char* preset_ook270_async = "FuriHalSubGhzPresetOok270Async"; +static const char* preset_ook650_async = "FuriHalSubGhzPresetOok650Async"; +static const char* preset_2fsk_dev238_async = "FuriHalSubGhzPreset2FSKDev238Async"; +static const char* preset_2fsk_dev476_async = "FuriHalSubGhzPreset2FSKDev476Async"; +static const char* preset_msk99_97_kb_async = "FuriHalSubGhzPresetMSK99_97KbAsync"; +static const char* preset_gfs99_97_kb_async = "FuriHalSubGhzPresetGFS99_97KbAsync"; + +SubBruteDevice* subbrute_device_alloc() { + SubBruteDevice* instance = malloc(sizeof(SubBruteDevice)); + + instance->state = SubBruteDeviceStateIDLE; + instance->key_index = 0; + instance->dialogs = furi_record_open(RECORD_DIALOGS); + + string_init(instance->load_path); + + string_init(instance->payload); + string_init(instance->preset_name); + string_init(instance->protocol_name); + + subbrute_device_attack_set_default_values(instance); + + return instance; +} + +void subbrute_device_free(SubBruteDevice* instance) { + furi_assert(instance); + + furi_record_close(RECORD_DIALOGS); + + string_clear(instance->payload); + string_clear(instance->load_path); + string_clear(instance->preset_name); + string_clear(instance->protocol_name); + + string_clear(instance->load_path); + + free(instance); +} + +SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance) { + furi_assert(instance); + + // Input events and views are managed by file_browser + string_t app_directory; + string_init_set_str(app_directory, SUBBRUTE_PATH); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px); + + SubBruteFileResult load_result = SubBruteFileResultUnknown; + bool res = dialog_file_browser_show( + instance->dialogs, instance->load_path, app_directory, &browser_options); + + string_clear(app_directory); + if(res) { + load_result = subbrute_device_attack_set( + instance, SubBruteAttackLoadFile, string_get_cstr(instance->load_path)); + if(load_result == SubBruteFileResultOk) { + // Ready to run! + instance->state = SubBruteDeviceStateReady; + FURI_LOG_I(TAG, "Ready to run"); + } + } else { + FURI_LOG_I(TAG, "Returned error: %sd", load_result); + // res = false; + // + // char file_info_message[128]; + // snprintf( + // file_info_message, + // sizeof(file_info_message), + // "Can not load file\n%s", + // (char*)subbrute_device_error_get_desc(set_result)); + // dialog_message_show_storage_error(instance->dialogs, file_info_message); + } + + return load_result; +} + +bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) { + furi_assert(instance); + bool result = subbrute_device_create_packet_parsed(instance, instance->key_index); + + if(!result) { + //subbrute_device_notification_message(instance, &sequence_error); + return false; + } + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* stream = buffered_file_stream_alloc(storage); + + result = false; + do { + if(!buffered_file_stream_open(stream, dev_file_name, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { + buffered_file_stream_close(stream); + break; + } + stream_write_string(stream, instance->payload); + + result = true; + } while(false); + + buffered_file_stream_close(stream); + stream_free(stream); + if(!result) { + //subbrute_device_notification_message(instance, &sequence_error); + } + + furi_record_close(RECORD_STORAGE); + + return result; +} + +const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) { + const char* result; + switch(error_id) { + case(SubBruteFileResultOk): + result = "OK"; + break; + case(SubBruteFileResultErrorOpenFile): + result = "invalid name/path"; + break; + case(SubBruteFileResultMissingOrIncorrectHeader): + result = "Missing or incorrect header"; + break; + case(SubBruteFileResultFrequencyNotAllowed): + result = "Invalid frequency!"; + break; + case(SubBruteFileResultMissingOrIncorrectFrequency): + result = "Missing or incorrect Frequency"; + break; + case(SubBruteFileResultPresetInvalid): + result = "Preset FAIL"; + break; + case(SubBruteFileResultMissingProtocol): + result = "Missing Protocol"; + break; + case(SubBruteFileResultProtocolNotSupported): + result = "RAW unsupported"; + break; + case(SubBruteFileResultDynamicProtocolNotValid): + result = "Dynamic protocol unsupported"; + break; + case(SubBruteFileResultProtocolNotFound): + result = "Protocol not found"; + break; + case(SubBruteFileResultMissingOrIncorrectBit): + result = "Missing or incorrect Bit"; + break; + case(SubBruteFileResultMissingOrIncorrectKey): + result = "Missing or incorrect Key"; + break; + case(SubBruteFileResultMissingOrIncorrectTe): + result = "Missing or incorrect TE"; + break; + case SubBruteFileResultUnknown: + default: + result = "Unknown error"; + break; + } + return result; +} + +bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint8_t step) { + furi_assert(instance); + + char step_payload[SUBBRUTE_PAYLOAD_SIZE] = {0}; + string_reset(instance->payload); + + if(instance->attack == SubBruteAttackLoadFile) { + if(step >= sizeof(instance->file_key)) { + return false; + } + snprintf( + step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); + } else { + //snprintf(step_payload, sizeof(step_payload), "%16X", step); + snprintf(step_payload, sizeof(step_payload), "%02X", step); + } + + FURI_LOG_D(TAG, "step_payload: %s, step: %d", step_payload, step); + + if(instance->has_tail) { + string_init_printf( + instance->payload, + instance->file_template, + step_payload, + instance->te); + } else { + string_init_printf( + instance->payload, instance->file_template, step_payload); + } + + return true; +} + +SubBruteFileResult subbrute_device_attack_set( + SubBruteDevice* instance, + SubBruteAttacks type, + const char* file_path) { + furi_assert(instance); + subbrute_device_attack_set_default_values(instance); + uint8_t file_result; + + switch(type) { + case SubBruteAttackLoadFile: + file_result = subbrute_device_load_from_file(instance, file_path); + if(file_result != SubBruteFileResultOk) { + // Failed load file so failed to set attack type + return file_result; // RETURN + } + break; + case SubBruteAttackCAME12bit307: + case SubBruteAttackCAME12bit433: + case SubBruteAttackCAME12bit868: + if(type == SubBruteAttackCAME12bit307) { + instance->frequency = 307800000; + } else if(type == SubBruteAttackCAME12bit433) { + instance->frequency = 433920000; + } else /* ALWAYS TRUE if(type == SubBruteAttackCAME12bit868) */ { + instance->frequency = 868350000; + } + instance->bit = 12; + string_set_str(instance->protocol_name, protocol_came); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackChamberlain9bit315: + instance->frequency = 315000000; + instance->bit = 9; + string_set_str(instance->protocol_name, protocol_cham_code); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackChamberlain9bit390: + instance->frequency = 390000000; + instance->bit = 9; + string_set_str(instance->protocol_name, protocol_cham_code); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackLinear10bit300: + instance->frequency = 300000000; + instance->bit = 10; + string_set_str(instance->protocol_name, protocol_linear); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackLinear10bit310: + instance->frequency = 310000000; + instance->bit = 10; + string_set_str(instance->protocol_name, protocol_linear); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackNICE12bit433: + instance->frequency = 433920000; + instance->bit = 12; + string_set_str(instance->protocol_name, protocol_nice_flo); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + case SubBruteAttackNICE12bit868: + instance->frequency = 868350000; + instance->bit = 12; + string_set_str(instance->protocol_name, protocol_nice_flo); + //string_set_str(instance->preset_name, preset_ook650_async); + break; + default: + FURI_LOG_E(TAG, "Unknown attack type: %d", type); + return SubBruteFileResultProtocolNotFound; // RETURN + } + + if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) { + FURI_LOG_E(TAG, "Frequency invalid: %d", instance->frequency); + return SubBruteFileResultMissingOrIncorrectFrequency; // RETURN + } + + // For non-file types we didn't set SubGhzProtocolDecoderBase + instance->environment = subghz_environment_alloc(); + instance->receiver = subghz_receiver_alloc_init(instance->environment); + subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); + furi_hal_subghz_reset(); + + uint8_t protocol_check_result = SubBruteFileResultProtocolNotFound; + if(type != SubBruteAttackLoadFile) { + instance->decoder_result = subghz_receiver_search_decoder_base_by_name( + instance->receiver, string_get_cstr(instance->protocol_name)); + + if(!instance->decoder_result || + instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set"); + } else { + protocol_check_result = SubBruteFileResultOk; + } + } else { + // And here we need to set preset enum + instance->preset = subbrute_device_convert_preset(instance->preset_name); + protocol_check_result = SubBruteFileResultOk; + } + + subghz_environment_free(instance->environment); + subghz_receiver_free(instance->receiver); + + if(protocol_check_result != SubBruteFileResultOk) { + return SubBruteFileResultProtocolNotFound; + } + + if(strcmp(string_get_cstr(instance->protocol_name), protocol_princeton) == 0) { + instance->has_tail = true; + } + + // Calc max value + if(instance->attack == SubBruteAttackLoadFile) { + instance->max_value = 0xFF; + } else { + string_t max_value_s; + string_init(max_value_s); + for(uint8_t i = 0; i < instance->bit; i++) { + string_cat_printf(max_value_s, "1"); + } + instance->max_value = (uint64_t)strtol(string_get_cstr(max_value_s), NULL, 2); + string_clear(max_value_s); + } + + // Now we are ready to set file template for using in the future with snprintf + // for sending attack payload + snprintf( + instance->file_template, + sizeof(instance->file_template), + subbrute_key_file_start, + instance->frequency, + string_get_cstr(instance->preset_name), + string_get_cstr(instance->protocol_name), + instance->bit); + strncat( + instance->file_template, + subbrute_key_file_key, + sizeof(instance->file_template)); + if(instance->has_tail) { + strncat( + instance->file_template, + subbrute_key_file_princeton_end, + sizeof(instance->file_template)); + } + + return SubBruteFileResultOk; +} + +uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) { + furi_assert(instance); + + SubBruteFileResult result = SubBruteFileResultUnknown; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + + string_t temp_str; + string_init(temp_str); + uint32_t temp_data32; + + instance->environment = subghz_environment_alloc(); + instance->receiver = subghz_receiver_alloc_init(instance->environment); + subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); + furi_hal_subghz_reset(); + + do { + if(!flipper_format_file_open_existing(fff_data_file, file_path)) { + FURI_LOG_E(TAG, "Error open file %s", file_path); + result = SubBruteFileResultErrorOpenFile; + break; + } + if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + result = SubBruteFileResultMissingOrIncorrectHeader; + break; + } + + // Frequency + if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { + instance->frequency = temp_data32; + if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) { + result = SubBruteFileResultFrequencyNotAllowed; + break; + } + } else { + FURI_LOG_E(TAG, "Missing or incorrect Frequency"); + result = SubBruteFileResultMissingOrIncorrectFrequency; + break; + } + // Preset + if(!flipper_format_read_string(fff_data_file, "Preset", instance->preset_name)) { + FURI_LOG_E(TAG, "Preset FAIL"); + result = SubBruteFileResultPresetInvalid; + } + // Protocol + if(!flipper_format_read_string( + fff_data_file, "Protocol", instance->protocol_name)) { + FURI_LOG_E(TAG, "Missing Protocol"); + result = SubBruteFileResultMissingProtocol; + break; + } +#ifdef FURI_DEBUG + else { + FURI_LOG_D(TAG, "Protocol: %s", string_get_cstr(instance->protocol_name)); + } +#endif + + instance->decoder_result = subghz_receiver_search_decoder_base_by_name( + instance->receiver, string_get_cstr(instance->protocol_name)); + + if(!instance->decoder_result || + strcmp(string_get_cstr(instance->protocol_name), "RAW") == 0) { + FURI_LOG_E(TAG, "RAW unsupported"); + result = SubBruteFileResultProtocolNotSupported; + break; + } + + if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + FURI_LOG_E(TAG, "Protocol is dynamic - not supported"); + result = SubBruteFileResultDynamicProtocolNotValid; + break; + } +#ifdef FURI_DEBUG + else { + FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name); + } +#endif + + // instance->decoder_result = subghz_receiver_search_decoder_base_by_name( + // instance->receiver, string_get_cstr(instance->protocol_name)); + // + // if(!instance->decoder_result) { + // FURI_LOG_E(TAG, "Protocol not found"); + // result = SubBruteFileResultProtocolNotFound; + // break; + // } + + // Bit + if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) { + FURI_LOG_E(TAG, "Missing or incorrect Bit"); + result = SubBruteFileResultMissingOrIncorrectBit; + break; + } else { + instance->bit = temp_data32; + } + + // Key + if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { + FURI_LOG_E(TAG, "Missing or incorrect Key"); + result = SubBruteFileResultMissingOrIncorrectKey; + break; + } else { + snprintf( + instance->file_key, + sizeof(instance->file_key), + "%s", + string_get_cstr(temp_str)); + } + + // TE + if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { + FURI_LOG_E(TAG, "Missing or incorrect TE"); + //result = SubBruteFileResultMissingOrIncorrectTe; + //break; + } else { + instance->te = temp_data32; + instance->has_tail = true; + } + + // Repeat + if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Repeat: %d", temp_data32); +#endif + instance->repeat = temp_data32; + } else { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Repeat: 3 (default)"); +#endif + instance->repeat = 3; + } + + result = SubBruteFileResultOk; + } while(0); + + string_clear(temp_str); + flipper_format_file_close(fff_data_file); + flipper_format_free(fff_data_file); + furi_record_close(RECORD_STORAGE); + + subghz_environment_free(instance->environment); + subghz_receiver_free(instance->receiver); + + if(result == SubBruteFileResultOk) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Loaded successfully"); +#endif + } + + return result; +} + +void subbrute_device_attack_set_default_values(SubBruteDevice* instance) { + furi_assert(instance); + + instance->attack = SubBruteAttackNone; + instance->max_value = 0; + instance->key_index = 0; + + memset(instance->file_template, 0, sizeof(instance->file_template)); + memset(instance->current_key, 0, sizeof(instance->current_key)); + memset(instance->file_key, 0, sizeof(instance->file_key)); + + string_set_str(instance->protocol_name, protocol_raw); + + string_set_str(instance->preset_name, preset_ook650_async); + instance->preset = FuriHalSubGhzPresetOok650Async; + + string_reset(instance->payload); + + instance->repeat = 5; + instance->te = 0; + instance->has_tail = false; +} + +FuriHalSubGhzPreset subbrute_device_convert_preset(string_t preset) { + if(string_cmp_str(preset, preset_ook270_async) == 0) { + return FuriHalSubGhzPresetOok270Async; + } + if(string_cmp_str(preset, preset_ook650_async) == 0) { + return FuriHalSubGhzPresetOok650Async; + } + if(string_cmp_str(preset, preset_2fsk_dev238_async) == 0) { + return FuriHalSubGhzPreset2FSKDev238Async; + } + if(string_cmp_str(preset, preset_2fsk_dev476_async) == 0) { + return FuriHalSubGhzPreset2FSKDev476Async; + } + if(string_cmp_str(preset, preset_msk99_97_kb_async) == 0) { + return FuriHalSubGhzPresetMSK99_97KbAsync; + } + if(string_cmp_str(preset, preset_gfs99_97_kb_async) == 0) { + return FuriHalSubGhzPresetMSK99_97KbAsync; + } + return FuriHalSubGhzPresetCustom; +} diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h new file mode 100644 index 000000000..fab750cc6 --- /dev/null +++ b/applications/plugins/subbrute/subbrute_device.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#define SUBBRUTE_TEXT_STORE_SIZE 128 + +#define SUBBRUTE_MAX_LEN_NAME 64 +#define SUBBRUTE_PATH EXT_PATH("subghz") +#define SUBBRUTE_FILE_EXT ".sub" + +#define SUBBRUTE_PAYLOAD_SIZE 8 + +typedef enum { + SubBruteAttackNone, + SubBruteAttackCAME12bit307, + SubBruteAttackCAME12bit433, + SubBruteAttackCAME12bit868, + SubBruteAttackChamberlain9bit315, + SubBruteAttackChamberlain9bit390, + SubBruteAttackLinear10bit300, + SubBruteAttackLinear10bit310, + SubBruteAttackNICE12bit433, + SubBruteAttackNICE12bit868, + SubBruteAttackLoadFile, + SubBruteAttackTotalCount, +} SubBruteAttacks; + +typedef enum { + SubBruteFileResultUnknown, + SubBruteFileResultOk, + SubBruteFileResultErrorOpenFile, + SubBruteFileResultMissingOrIncorrectHeader, + SubBruteFileResultFrequencyNotAllowed, + SubBruteFileResultMissingOrIncorrectFrequency, + SubBruteFileResultPresetInvalid, + SubBruteFileResultMissingProtocol, + SubBruteFileResultProtocolNotSupported, + SubBruteFileResultDynamicProtocolNotValid, + SubBruteFileResultProtocolNotFound, + SubBruteFileResultMissingOrIncorrectBit, + SubBruteFileResultMissingOrIncorrectKey, + SubBruteFileResultMissingOrIncorrectTe, +} SubBruteFileResult; + +typedef enum { + SubBruteDeviceStateIDLE, + SubBruteDeviceStateReady, + SubBruteDeviceStateTx, + SubBruteDeviceStateFinished, +} SubBruteDeviceState; + +typedef struct { + DialogsApp* dialogs; + SubBruteDeviceState state; + + // Current step + uint8_t key_index; + string_t load_path; + + SubGhzReceiver* receiver; + SubGhzProtocolDecoderBase* decoder_result; + SubGhzEnvironment* environment; + + // Attack state + SubBruteAttacks attack; + char file_template[SUBBRUTE_TEXT_STORE_SIZE]; + bool has_tail; + string_t payload; + uint8_t max_value; + + // Loaded info for attack type + FuriHalSubGhzPreset preset; + string_t preset_name; + string_t protocol_name; + uint32_t frequency; + uint32_t repeat; + uint32_t bit; + char current_key[SUBBRUTE_PAYLOAD_SIZE]; + uint32_t te; + + char file_key[SUBBRUTE_PAYLOAD_SIZE]; + char text_store[SUBBRUTE_PAYLOAD_SIZE]; +} SubBruteDevice; + +SubBruteDevice* subbrute_device_alloc(); +void subbrute_device_free(SubBruteDevice* instance); +SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance); +bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name); +const char* subbrute_device_error_get_desc(SubBruteFileResult error_id); +bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint8_t step); +SubBruteFileResult subbrute_device_attack_set( + SubBruteDevice* context, + SubBruteAttacks type, + const char* file_path); +uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path); +FuriHalSubGhzPreset subbrute_device_convert_preset(string_t preset); +void subbrute_device_attack_set_default_values(SubBruteDevice* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_i.h b/applications/plugins/subbrute/subbrute_i.h new file mode 100644 index 000000000..5d434738e --- /dev/null +++ b/applications/plugins/subbrute/subbrute_i.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include + +#include "lib/toolbox/path.h" +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "subbrute_device.h" +#include "subbrute.h" +#include "scenes/subbrute_scene.h" +#include "views/subbrute_attack_view.h" +#include "views/subbrute_main_view.h" + +typedef enum { + SubBruteViewNone, + SubBruteViewMain, + SubBruteViewAttack, + SubBruteViewTextInput, + SubBruteViewDialogEx, + SubBruteViewPopup, + SubBruteViewWidget, + SubBruteViewStack, +} SubBruteView; + +struct SubBruteState { + // GUI elements + NotificationApp* notifications; + Gui* gui; + ViewDispatcher* view_dispatcher; + ViewStack* view_stack; + TextInput* text_input; + Popup* popup; + Widget* widget; + DialogsApp* dialogs; + Loading* loading; + + // Views + SubBruteMainView* view_main; + SubBruteAttackView* view_attack; + SubBruteView current_view; + + // Scene + SceneManager* scene_manager; + + SubBruteDevice* device; + + //Menu stuff + // TODO: Do we need it? + uint8_t menu_index; +}; + +void subbrute_show_loading_popup(void* context, bool show); +void subbrute_text_input_callback(void* context); +void subbrute_popup_closed_callback(void* context); +const char* subbrute_get_menu_name(uint8_t index); + +int32_t subbrute_app(void* p); +SubBruteState* subbrute_alloc(); +void subbrute_free(SubBruteState* instance); +bool subbrute_custom_event_callback(void* context, uint32_t event); +bool subbrute_back_event_callback(void* context); +void subbrute_tick_event_callback(void* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_utils.c b/applications/plugins/subbrute/subbrute_utils.c deleted file mode 100644 index 2aafc7175..000000000 --- a/applications/plugins/subbrute/subbrute_utils.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "subbrute_utils.h" - -bool subbrute_is_frequency_allowed(SubBruteState* context) { - // I know you don't like it but laws are laws - // It's opensource so do whatever you want, but remember the risks :) - // (Yes, this comment is the only purpose of this function) - bool r = furi_hal_subghz_is_tx_allowed(context->frequency); - if(!r) { - FURI_LOG_E(TAG, "Frequency %d is not allowed in your region", context->frequency); - notification_message(context->notify, &sequence_single_vibro); - } - return r; -} \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_utils.h b/applications/plugins/subbrute/subbrute_utils.h deleted file mode 100644 index 90f7c60ad..000000000 --- a/applications/plugins/subbrute/subbrute_utils.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "subbrute.h" - -bool subbrute_is_frequency_allowed(SubBruteState* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c new file mode 100644 index 000000000..f651bb4c6 --- /dev/null +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -0,0 +1,321 @@ +#include "subbrute_attack_view.h" +#include "../subbrute_i.h" +#include "../helpers/subbrute_worker.h" + +#include "assets_icons.h" +#include "../../../services/gui/icon_i.h" +#include +#include +#include + +struct SubBruteAttackView { + View* view; + SubBruteAttackViewCallback callback; + void* context; + SubBruteWorker* worker; +}; + +typedef struct { + SubBruteAttacks index; + uint8_t max_value; + uint8_t current_step; + bool is_attacking; +} SubBruteAttackViewModel; + +void subbrute_attack_view_set_callback( + SubBruteAttackView* instance, + SubBruteAttackViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + + instance->callback = callback; + instance->context = context; +} + +bool subbrute_attack_view_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + SubBruteAttackView* instance = context; + + if(event->key == InputKeyBack && event->type == InputTypeShort) { + instance->callback(SubBruteCustomEventTypeBackPressed, instance->context); + return true; + } + + bool is_attacking = false; + + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + is_attacking = model->is_attacking; + return false; + }); + + // if(!is_attacking) { + // instance->callback(SubBruteCustomEventTypeTransmitNotStarted, instance->context); + // } else { + // instance->callback(SubBruteCustomEventTypeTransmitStarted, instance->context); + // } + + if(!is_attacking) { + if(event->key == InputKeyOk) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->is_attacking = true; + return true; + }); + instance->callback(SubBruteCustomEventTypeTransmitStarted, instance->context); + // } else if(event->key == InputKeyBack) { + // if(previous_scene == SubBruteSceneLoadFile) { + // instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); + // } else { + // instance->callback(SubBruteCustomEventTypeBackPressed, instance->context); + // } + } else if(event->key == InputKeyUp) { + instance->callback(SubBruteCustomEventTypeSaveFile, instance->context); + } else if(event->key == InputKeyDown) { + instance->callback(SubBruteCustomEventTypeTransmitCustom, instance->context); + } else if(event->type == InputTypePress) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + if(event->key == InputKeyLeft) { + model->current_step = + ((model->current_step - 100) + model->max_value) % model->max_value; + } else if(event->key == InputKeyRight) { + model->current_step = (model->current_step + 100) % model->max_value; + } + return true; + }); + instance->callback(SubBruteCustomEventTypeChangeStep, instance->context); + } else if(event->type == InputTypeShort || event->type == InputTypeRepeat) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + if(event->key == InputKeyLeft) { + model->current_step = + ((model->current_step - 1) + model->max_value) % model->max_value; + } else if(event->key == InputKeyRight) { + model->current_step = (model->current_step + 1) % model->max_value; + } + return true; + }); + instance->callback(SubBruteCustomEventTypeChangeStep, instance->context); + } + } else { + if((event->type == InputTypeShort || event->type == InputTypeRepeat) && + (event->key == InputKeyOk || event->key == InputKeyBack)) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->is_attacking = false; + return true; + }); + instance->callback(SubBruteCustomEventTypeTransmitNotStarted, instance->context); + } + } + + return true; +} + +SubBruteAttackView* subbrute_attack_view_alloc() { + SubBruteAttackView* instance = malloc(sizeof(SubBruteAttackView)); + + instance->view = view_alloc(); + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubBruteAttackViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)subbrute_attack_view_draw); + view_set_input_callback(instance->view, subbrute_attack_view_input); + view_set_enter_callback(instance->view, subbrute_attack_view_enter); + view_set_exit_callback(instance->view, subbrute_attack_view_exit); + + instance->worker = subbrute_worker_alloc(); + + return instance; +} + +void subbrute_attack_view_enter(void* context) { + furi_assert(context); +} + +void subbrute_attack_view_free(SubBruteAttackView* instance) { + furi_assert(instance); + + subbrute_worker_free(instance->worker); + + view_free(instance->view); + free(instance); +} + +View* subbrute_attack_view_get_view(SubBruteAttackView* instance) { + furi_assert(instance); + return instance->view; +} + +void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t current_step) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->current_step = current_step; + return true; + }); +} + +uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance) { + uint8_t current_step; + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + current_step = model->current_step; + return false; + }); + + return current_step; +} + +// We need to call init every time, because not every time we calls enter +// normally, call enter only once +void subbrute_attack_view_init_values( + SubBruteAttackView* instance, + uint8_t index, + uint8_t max_value, + uint8_t current_step) { + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->max_value = max_value; + model->index = index; + model->current_step = current_step; + return true; + }); +} + +void subbrute_attack_view_stop_worker(SubBruteAttackView* instance) { + furi_assert(instance); + subbrute_worker_stop(instance->worker); +} + +bool subbrute_attack_view_can_send(SubBruteAttackView* instance) { + furi_assert(instance); + + return subbrute_worker_can_transmit(instance->worker); +} + +void subbrute_attack_view_start_worker( + SubBruteAttackView* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + string_t protocol_name) { + furi_assert(instance); + if(!subbrute_worker_is_running(instance->worker)) { + subbrute_worker_start(instance->worker, frequency, preset, protocol_name); + } +} + +bool subbrute_attack_view_transmit(SubBruteAttackView* instance, string_t payload) { + furi_assert(instance); + + return subbrute_worker_transmit(instance->worker, payload); +} + +bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance) { + furi_assert(instance); + + return subbrute_worker_is_running(instance->worker); +} + +void subbrute_attack_view_exit(void* context) { + furi_assert(context); + SubBruteAttackView* instance = context; + + // Just stop, make free in free method + subbrute_worker_stop(instance->worker); +} + +void elements_button_top_left(Canvas* canvas, const char* str) { + const Icon* icon = &I_ButtonUp_7x4; + + const uint8_t button_height = 12; + const uint8_t vertical_offset = 3; + const uint8_t horizontal_offset = 3; + const uint8_t string_width = canvas_string_width(canvas, str); + const uint8_t icon_h_offset = 3; + const uint8_t icon_width_with_offset = icon->width + icon_h_offset; + const uint8_t icon_v_offset = icon->height + vertical_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + + const uint8_t x = 0; + const uint8_t y = 0; + + canvas_draw_box(canvas, x, y - button_height, button_width, button_height); + canvas_draw_line(canvas, x + button_width - 0, y, x + button_width - 0, y + button_height - 0); + canvas_draw_line(canvas, x + button_width - 1, y, x + button_width - 1, y + button_height - 1); + canvas_draw_line(canvas, x + button_width - 2, y, x + button_width - 2, y + button_height - 2); + + canvas_invert_color(canvas); + canvas_draw_icon(canvas, x + horizontal_offset, y + icon_v_offset, icon); + canvas_draw_str( + canvas, x + horizontal_offset + icon_width_with_offset, y + vertical_offset, str); + canvas_invert_color(canvas); +} + +void elements_button_top_right(Canvas* canvas, const char* str) { + const Icon* icon = &I_ButtonDown_7x4; + + const uint8_t button_height = 12; + const uint8_t vertical_offset = 3; + const uint8_t horizontal_offset = 3; + const uint8_t string_width = canvas_string_width(canvas, str); + const uint8_t icon_h_offset = 3; + const uint8_t icon_width_with_offset = icon->width + icon_h_offset; + const uint8_t icon_v_offset = icon->height + vertical_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + + const uint8_t x = canvas_width(canvas); + const uint8_t y = 0; + + canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height); + canvas_draw_line(canvas, x - button_width - 1, y, x + button_width + 1, y + button_height - 0); + canvas_draw_line(canvas, x - button_width - 2, y, x + button_width + 2, y + button_height - 1); + canvas_draw_line(canvas, x - button_width - 3, y, x + button_width + 3, y + button_height - 2); + + canvas_invert_color(canvas); + canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str); + canvas_draw_icon(canvas, x - horizontal_offset - icon->width, y - icon_v_offset, icon); + canvas_invert_color(canvas); +} + +void subbrute_attack_view_draw(Canvas* canvas, void* context) { + furi_assert(context); + SubBruteAttackViewModel* model = context; + //char buffer[64]; + + // Title + const char* attack_name = NULL; + attack_name = subbrute_get_menu_name(model->index); + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 20, 8, attack_name ? attack_name : "Sub-GHz Bruteforcer"); + + // Progress bar + // Resolution: 128x64 px + float progress_value = model->max_value / model->current_step; + elements_progress_bar(canvas, 8, 30, 98, progress_value > 1 ? 1 : progress_value); + + // Selected attack type + // const char* attack_name = NULL; + // attack_name = subbrute_get_menu_name(model->index); + // + // canvas_set_font(canvas, FontSecondary); + // if(attack_name) { + // snprintf(buffer, sizeof(buffer), "%s", attack_name); + // } else { + // snprintf(buffer, sizeof(buffer), "%s", "Unknown"; + // } + // canvas_draw_str(canvas, 9, 42, buffer); + + if(!model->is_attacking) { + elements_button_left(canvas, "-1"); + elements_button_right(canvas, "+1"); + elements_button_center(canvas, "Start"); + elements_button_top_left(canvas, "Save"); + elements_button_top_right(canvas, "Repeat"); + } else { + elements_button_center(canvas, "Stop"); + } +} diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.h b/applications/plugins/subbrute/views/subbrute_attack_view.h new file mode 100644 index 000000000..253b42adf --- /dev/null +++ b/applications/plugins/subbrute/views/subbrute_attack_view.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include "assets_icons.h" +#include +#include +#include +#include +#include "../subbrute_custom_event.h" + +typedef void (*SubBruteAttackViewCallback)(SubBruteCustomEvent event, void* context); +typedef struct SubBruteAttackView SubBruteAttackView; + +void subbrute_attack_view_set_callback( + SubBruteAttackView* instance, + SubBruteAttackViewCallback callback, + void* context); +SubBruteAttackView* subbrute_attack_view_alloc(); +void subbrute_attack_view_free(SubBruteAttackView* instance); +View* subbrute_attack_view_get_view(SubBruteAttackView* instance); +void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t current_step); +uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance); +void subbrute_attack_view_init_values( + SubBruteAttackView* instance, + uint8_t index, + uint8_t max_value, + uint8_t current_step); +void subbrute_attack_view_stop_worker(SubBruteAttackView* instance); +bool subbrute_attack_view_can_send(SubBruteAttackView* instance); +void subbrute_attack_view_start_worker( + SubBruteAttackView* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + string_t protocol_name); +bool subbrute_attack_view_transmit(SubBruteAttackView* instance, string_t payload); +bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c new file mode 100644 index 000000000..4f497fdb6 --- /dev/null +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -0,0 +1,152 @@ +#include "subbrute_main_view.h" +#include "../subbrute_i.h" + +#include +#include +#include + +#define STATUS_BAR_Y_SHIFT 13 + +struct SubBruteMainView { + View* view; + SubBruteMainViewCallback callback; + void* context; +}; + +typedef struct { + uint8_t index; +} SubBruteMainViewModel; + +void subbrute_main_view_set_callback( + SubBruteMainView* instance, + SubBruteMainViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + + instance->callback = callback; + instance->context = context; +} + +void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { + SubBruteMainViewModel* m = model; + + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + + for(uint8_t i = 1; i < SubBruteAttackTotalCount - 1; ++i) { + const char* str = subbrute_get_menu_name(i); + canvas_draw_str_aligned( + canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + + if(m->index == i) { + elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); + } + } +} + +bool subbrute_main_view_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + SubBruteMainView* instance = context; + const uint8_t min_value = SubBruteAttackNone + 1; + const uint8_t correct_total = SubBruteAttackTotalCount - 1; + //uint8_t idx = min_value; + bool consumed = false; + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + bool ret = false; + if(event->key == InputKeyUp) { + if(model->index == min_value) { + model->index = correct_total; + } else { + model->index = CLAMP(model->index - 1, correct_total, min_value); + } + ret = true; + consumed = true; + } else if(event->key == InputKeyDown) { + if(model->index == correct_total) { + model->index = min_value; + } else { + model->index = CLAMP(model->index + 1, correct_total, min_value); + } + ret = true; + consumed = true; + } + if(ret) { + model->index++; + } + //idx = model->index; + return ret; + }); + } + + if(event->key == InputKeyOk && event->type == InputTypeShort) { + /*if(idx == SubBruteAttackLoadFile) { + instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); + } else if(idx > SubBruteAttackNone && idx < SubBruteAttackLoadFile) {*/ + instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + /*}*/ + consumed = true; + } + + return consumed; +} + +void subbrute_main_view_enter(void* context) { + furi_assert(context); +} + +void subbrute_main_view_exit(void* context) { + furi_assert(context); +} + +SubBruteMainView* subbrute_main_view_alloc() { + SubBruteMainView* instance = malloc(sizeof(SubBruteMainView)); + instance->view = view_alloc(); + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubBruteMainViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)subbrute_main_view_draw); + view_set_input_callback(instance->view, subbrute_main_view_input); + view_set_enter_callback(instance->view, subbrute_main_view_enter); + view_set_exit_callback(instance->view, subbrute_main_view_exit); + + return instance; +} + +void subbrute_main_view_free(SubBruteMainView* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* subbrute_main_view_get_view(SubBruteMainView* instance) { + furi_assert(instance); + return instance->view; +} + +void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { + furi_assert(instance); + furi_assert(idx < SubBruteAttackTotalCount - 2); + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + model->index = idx <= 0 ? 1 : idx; + return true; + }); +} + +SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance) { + furi_assert(instance); + + uint8_t attack = 0; + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + attack = model->index; + return false; + }); + + return attack; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_main_view.h b/applications/plugins/subbrute/views/subbrute_main_view.h new file mode 100644 index 000000000..bb0e30b00 --- /dev/null +++ b/applications/plugins/subbrute/views/subbrute_main_view.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../subbrute_custom_event.h" +#include +#include "assets_icons.h" +#include +#include +#include + +typedef void (*SubBruteMainViewCallback)(SubBruteCustomEvent event, void* context); +typedef struct SubBruteMainView SubBruteMainView; + +void subbrute_main_view_set_callback( + SubBruteMainView* instance, + SubBruteMainViewCallback callback, + void* context); + +SubBruteMainView* subbrute_main_view_alloc(); +void subbrute_main_view_free(SubBruteMainView* instance); +View* subbrute_main_view_get_view(SubBruteMainView* instance); + +void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx); +uint8_t subbrute_main_view_get_index(SubBruteMainView* instance); + +void subbrute_attack_view_enter(void* context); +void subbrute_attack_view_exit(void* context); +bool subbrute_attack_view_input(InputEvent* event, void* context); +void subbrute_attack_view_draw(Canvas* canvas, void* context); \ No newline at end of file From c8e3d9b0407eb7c3f801dbf52e85fc315d5e3b0c Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sat, 24 Sep 2022 22:15:09 +0400 Subject: [PATCH 02/29] fix repeat call of view_dispatcher_alloc --- .../subbrute/scenes/subbrute_scene_start.c | 2 +- applications/plugins/subbrute/subbrute.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index ffc976c61..43b1b413d 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -19,9 +19,9 @@ void subbrute_scene_start_on_enter(void* context) { subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance); + subbrute_main_view_set_index(view, (uint8_t)instance->device->attack); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); - subbrute_main_view_set_index(view, (uint8_t)instance->device->attack); } void subbrute_scene_start_on_exit(void* context) { diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index e2f19916a..9ae354110 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -59,6 +59,8 @@ SubBruteState* subbrute_alloc() { instance->scene_manager = scene_manager_alloc(&subbrute_scene_handlers, instance); instance->view_dispatcher = view_dispatcher_alloc(); + instance->gui = furi_record_open(RECORD_GUI); + view_dispatcher_enable_queue(instance->view_dispatcher); view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance); view_dispatcher_set_custom_event_callback( @@ -68,17 +70,15 @@ SubBruteState* subbrute_alloc() { view_dispatcher_set_tick_event_callback( instance->view_dispatcher, subbrute_tick_event_callback, 100); - // Devices - instance->device = subbrute_device_alloc(); - - instance->gui = furi_record_open(RECORD_GUI); - instance->dialogs = furi_record_open(RECORD_DIALOGS); - instance->notifications = furi_record_open(RECORD_NOTIFICATION); - instance->view_dispatcher = view_dispatcher_alloc(); - //Dialog instance->dialogs = furi_record_open(RECORD_DIALOGS); + // Notifications + instance->notifications = furi_record_open(RECORD_NOTIFICATION); + + // Devices + instance->device = subbrute_device_alloc(); + // TextInput instance->text_input = text_input_alloc(); view_dispatcher_add_view( @@ -157,6 +157,7 @@ void subbrute_free(SubBruteState* instance) { //Dialog furi_record_close(RECORD_DIALOGS); + instance->dialogs = NULL; // Scene manager scene_manager_free(instance->scene_manager); From b03cc8ddc3882059a91cc755618faf68113a44bc Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sat, 24 Sep 2022 22:30:08 +0400 Subject: [PATCH 03/29] trying to fix load failure --- applications/plugins/subbrute/subbrute.c | 8 +++++--- applications/plugins/subbrute/subbrute_i.h | 9 +-------- .../plugins/subbrute/views/subbrute_attack_view.c | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index 9ae354110..c06d66291 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -35,19 +35,19 @@ static const char* subbrute_menu_names[] = { [SubBruteAttackTotalCount] = "Total Count", }; -bool subbrute_custom_event_callback(void* context, uint32_t event) { +static bool subbrute_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubBruteState* instance = context; return scene_manager_handle_custom_event(instance->scene_manager, event); } -bool subbrute_back_event_callback(void* context) { +static bool subbrute_back_event_callback(void* context) { furi_assert(context); SubBruteState* instance = context; return scene_manager_handle_back_event(instance->scene_manager); } -void subbrute_tick_event_callback(void* context) { +static void subbrute_tick_event_callback(void* context) { furi_assert(context); SubBruteState* instance = context; scene_manager_handle_tick_event(instance->scene_manager); @@ -217,6 +217,8 @@ const char* subbrute_get_menu_name(SubBruteAttacks index) { int32_t subbrute_app(void* p) { UNUSED(p); + FURI_LOG_I(TAG, "subbrute_app"); + SubBruteState* instance = subbrute_alloc(); #ifdef FURI_DEBUG FURI_LOG_I(TAG, "Starting subbrute_alloc done"); diff --git a/applications/plugins/subbrute/subbrute_i.h b/applications/plugins/subbrute/subbrute_i.h index 5d434738e..518631f3a 100644 --- a/applications/plugins/subbrute/subbrute_i.h +++ b/applications/plugins/subbrute/subbrute_i.h @@ -77,11 +77,4 @@ struct SubBruteState { void subbrute_show_loading_popup(void* context, bool show); void subbrute_text_input_callback(void* context); void subbrute_popup_closed_callback(void* context); -const char* subbrute_get_menu_name(uint8_t index); - -int32_t subbrute_app(void* p); -SubBruteState* subbrute_alloc(); -void subbrute_free(SubBruteState* instance); -bool subbrute_custom_event_callback(void* context, uint32_t event); -bool subbrute_back_event_callback(void* context); -void subbrute_tick_event_callback(void* context); \ No newline at end of file +const char* subbrute_get_menu_name(uint8_t index); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index f651bb4c6..cb8b0d9c7 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -127,7 +127,7 @@ SubBruteAttackView* subbrute_attack_view_alloc() { view_set_enter_callback(instance->view, subbrute_attack_view_enter); view_set_exit_callback(instance->view, subbrute_attack_view_exit); - instance->worker = subbrute_worker_alloc(); + //instance->worker = subbrute_worker_alloc(); return instance; } From 666821e9ce7ace773da6ba4cb0142c28f62469fd Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 00:46:43 +0400 Subject: [PATCH 04/29] SubBruteMainView is ready --- .../subbrute/scenes/subbrute_scene_start.c | 39 ++++-- applications/plugins/subbrute/subbrute.c | 13 +- .../plugins/subbrute/subbrute_device.c | 27 +++- .../plugins/subbrute/subbrute_device.h | 1 - .../subbrute/views/subbrute_attack_view.c | 26 +++- .../subbrute/views/subbrute_main_view.c | 131 +++++++++++++++--- 6 files changed, 183 insertions(+), 54 deletions(-) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index 43b1b413d..4b10d3865 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -2,48 +2,61 @@ #include "../subbrute_custom_event.h" #include "../views/subbrute_main_view.h" +#define TAG "SubBruteSceneStart" + void subbrute_scene_start_callback(SubBruteCustomEvent event, void* context) { furi_assert(context); SubBruteState* instance = (SubBruteState*)context; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_scene_start_callback"); +#endif view_dispatcher_send_custom_event(instance->view_dispatcher, event); } void subbrute_scene_start_on_enter(void* context) { furi_assert(context); - +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_start_on_enter"); +#endif SubBruteState* instance = (SubBruteState*)context; SubBruteMainView* view = instance->view_main; instance->current_view = SubBruteViewMain; - subbrute_main_view_set_callback(view, - subbrute_scene_start_callback, - instance); + subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance); subbrute_main_view_set_index(view, (uint8_t)instance->device->attack); - +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "view_dispatcher_switch_to_view"); +#endif view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } void subbrute_scene_start_on_exit(void* context) { UNUSED(context); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_start_on_exit"); +#endif } bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { SubBruteState* instance = (SubBruteState*)context; bool consumed = false; - if(event.type == SceneManagerEventTypeCustom && event.event == SubBruteCustomEventTypeMenuSelected) { - //subbrute_device_attack_set - SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main); + if(event.type == SceneManagerEventTypeCustom) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Event: %d", event.event); +#endif + if(event.event == SubBruteCustomEventTypeMenuSelected) { + SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main); - if (attack == SubBruteAttackLoadFile) { - scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); - } else { subbrute_device_attack_set(instance->device, attack, NULL); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); - } - consumed = true; + consumed = true; + } else if(event.event == SubBruteCustomEventTypeLoadFile) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); + consumed = true; + } } return consumed; diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index c06d66291..878b112e4 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -21,7 +21,6 @@ #define TAG "SubBruteApp" static const char* subbrute_menu_names[] = { - [SubBruteAttackNone] = "None", [SubBruteAttackCAME12bit307] = "CAME 12bit 307mhz", [SubBruteAttackCAME12bit433] = "CAME 12bit 433mhz", [SubBruteAttackCAME12bit868] = "CAME 12bit 868mhz", @@ -208,7 +207,7 @@ void subbrute_popup_closed_callback(void* context) { } const char* subbrute_get_menu_name(SubBruteAttacks index) { - furi_assert(index < SubBruteAttackTotalCount - 1); + furi_assert(index < SubBruteAttackTotalCount); return subbrute_menu_names[index]; } @@ -216,22 +215,22 @@ const char* subbrute_get_menu_name(SubBruteAttacks index) { // ENTRYPOINT int32_t subbrute_app(void* p) { UNUSED(p); - +#ifdef FURI_DEBUG FURI_LOG_I(TAG, "subbrute_app"); - +#endif SubBruteState* instance = subbrute_alloc(); #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "Starting subbrute_alloc done"); + FURI_LOG_D(TAG, "Starting subbrute_alloc done"); #endif view_dispatcher_attach_to_gui( instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "scene_manager_next_scene set"); + FURI_LOG_D(TAG, "scene_manager_next_scene set"); #endif furi_hal_power_suppress_charge_enter(); #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "view_dispatcher_run"); + FURI_LOG_D(TAG, "view_dispatcher_run"); #endif view_dispatcher_run(instance->view_dispatcher); furi_hal_power_suppress_charge_exit(); diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index df2a94cd7..200720e89 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -81,7 +81,9 @@ void subbrute_device_free(SubBruteDevice* instance) { SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance) { furi_assert(instance); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_load_protocol_from_file"); +#endif // Input events and views are managed by file_browser string_t app_directory; string_init_set_str(app_directory, SUBBRUTE_PATH); @@ -120,9 +122,14 @@ SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* insta bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) { furi_assert(instance); + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name); +#endif bool result = subbrute_device_create_packet_parsed(instance, instance->key_index); if(!result) { + FURI_LOG_E(TAG, "subbrute_device_create_packet_parsed failed!"); //subbrute_device_notification_message(instance, &sequence_error); return false; } @@ -144,6 +151,7 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na buffered_file_stream_close(stream); stream_free(stream); if(!result) { + FURI_LOG_E(TAG, "stream_write_string failed!"); //subbrute_device_notification_message(instance, &sequence_error); } @@ -218,9 +226,9 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint8_t step //snprintf(step_payload, sizeof(step_payload), "%16X", step); snprintf(step_payload, sizeof(step_payload), "%02X", step); } - +#ifdef FURI_DEBUG FURI_LOG_D(TAG, "step_payload: %s, step: %d", step_payload, step); - +#endif if(instance->has_tail) { string_init_printf( instance->payload, @@ -240,6 +248,9 @@ SubBruteFileResult subbrute_device_attack_set( SubBruteAttacks type, const char* file_path) { furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_attack_set: %d", type); +#endif subbrute_device_attack_set_default_values(instance); uint8_t file_result; @@ -384,7 +395,9 @@ SubBruteFileResult subbrute_device_attack_set( uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) { furi_assert(instance); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", file_path); +#endif SubBruteFileResult result = SubBruteFileResultUnknown; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -538,8 +551,10 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil void subbrute_device_attack_set_default_values(SubBruteDevice* instance) { furi_assert(instance); - - instance->attack = SubBruteAttackNone; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values"); +#endif + instance->attack = SubBruteAttackCAME12bit307; instance->max_value = 0; instance->key_index = 0; diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index fab750cc6..fea7563e4 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -17,7 +17,6 @@ #define SUBBRUTE_PAYLOAD_SIZE 8 typedef enum { - SubBruteAttackNone, SubBruteAttackCAME12bit307, SubBruteAttackCAME12bit433, SubBruteAttackCAME12bit868, diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index cb8b0d9c7..18eac8125 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -3,11 +3,12 @@ #include "../helpers/subbrute_worker.h" #include "assets_icons.h" -#include "../../../services/gui/icon_i.h" #include #include #include +#define TAG "SubBruteAttackView" + struct SubBruteAttackView { View* view; SubBruteAttackViewCallback callback; @@ -36,7 +37,9 @@ void subbrute_attack_view_set_callback( bool subbrute_attack_view_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "InputKey: %d", event->key); +#endif SubBruteAttackView* instance = context; if(event->key == InputKeyBack && event->type == InputTypeShort) { @@ -127,13 +130,17 @@ SubBruteAttackView* subbrute_attack_view_alloc() { view_set_enter_callback(instance->view, subbrute_attack_view_enter); view_set_exit_callback(instance->view, subbrute_attack_view_exit); - //instance->worker = subbrute_worker_alloc(); + instance->worker = subbrute_worker_alloc(); return instance; } void subbrute_attack_view_enter(void* context) { furi_assert(context); + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_attack_view_enter"); +#endif } void subbrute_attack_view_free(SubBruteAttackView* instance) { @@ -151,6 +158,9 @@ View* subbrute_attack_view_get_view(SubBruteAttackView* instance) { } void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t current_step) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Set step: %d", current_step); +#endif with_view_model( instance->view, (SubBruteAttackViewModel * model) { model->current_step = current_step; @@ -165,7 +175,9 @@ uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance) { current_step = model->current_step; return false; }); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Get step: %d", current_step); +#endif return current_step; } @@ -222,7 +234,9 @@ bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance) { void subbrute_attack_view_exit(void* context) { furi_assert(context); SubBruteAttackView* instance = context; - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_attack_view_exit"); +#endif // Just stop, make free in free method subbrute_worker_stop(instance->worker); } @@ -282,7 +296,7 @@ void elements_button_top_right(Canvas* canvas, const char* str) { void subbrute_attack_view_draw(Canvas* canvas, void* context) { furi_assert(context); - SubBruteAttackViewModel* model = context; + SubBruteAttackViewModel* model = (SubBruteAttackViewModel*)context; //char buffer[64]; // Title diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 4f497fdb6..e1fc1a91b 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -5,7 +5,8 @@ #include #include -#define STATUS_BAR_Y_SHIFT 13 +#define STATUS_BAR_Y_SHIFT 14 +#define TAG "SubBruteMainView" struct SubBruteMainView { View* view; @@ -15,6 +16,7 @@ struct SubBruteMainView { typedef struct { uint8_t index; + uint8_t window_position; } SubBruteMainViewModel; void subbrute_main_view_set_callback( @@ -31,16 +33,32 @@ void subbrute_main_view_set_callback( void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { SubBruteMainViewModel* m = model; + // Title + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); + + // Menu canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); + uint8_t items_on_screen = 3; + const uint8_t item_height = 16; - for(uint8_t i = 1; i < SubBruteAttackTotalCount - 1; ++i) { - const char* str = subbrute_get_menu_name(i); - canvas_draw_str_aligned( - canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); +#endif + for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { + uint8_t item_position = position - model->window_position; - if(m->index == i) { - elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); + if(item_position < items_on_screen) { + const char* str = subbrute_get_menu_name(position); + if(m->index == position) { + canvas_draw_str_aligned( + canvas, 64, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + elements_frame(canvas, 1, 2 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); + } else { + canvas_draw_str_aligned( + canvas, 64, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + } } } } @@ -48,16 +66,25 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { bool subbrute_main_view_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "InputKey: %d", event->key); +#endif + + if(event->key == InputKeyBack && event->type == InputTypeShort) { + return false; + } SubBruteMainView* instance = context; - const uint8_t min_value = SubBruteAttackNone + 1; + const uint8_t min_value = 0; const uint8_t correct_total = SubBruteAttackTotalCount - 1; - //uint8_t idx = min_value; + uint8_t index = 0; + bool consumed = false; if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { with_view_model( instance->view, (SubBruteMainViewModel * model) { bool ret = false; + uint8_t items_on_screen = 3; if(event->key == InputKeyUp) { if(model->index == min_value) { model->index = correct_total; @@ -75,20 +102,42 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { ret = true; consumed = true; } - if(ret) { - model->index++; + if (ret) { + model->window_position = model->index; + if(model->window_position > 0) { + model->window_position -= 1; + } + + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= + (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = + (SubBruteAttackTotalCount - items_on_screen); + } + } } - //idx = model->index; + index = model->index; return ret; }); } +#ifdef FURI_DEBUG + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + index = model->index; + return false; + }); + FURI_LOG_I(TAG, "Index: %d", index); +#endif + if(event->key == InputKeyOk && event->type == InputTypeShort) { - /*if(idx == SubBruteAttackLoadFile) { + if(index == SubBruteAttackLoadFile) { instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); - } else if(idx > SubBruteAttackNone && idx < SubBruteAttackLoadFile) {*/ - instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); - /*}*/ + } else { + instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + } consumed = true; } @@ -97,10 +146,18 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { void subbrute_main_view_enter(void* context) { furi_assert(context); + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_main_view_enter"); +#endif } void subbrute_main_view_exit(void* context) { furi_assert(context); + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_main_view_exit"); +#endif } SubBruteMainView* subbrute_main_view_alloc() { @@ -113,6 +170,13 @@ SubBruteMainView* subbrute_main_view_alloc() { view_set_enter_callback(instance->view, subbrute_main_view_enter); view_set_exit_callback(instance->view, subbrute_main_view_exit); + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + model->index = 0; + model->window_position = 0; + return true; + }); + return instance; } @@ -130,10 +194,31 @@ View* subbrute_main_view_get_view(SubBruteMainView* instance) { void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { furi_assert(instance); - furi_assert(idx < SubBruteAttackTotalCount - 2); + furi_assert(idx < SubBruteAttackTotalCount - 1); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Set index: %d", idx); +#endif with_view_model( instance->view, (SubBruteMainViewModel * model) { - model->index = idx <= 0 ? 1 : idx; + model->index = idx; + model->window_position = idx; + + uint8_t items_on_screen = 3; + + if(model->window_position > 0) { + model->window_position -= 1; + } + + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= + (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = + (SubBruteAttackTotalCount - items_on_screen); + } + } + return true; }); } @@ -141,12 +226,16 @@ void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance) { furi_assert(instance); - uint8_t attack = 0; + uint8_t idx = 0; with_view_model( instance->view, (SubBruteMainViewModel * model) { - attack = model->index; + idx = model->index; return false; }); - return attack; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Get index: %d", idx); +#endif + + return idx; } \ No newline at end of file From ec9ce0cad7332d5bd2e93df33e2e653daad3df99 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 17:05:52 +0400 Subject: [PATCH 05/29] Working prototype, but not yet tested on a real device --- .../subbrute/helpers/subbrute_worker.c | 22 +- .../subbrute/helpers/subbrute_worker.h | 4 +- .../scenes/subbrute_scene_run_attack.c | 5 +- .../scenes/subbrute_scene_save_name.c | 52 +++-- .../scenes/subbrute_scene_save_success.c | 12 +- .../scenes/subbrute_scene_setup_attack.c | 51 +++- .../subbrute/scenes/subbrute_scene_start.c | 5 + applications/plugins/subbrute/subbrute.c | 89 ++++++- .../plugins/subbrute/subbrute_custom_event.h | 5 +- .../plugins/subbrute/subbrute_device.c | 221 ++++++++++++------ .../plugins/subbrute/subbrute_device.h | 12 +- applications/plugins/subbrute/subbrute_i.h | 3 +- .../subbrute/views/subbrute_attack_view.c | 170 ++++++++++---- .../subbrute/views/subbrute_attack_view.h | 13 +- 14 files changed, 465 insertions(+), 199 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index e947aaf2a..1b7b0d564 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -13,13 +13,10 @@ struct SubBruteWorker { volatile bool worker_running; SubGhzEnvironment* environment; - SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; - SubGhzProtocolDecoderBase* decoder_result; FlipperFormat* flipper_format; uint32_t last_time_tx_data; - FuriMessageQueue* event_queue; // Preset and frequency needed FuriHalSubGhzPreset preset; @@ -77,7 +74,7 @@ int32_t subbrute_worker_thread(void* context) { FURI_LOG_E(TAG, "Cannot transmit!"); break; } - furi_delay_ms(250); + furi_delay_ms(SUBBRUTE_TX_TIMEOUT); } furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); @@ -86,7 +83,9 @@ int32_t subbrute_worker_thread(void* context) { furi_hal_power_suppress_charge_exit(); subghz_transmitter_free(instance->transmitter); + instance->transmitter = NULL; subghz_environment_free(instance->environment); + instance->environment = NULL; #ifdef FURI_DEBUG FURI_LOG_I(TAG, "Worker stop"); @@ -118,6 +117,7 @@ void subbrute_worker_free(SubBruteWorker* instance) { furi_thread_free(instance->thread); flipper_format_free(instance->flipper_format); + string_clear(instance->protocol_name); free(instance); @@ -127,13 +127,15 @@ bool subbrute_worker_start( SubBruteWorker* instance, uint32_t frequency, FuriHalSubGhzPreset preset, - string_t protocol_name) { + const char* protocol_name) { furi_assert(instance); furi_assert(!instance->worker_running); instance->frequency = frequency; instance->preset = preset; - string_init_move(instance->protocol_name, protocol_name); + + string_clear(instance->protocol_name); + string_init_set_str(instance->protocol_name, protocol_name); bool res = false; @@ -183,7 +185,7 @@ bool subbrute_worker_can_transmit(SubBruteWorker* instance) { return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY; } -bool subbrute_worker_transmit(SubBruteWorker* instance, string_t payload) { +bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) { furi_assert(instance); furi_assert(instance->worker_running); @@ -194,9 +196,13 @@ bool subbrute_worker_transmit(SubBruteWorker* instance, string_t payload) { } instance->last_time_tx_data = furi_get_tick(); +#ifdef FURI_DEBUG + //FURI_LOG_D(TAG, "payload: %s", payload); +#endif + Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); stream_clean(stream); - stream_write_cstring(stream, string_get_cstr(payload)); + stream_write_cstring(stream, payload); subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); return true; diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h index d0ed3cbf7..56f48743a 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.h +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -24,9 +24,9 @@ bool subbrute_worker_start( SubBruteWorker* instance, uint32_t frequency, FuriHalSubGhzPreset preset, - string_t protocol_name); + const char* protocol_name); void subbrute_worker_stop(SubBruteWorker* instance); //bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size); bool subbrute_worker_is_running(SubBruteWorker* instance); bool subbrute_worker_can_transmit(SubBruteWorker* instance); -bool subbrute_worker_transmit(SubBruteWorker* instance, string_t payload); \ No newline at end of file +bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload); \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c index 59c5b8ef0..55431cdd0 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -29,14 +29,15 @@ void subbrute_scene_run_attack_on_enter(void* context) { view, (uint8_t)instance->device->attack, instance->device->max_value, - instance->device->key_index); + instance->device->key_index, + true); // Start worker if not started subbrute_attack_view_start_worker( view, instance->device->frequency, instance->device->preset, - instance->device->protocol_name); + string_get_cstr(instance->device->protocol_name)); } bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c index 0400bbe5a..9dc8f7a77 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c @@ -6,55 +6,65 @@ #include "../subbrute_i.h" #include "../subbrute_custom_event.h" -#include "../views/subbrute_attack_view.h" #define TAG "SubBruteSceneSaveFile" void subbrute_scene_save_name_on_enter(void* context) { SubBruteState* instance = (SubBruteState*)context; + SubBruteDevice* device = instance->device; // Setup view TextInput* text_input = instance->text_input; - set_random_name(instance->device->text_store, sizeof(instance->device->text_store)); + set_random_name(device->text_store, sizeof(device->text_store)); text_input_set_header_text(text_input, "Name of file"); text_input_set_result_callback( text_input, subbrute_text_input_callback, instance, - instance->device->text_store, + device->text_store, SUBBRUTE_MAX_LEN_NAME, true); - string_t folder_path; - string_init(folder_path); - - SubBruteDevice* device = instance->device; - if(string_end_with_str_p(device->load_path, SUBBRUTE_FILE_EXT)) { - path_extract_dirname(string_get_cstr(device->load_path), folder_path); - } else { - string_set_str(folder_path, SUBBRUTE_PATH); - } + string_set_str(device->load_path, SUBBRUTE_PATH); ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(string_get_cstr(folder_path), SUBBRUTE_FILE_EXT, TAG); + validator_is_file_alloc_init(string_get_cstr(device->load_path), SUBBRUTE_FILE_EXT, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewTextInput); - - string_clear(folder_path); } bool subbrute_scene_save_name_on_event(void* context, SceneManagerEvent event) { SubBruteState* instance = (SubBruteState*)context; bool consumed = false; - if(event.type == SceneManagerEventTypeCustom && - event.event == SubBruteCustomEventTypeTextEditDone) { - if(subbrute_device_save_file(instance->device, instance->device->text_store)) { - scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveSuccess); - consumed = true; - } else { + if(event.type == SceneManagerEventTypeBack) { + scene_manager_previous_scene(instance->scene_manager); + return true; + } else if( + event.type == SceneManagerEventTypeCustom && + event.event == SubBruteCustomEventTypeTextEditDone) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Saving: %s", instance->device->text_store); +#endif + bool success = false; + if(strcmp(instance->device->text_store, "")) { + string_cat_printf( + instance->device->load_path, + "/%s%s", + instance->device->text_store, + SUBBRUTE_FILE_EXT); + + if(subbrute_device_save_file( + instance->device, string_get_cstr(instance->device->load_path))) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveSuccess); + success = true; + consumed = true; + } + } + + if(!success) { dialog_message_show_storage_error(instance->dialogs, "Error during saving!"); consumed = scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, SubBruteSceneSetupAttack); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c index 5f12c23c6..7f0e28809 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c @@ -1,13 +1,5 @@ #include "../subbrute_i.h" #include "../subbrute_custom_event.h" -#include "../views/subbrute_attack_view.h" - -void subbrute_scene_save_success_callback(void* context) { - furi_assert(context); - - SubBruteState* instance = (SubBruteState*)context; - view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeSaveSuccess); -} void subbrute_scene_save_success_on_enter(void* context) { furi_assert(context); @@ -19,7 +11,7 @@ void subbrute_scene_save_success_on_enter(void* context) { popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, instance); - popup_set_callback(popup, subbrute_scene_save_success_callback); + popup_set_callback(popup, subbrute_popup_closed_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewPopup); } @@ -31,7 +23,7 @@ bool subbrute_scene_save_success_on_event(void* context, SceneManagerEvent event //SubBruteMainView* view = instance->view_main; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubBruteCustomEventTypeSaveSuccess) { + if(event.event == SubBruteCustomEventTypePopupClosed) { if(!scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, SubBruteSceneSetupAttack)) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index cc764b6ec..67bf3b4f9 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -2,6 +2,8 @@ #include "../subbrute_custom_event.h" #include "../views/subbrute_attack_view.h" +#define TAG "SubBruteSceneSetupAttack" + static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void* context) { furi_assert(context); @@ -14,23 +16,27 @@ void subbrute_scene_setup_attack_on_enter(void* context) { SubBruteState* instance = (SubBruteState*)context; SubBruteAttackView* view = instance->view_attack; - instance->current_view = SubBruteViewAttack; - subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); - view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Enter Attack: %d", instance->device->attack); +#endif - instance->device->key_index = subbrute_attack_view_get_current_step(view); subbrute_attack_view_init_values( view, - (uint8_t)instance->device->attack, + instance->device->attack, instance->device->max_value, - instance->device->key_index); + instance->device->key_index, + false); // Run worker anyway subbrute_attack_view_start_worker( view, instance->device->frequency, instance->device->preset, - instance->device->protocol_name); + string_get_cstr(instance->device->protocol_name)); + + instance->current_view = SubBruteViewAttack; + subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } void subbrute_scene_setup_attack_on_exit(void* context) { @@ -41,17 +47,40 @@ void subbrute_scene_setup_attack_on_exit(void* context) { bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event) { SubBruteState* instance = (SubBruteState*)context; - SubBruteAttackView * view = instance->view_attack; + SubBruteAttackView* view = instance->view_attack; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeTransmitStarted) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); - } else if (event.event == SubBruteCustomEventTypeBackPressed) { + } else if (event.event == SubBruteCustomEventTypeSaveFile) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName); + } else if(event.event == SubBruteCustomEventTypeBackPressed) { subbrute_attack_view_stop_worker(view); + instance->device->key_index = 0x00; scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); - } else if (event.event == SubBruteCustomEventTypeChangeStep) { - instance->device->key_index = subbrute_attack_view_get_current_step(view); + } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { + // +1 + instance->device->key_index = + (instance->device->key_index + 1) % instance->device->max_value; + subbrute_attack_view_set_current_step(view, instance->device->key_index); + } else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) { + // +100 + instance->device->key_index = + (instance->device->key_index + 100) % instance->device->max_value; + subbrute_attack_view_set_current_step(view, instance->device->key_index); + } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { + // -1 + instance->device->key_index = + ((instance->device->key_index - 1) + instance->device->max_value) % + instance->device->max_value; + subbrute_attack_view_set_current_step(view, instance->device->key_index); + } else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) { + // -100 + instance->device->key_index = + ((instance->device->key_index - 100) + instance->device->max_value) % + instance->device->max_value; + subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { if(subbrute_attack_view_can_send(view)) { // Blink diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index 4b10d3865..beefafa58 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -57,6 +57,11 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); consumed = true; } + } else if (event.type == SceneManagerEventTypeBack) { + //exit app + scene_manager_stop(instance->scene_manager); + view_dispatcher_stop(instance->view_dispatcher); + consumed = true; } return consumed; diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index 878b112e4..b54911fdb 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -34,6 +34,20 @@ static const char* subbrute_menu_names[] = { [SubBruteAttackTotalCount] = "Total Count", }; +static const char* subbrute_menu_names_small[] = { + [SubBruteAttackCAME12bit307] = "CAME 307mhz", + [SubBruteAttackCAME12bit433] = "CAME 433mhz", + [SubBruteAttackCAME12bit868] = "CAME 868mhz", + [SubBruteAttackChamberlain9bit315] = "Cham 315mhz", + [SubBruteAttackChamberlain9bit390] = "Cham 390mhz", + [SubBruteAttackLinear10bit300] = "Linear 300mhz", + [SubBruteAttackLinear10bit310] = "Linear 310mhz", + [SubBruteAttackNICE12bit433] = "NICE 433mhz", + [SubBruteAttackNICE12bit868] = "NICE 868mhz", + [SubBruteAttackLoadFile] = "Existing", + [SubBruteAttackTotalCount] = "Total Count", +}; + static bool subbrute_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubBruteState* instance = context; @@ -81,8 +95,10 @@ SubBruteState* subbrute_alloc() { // TextInput instance->text_input = text_input_alloc(); view_dispatcher_add_view( - instance->view_dispatcher, SubBruteViewTextInput, text_input_get_view(instance->text_input)); - + instance->view_dispatcher, + SubBruteViewTextInput, + text_input_get_view(instance->text_input)); + // Custom Widget instance->widget = widget_alloc(); view_dispatcher_add_view( @@ -90,7 +106,8 @@ SubBruteState* subbrute_alloc() { // Popup instance->popup = popup_alloc(); - view_dispatcher_add_view(instance->view_dispatcher, SubBruteViewPopup, popup_get_view(instance->popup)); + view_dispatcher_add_view( + instance->view_dispatcher, SubBruteViewPopup, popup_get_view(instance->popup)); // ViewStack instance->view_stack = view_stack_alloc(); @@ -122,56 +139,98 @@ SubBruteState* subbrute_alloc() { void subbrute_free(SubBruteState* instance) { furi_assert(instance); + // SubBruteDevice +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteDevice"); +#endif + subbrute_device_free(instance->device); + // Notifications +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free Notifications"); +#endif notification_message(instance->notifications, &sequence_blink_stop); furi_record_close(RECORD_NOTIFICATION); instance->notifications = NULL; // Loading +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free loading"); +#endif loading_free(instance->loading); // View Main +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewMain"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewMain); subbrute_main_view_free(instance->view_main); // View Attack +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewAttack"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewAttack); subbrute_attack_view_free(instance->view_attack); // TextInput +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewTextInput"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewTextInput); text_input_free(instance->text_input); // Custom Widget +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewWidget"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewWidget); widget_free(instance->widget); // Popup +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewPopup"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewPopup); popup_free(instance->popup); // ViewStack +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteViewStack"); +#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewStack); view_stack_free(instance->view_stack); //Dialog +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free RECORD_DIALOGS"); +#endif furi_record_close(RECORD_DIALOGS); instance->dialogs = NULL; // Scene manager +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free scene_manager"); +#endif scene_manager_free(instance->scene_manager); // View Dispatcher +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free view_dispatcher"); +#endif view_dispatcher_free(instance->view_dispatcher); // GUI +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free RECORD_GUI"); +#endif furi_record_close(RECORD_GUI); instance->gui = NULL; - // SubBruteDevice - subbrute_device_free(instance->device); - // The rest +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free instance"); +#endif free(instance); } @@ -196,7 +255,7 @@ void subbrute_text_input_callback(void* context) { furi_assert(context); SubBruteState* instance = context; view_dispatcher_send_custom_event( - instance->view_dispatcher, SubBruteCustomEventTypeTextEditResult); + instance->view_dispatcher, SubBruteCustomEventTypeTextEditDone); } void subbrute_popup_closed_callback(void* context) { @@ -212,11 +271,17 @@ const char* subbrute_get_menu_name(SubBruteAttacks index) { return subbrute_menu_names[index]; } +const char* subbrute_get_small_menu_name(SubBruteAttacks index) { + furi_assert(index < SubBruteAttackTotalCount); + + return subbrute_menu_names_small[index]; +} + // ENTRYPOINT int32_t subbrute_app(void* p) { UNUSED(p); #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "subbrute_app"); + FURI_LOG_D(TAG, "subbrute_app"); #endif SubBruteState* instance = subbrute_alloc(); #ifdef FURI_DEBUG @@ -234,8 +299,12 @@ int32_t subbrute_app(void* p) { #endif view_dispatcher_run(instance->view_dispatcher); furi_hal_power_suppress_charge_exit(); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "before subbrute_free"); +#endif subbrute_free(instance); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "return 0"); +#endif return 0; } \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_custom_event.h b/applications/plugins/subbrute/subbrute_custom_event.h index 6a5a9f08e..c3b04ebdf 100644 --- a/applications/plugins/subbrute/subbrute_custom_event.h +++ b/applications/plugins/subbrute/subbrute_custom_event.h @@ -15,7 +15,10 @@ typedef enum { SubBruteCustomEventTypeTransmitCustom, SubBruteCustomEventTypeSaveFile, SubBruteCustomEventTypeSaveSuccess, - SubBruteCustomEventTypeChangeStep, + SubBruteCustomEventTypeChangeStepUp, + SubBruteCustomEventTypeChangeStepDown, + SubBruteCustomEventTypeChangeStepUpMore, + SubBruteCustomEventTypeChangeStepDownMore, SubBruteCustomEventTypeMenuSelected, SubBruteCustomEventTypeTextEditDone, diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 200720e89..93ef80dc6 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -34,9 +34,9 @@ static const char* protocol_raw = "RAW"; * Values to not use less memory for packet parse operations */ static const char* subbrute_key_file_start = - "Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\n"; -static const char* subbrute_key_file_key = "Key: %s\n"; -static const char* subbrute_key_file_princeton_end = "TE: %d\n"; + "Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d"; +static const char* subbrute_key_file_key = "%s\nKey: %s\n"; +static const char* subbrute_key_file_princeton_end = "%s\nKey: %s\nTE: %d\n"; // Why nobody set in as const in all codebase? static const char* preset_ook270_async = "FuriHalSubGhzPresetOok270Async"; @@ -54,11 +54,13 @@ SubBruteDevice* subbrute_device_alloc() { instance->dialogs = furi_record_open(RECORD_DIALOGS); string_init(instance->load_path); - - string_init(instance->payload); string_init(instance->preset_name); string_init(instance->protocol_name); + instance->decoder_result = NULL; + instance->receiver = NULL; + instance->environment = NULL; + subbrute_device_attack_set_default_values(instance); return instance; @@ -66,16 +68,38 @@ SubBruteDevice* subbrute_device_alloc() { void subbrute_device_free(SubBruteDevice* instance) { furi_assert(instance); - +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_free"); +#endif furi_record_close(RECORD_DIALOGS); - string_clear(instance->payload); + // I don't know how to free this + instance->decoder_result = NULL; + + if(instance->receiver != NULL) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subghz_receiver_free"); +#endif + subghz_receiver_free(instance->receiver); + instance->receiver = NULL; + } + + if(instance->environment != NULL) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subghz_environment_free"); +#endif + subghz_environment_free(instance->environment); + instance->environment = NULL; + } + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "before free"); +#endif + string_clear(instance->load_path); string_clear(instance->preset_name); string_clear(instance->protocol_name); - string_clear(instance->load_path); - free(instance); } @@ -143,7 +167,7 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na buffered_file_stream_close(stream); break; } - stream_write_string(stream, instance->payload); + stream_write_cstring(stream, instance->payload); result = true; } while(false); @@ -210,36 +234,72 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) { return result; } -bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint8_t step) { +bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t step) { furi_assert(instance); - char step_payload[SUBBRUTE_PAYLOAD_SIZE] = {0}; - string_reset(instance->payload); + //char step_payload[32]; + //memset(step_payload, '0', sizeof(step_payload)); + memset(instance->payload, 0, sizeof(instance->payload)); + string_t candidate; + string_init(candidate); if(instance->attack == SubBruteAttackLoadFile) { if(step >= sizeof(instance->file_key)) { return false; } - snprintf( - step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); + char subbrute_payload_byte[4]; + string_set_str(candidate, instance->file_key); + snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)instance->file_key[step]); + string_replace_at(candidate, step, 3, subbrute_payload_byte); + //snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); } else { //snprintf(step_payload, sizeof(step_payload), "%16X", step); - snprintf(step_payload, sizeof(step_payload), "%02X", step); + //snprintf(step_payload, sizeof(step_payload), "%016llX", step); + string_t buffer; + string_init(buffer); + string_init_printf(buffer, "%16X", step); + int j = 0; + string_set_str(candidate, " "); + for(uint8_t i = 0; i < 16; i++) { + if(string_get_char(buffer, i) != ' ') { + string_set_char(candidate, i + j, string_get_char(buffer, i)); + } else { + string_set_char(candidate, i + j, '0'); + } + if(i % 2 != 0) { + j++; + } + } + string_clear(buffer); } + #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "step_payload: %s, step: %d", step_payload, step); + FURI_LOG_D(TAG, "candidate: %s, step: %d", string_get_cstr(candidate), step); #endif + if(instance->has_tail) { - string_init_printf( + snprintf( instance->payload, + sizeof(instance->payload), + subbrute_key_file_princeton_end, instance->file_template, - step_payload, + string_get_cstr(candidate), instance->te); } else { - string_init_printf( - instance->payload, instance->file_template, step_payload); + snprintf( + instance->payload, + sizeof(instance->payload), + subbrute_key_file_key, + instance->file_template, + string_get_cstr(candidate)); } +#ifdef FURI_DEBUG + //FURI_LOG_D(TAG, "payload: %s", instance->payload); +#endif + + string_clear(candidate); + return true; } @@ -254,6 +314,8 @@ SubBruteFileResult subbrute_device_attack_set( subbrute_device_attack_set_default_values(instance); uint8_t file_result; + instance->attack = type; + switch(type) { case SubBruteAttackLoadFile: file_result = subbrute_device_load_from_file(instance, file_path); @@ -274,43 +336,43 @@ SubBruteFileResult subbrute_device_attack_set( } instance->bit = 12; string_set_str(instance->protocol_name, protocol_came); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackChamberlain9bit315: instance->frequency = 315000000; instance->bit = 9; string_set_str(instance->protocol_name, protocol_cham_code); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackChamberlain9bit390: instance->frequency = 390000000; instance->bit = 9; string_set_str(instance->protocol_name, protocol_cham_code); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackLinear10bit300: instance->frequency = 300000000; instance->bit = 10; string_set_str(instance->protocol_name, protocol_linear); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackLinear10bit310: instance->frequency = 310000000; instance->bit = 10; string_set_str(instance->protocol_name, protocol_linear); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackNICE12bit433: instance->frequency = 433920000; instance->bit = 12; string_set_str(instance->protocol_name, protocol_nice_flo); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; case SubBruteAttackNICE12bit868: instance->frequency = 868350000; instance->bit = 12; string_set_str(instance->protocol_name, protocol_nice_flo); - //string_set_str(instance->preset_name, preset_ook650_async); + string_set_str(instance->preset_name, preset_ook650_async); break; default: FURI_LOG_E(TAG, "Unknown attack type: %d", type); @@ -341,20 +403,21 @@ SubBruteFileResult subbrute_device_attack_set( } } else { // And here we need to set preset enum - instance->preset = subbrute_device_convert_preset(instance->preset_name); + instance->preset = subbrute_device_convert_preset(string_get_cstr(instance->preset_name)); protocol_check_result = SubBruteFileResultOk; } subghz_environment_free(instance->environment); subghz_receiver_free(instance->receiver); + instance->receiver = NULL; + instance->environment = NULL; if(protocol_check_result != SubBruteFileResultOk) { return SubBruteFileResultProtocolNotFound; } - if(strcmp(string_get_cstr(instance->protocol_name), protocol_princeton) == 0) { - instance->has_tail = true; - } + instance->has_tail = + (strcmp(string_get_cstr(instance->protocol_name), protocol_princeton) == 0); // Calc max value if(instance->attack == SubBruteAttackLoadFile) { @@ -379,16 +442,20 @@ SubBruteFileResult subbrute_device_attack_set( string_get_cstr(instance->preset_name), string_get_cstr(instance->protocol_name), instance->bit); - strncat( - instance->file_template, - subbrute_key_file_key, - sizeof(instance->file_template)); - if(instance->has_tail) { - strncat( - instance->file_template, - subbrute_key_file_princeton_end, - sizeof(instance->file_template)); - } +// strncat(instance->file_template, "\n", sizeof(instance->file_template)); +// strncat(instance->file_template, subbrute_key_file_key, sizeof(instance->file_template)); +// if(instance->has_tail) { +// strncat( +// instance->file_template, +// subbrute_key_file_princeton_end, +// sizeof(instance->file_template)); +// } +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "tail: %d, file_template: %s", instance->has_tail, instance->file_template); +#endif + + // Init payload + subbrute_device_create_packet_parsed(instance, instance->key_index); return SubBruteFileResultOk; } @@ -442,8 +509,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil result = SubBruteFileResultPresetInvalid; } // Protocol - if(!flipper_format_read_string( - fff_data_file, "Protocol", instance->protocol_name)) { + if(!flipper_format_read_string(fff_data_file, "Protocol", instance->protocol_name)) { FURI_LOG_E(TAG, "Missing Protocol"); result = SubBruteFileResultMissingProtocol; break; @@ -500,10 +566,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil break; } else { snprintf( - instance->file_key, - sizeof(instance->file_key), - "%s", - string_get_cstr(temp_str)); + instance->file_key, sizeof(instance->file_key), "%s", string_get_cstr(temp_str)); } // TE @@ -540,6 +603,9 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil subghz_environment_free(instance->environment); subghz_receiver_free(instance->receiver); + instance->receiver = NULL; + instance->environment = NULL; + if(result == SubBruteFileResultOk) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "Loaded successfully"); @@ -556,42 +622,55 @@ void subbrute_device_attack_set_default_values(SubBruteDevice* instance) { #endif instance->attack = SubBruteAttackCAME12bit307; instance->max_value = 0; - instance->key_index = 0; + instance->key_index = 0x00; memset(instance->file_template, 0, sizeof(instance->file_template)); memset(instance->current_key, 0, sizeof(instance->current_key)); memset(instance->file_key, 0, sizeof(instance->file_key)); + memset(instance->text_store, 0, sizeof(instance->text_store)); + memset(instance->payload, 0, sizeof(instance->payload)); - string_set_str(instance->protocol_name, protocol_raw); + string_clear(instance->protocol_name); + string_clear(instance->preset_name); + string_clear(instance->load_path); - string_set_str(instance->preset_name, preset_ook650_async); + string_init(instance->load_path); + + string_init_set_str(instance->protocol_name, protocol_raw); + string_init_set_str(instance->preset_name, preset_ook650_async); instance->preset = FuriHalSubGhzPresetOok650Async; - string_reset(instance->payload); - instance->repeat = 5; instance->te = 0; instance->has_tail = false; + +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, "subbrute_device_attack_set_default_values done. has_tail: %d", instance->has_tail); + //furi_delay_ms(250); +#endif } -FuriHalSubGhzPreset subbrute_device_convert_preset(string_t preset) { +FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset_name) { + string_t preset; + string_init_set_str(preset, preset_name); + FuriHalSubGhzPreset preset_value; if(string_cmp_str(preset, preset_ook270_async) == 0) { - return FuriHalSubGhzPresetOok270Async; + preset_value = FuriHalSubGhzPresetOok270Async; + } else if(string_cmp_str(preset, preset_ook650_async) == 0) { + preset_value = FuriHalSubGhzPresetOok650Async; + } else if(string_cmp_str(preset, preset_2fsk_dev238_async) == 0) { + preset_value = FuriHalSubGhzPreset2FSKDev238Async; + } else if(string_cmp_str(preset, preset_2fsk_dev476_async) == 0) { + preset_value = FuriHalSubGhzPreset2FSKDev476Async; + } else if(string_cmp_str(preset, preset_msk99_97_kb_async) == 0) { + preset_value = FuriHalSubGhzPresetMSK99_97KbAsync; + } else if(string_cmp_str(preset, preset_gfs99_97_kb_async) == 0) { + preset_value = FuriHalSubGhzPresetMSK99_97KbAsync; + } else { + preset_value = FuriHalSubGhzPresetCustom; } - if(string_cmp_str(preset, preset_ook650_async) == 0) { - return FuriHalSubGhzPresetOok650Async; - } - if(string_cmp_str(preset, preset_2fsk_dev238_async) == 0) { - return FuriHalSubGhzPreset2FSKDev238Async; - } - if(string_cmp_str(preset, preset_2fsk_dev476_async) == 0) { - return FuriHalSubGhzPreset2FSKDev476Async; - } - if(string_cmp_str(preset, preset_msk99_97_kb_async) == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - if(string_cmp_str(preset, preset_gfs99_97_kb_async) == 0) { - return FuriHalSubGhzPresetMSK99_97KbAsync; - } - return FuriHalSubGhzPresetCustom; + + string_clear(preset); + return preset_value; } diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index fea7563e4..a6fdeef58 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -14,7 +14,7 @@ #define SUBBRUTE_PATH EXT_PATH("subghz") #define SUBBRUTE_FILE_EXT ".sub" -#define SUBBRUTE_PAYLOAD_SIZE 8 +#define SUBBRUTE_PAYLOAD_SIZE 16 typedef enum { SubBruteAttackCAME12bit307, @@ -59,7 +59,7 @@ typedef struct { SubBruteDeviceState state; // Current step - uint8_t key_index; + uint64_t key_index; string_t load_path; SubGhzReceiver* receiver; @@ -70,8 +70,8 @@ typedef struct { SubBruteAttacks attack; char file_template[SUBBRUTE_TEXT_STORE_SIZE]; bool has_tail; - string_t payload; - uint8_t max_value; + char payload[SUBBRUTE_TEXT_STORE_SIZE * 2]; + uint64_t max_value; // Loaded info for attack type FuriHalSubGhzPreset preset; @@ -92,11 +92,11 @@ void subbrute_device_free(SubBruteDevice* instance); SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance); bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name); const char* subbrute_device_error_get_desc(SubBruteFileResult error_id); -bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint8_t step); +bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint64_t step); SubBruteFileResult subbrute_device_attack_set( SubBruteDevice* context, SubBruteAttacks type, const char* file_path); uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path); -FuriHalSubGhzPreset subbrute_device_convert_preset(string_t preset); +FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset); void subbrute_device_attack_set_default_values(SubBruteDevice* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_i.h b/applications/plugins/subbrute/subbrute_i.h index 518631f3a..51c84c898 100644 --- a/applications/plugins/subbrute/subbrute_i.h +++ b/applications/plugins/subbrute/subbrute_i.h @@ -77,4 +77,5 @@ struct SubBruteState { void subbrute_show_loading_popup(void* context, bool show); void subbrute_text_input_callback(void* context); void subbrute_popup_closed_callback(void* context); -const char* subbrute_get_menu_name(uint8_t index); \ No newline at end of file +const char* subbrute_get_menu_name(uint8_t index); +const char* subbrute_get_small_menu_name(uint8_t index); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index 18eac8125..395e4b06e 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -18,8 +18,8 @@ struct SubBruteAttackView { typedef struct { SubBruteAttacks index; - uint8_t max_value; - uint8_t current_step; + uint64_t max_value; + uint64_t current_step; bool is_attacking; } SubBruteAttackViewModel; @@ -44,6 +44,11 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { if(event->key == InputKeyBack && event->type == InputTypeShort) { instance->callback(SubBruteCustomEventTypeBackPressed, instance->context); + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->is_attacking = false; + return true; + }); return true; } @@ -62,7 +67,11 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { // } if(!is_attacking) { - if(event->key == InputKeyOk) { + if((event->type == InputTypeShort || event->type == InputTypeRepeat) && + event->key == InputKeyOk) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "InputKey: %d OK", event->key); +#endif with_view_model( instance->view, (SubBruteAttackViewModel * model) { model->is_attacking = true; @@ -76,11 +85,39 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { // instance->callback(SubBruteCustomEventTypeBackPressed, instance->context); // } } else if(event->key == InputKeyUp) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "InputKey: %d UP", event->key); +#endif instance->callback(SubBruteCustomEventTypeSaveFile, instance->context); } else if(event->key == InputKeyDown) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "InputKey: %d DOWN", event->key); +#endif instance->callback(SubBruteCustomEventTypeTransmitCustom, instance->context); - } else if(event->type == InputTypePress) { - with_view_model( + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyLeft) { + instance->callback(SubBruteCustomEventTypeChangeStepDown, instance->context); + } else if(event->key == InputKeyRight) { + instance->callback(SubBruteCustomEventTypeChangeStepUp, instance->context); + } + // with_view_model( + // instance->view, (SubBruteAttackViewModel * model) { + // if(event->key == InputKeyLeft) { + // model->current_step = + // ((model->current_step - 1) + model->max_value) % model->max_value; + // } else if(event->key == InputKeyRight) { + // model->current_step = (model->current_step + 1) % model->max_value; + // } + // return true; + // }); + // instance->callback(SubBruteCustomEventTypeChangeStep, instance->context); + } else if(event->type == InputTypeRepeat) { + if(event->key == InputKeyLeft) { + instance->callback(SubBruteCustomEventTypeChangeStepDownMore, instance->context); + } else if(event->key == InputKeyRight) { + instance->callback(SubBruteCustomEventTypeChangeStepUpMore, instance->context); + } + /*with_view_model( instance->view, (SubBruteAttackViewModel * model) { if(event->key == InputKeyLeft) { model->current_step = @@ -90,19 +127,7 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { } return true; }); - instance->callback(SubBruteCustomEventTypeChangeStep, instance->context); - } else if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - with_view_model( - instance->view, (SubBruteAttackViewModel * model) { - if(event->key == InputKeyLeft) { - model->current_step = - ((model->current_step - 1) + model->max_value) % model->max_value; - } else if(event->key == InputKeyRight) { - model->current_step = (model->current_step + 1) % model->max_value; - } - return true; - }); - instance->callback(SubBruteCustomEventTypeChangeStep, instance->context); + instance->callback(SubBruteCustomEventTypeChangeStep, instance->context);*/ } } else { if((event->type == InputTypeShort || event->type == InputTypeRepeat) && @@ -146,6 +171,9 @@ void subbrute_attack_view_enter(void* context) { void subbrute_attack_view_free(SubBruteAttackView* instance) { furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_attack_view_free"); +#endif subbrute_worker_free(instance->worker); view_free(instance->view); @@ -157,7 +185,8 @@ View* subbrute_attack_view_get_view(SubBruteAttackView* instance) { return instance->view; } -void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t current_step) { +void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint64_t current_step) { + furi_assert(instance); #ifdef FURI_DEBUG FURI_LOG_D(TAG, "Set step: %d", current_step); #endif @@ -168,8 +197,8 @@ void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t }); } -uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance) { - uint8_t current_step; +uint64_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance) { + uint64_t current_step; with_view_model( instance->view, (SubBruteAttackViewModel * model) { current_step = model->current_step; @@ -186,25 +215,33 @@ uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance) { void subbrute_attack_view_init_values( SubBruteAttackView* instance, uint8_t index, - uint8_t max_value, - uint8_t current_step) { + uint64_t max_value, + uint64_t current_step, + bool is_attacking) { +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, "init, index: %d, max_value: %d, current_step: %d", index, max_value, current_step); +#endif with_view_model( instance->view, (SubBruteAttackViewModel * model) { model->max_value = max_value; model->index = index; model->current_step = current_step; + model->is_attacking = is_attacking; return true; }); } void subbrute_attack_view_stop_worker(SubBruteAttackView* instance) { furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_attack_view_stop_worker"); +#endif subbrute_worker_stop(instance->worker); } bool subbrute_attack_view_can_send(SubBruteAttackView* instance) { furi_assert(instance); - return subbrute_worker_can_transmit(instance->worker); } @@ -212,14 +249,22 @@ void subbrute_attack_view_start_worker( SubBruteAttackView* instance, uint32_t frequency, FuriHalSubGhzPreset preset, - string_t protocol_name) { + const char* protocol_name) { furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, + "start_worker. frequency: %d, preset: %d, protocol_name: %s", + frequency, + preset, + protocol_name); +#endif if(!subbrute_worker_is_running(instance->worker)) { subbrute_worker_start(instance->worker, frequency, preset, protocol_name); } } -bool subbrute_attack_view_transmit(SubBruteAttackView* instance, string_t payload) { +bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* payload) { furi_assert(instance); return subbrute_worker_transmit(instance->worker, payload); @@ -245,21 +290,25 @@ void elements_button_top_left(Canvas* canvas, const char* str) { const Icon* icon = &I_ButtonUp_7x4; const uint8_t button_height = 12; - const uint8_t vertical_offset = 3; + const uint8_t vertical_offset = 9; // const uint8_t horizontal_offset = 3; const uint8_t string_width = canvas_string_width(canvas, str); const uint8_t icon_h_offset = 3; const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height + vertical_offset; - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + const uint8_t icon_v_offset = icon->height; // + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1; const uint8_t x = 0; const uint8_t y = 0; - canvas_draw_box(canvas, x, y - button_height, button_width, button_height); - canvas_draw_line(canvas, x + button_width - 0, y, x + button_width - 0, y + button_height - 0); - canvas_draw_line(canvas, x + button_width - 1, y, x + button_width - 1, y + button_height - 1); - canvas_draw_line(canvas, x + button_width - 2, y, x + button_width - 2, y + button_height - 2); + canvas_draw_box(canvas, x, y, button_width, button_height); +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, "lbox, x: %d, y: %d, width: %d, height: %d", x, y, button_width, button_height); +#endif + // canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y + button_height - 0); // + // canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y + button_height - 1); + // canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y + button_height - 2); canvas_invert_color(canvas); canvas_draw_icon(canvas, x + horizontal_offset, y + icon_v_offset, icon); @@ -272,45 +321,66 @@ void elements_button_top_right(Canvas* canvas, const char* str) { const Icon* icon = &I_ButtonDown_7x4; const uint8_t button_height = 12; - const uint8_t vertical_offset = 3; + const uint8_t vertical_offset = 9; const uint8_t horizontal_offset = 3; const uint8_t string_width = canvas_string_width(canvas, str); const uint8_t icon_h_offset = 3; const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height + vertical_offset; - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + const uint8_t icon_v_offset = icon->height; // + vertical_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1; const uint8_t x = canvas_width(canvas); const uint8_t y = 0; - canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height); - canvas_draw_line(canvas, x - button_width - 1, y, x + button_width + 1, y + button_height - 0); - canvas_draw_line(canvas, x - button_width - 2, y, x + button_width + 2, y + button_height - 1); - canvas_draw_line(canvas, x - button_width - 3, y, x + button_width + 3, y + button_height - 2); + canvas_draw_box(canvas, x - button_width, y, button_width, button_height); +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, + "rbox, x: %d, y: %d, width: %d, height: %d", + x - button_width, + y, + button_width, + button_height); +#endif + // canvas_draw_line(canvas, x - button_width - 1, y, x + button_width - 1, y + button_height - 0); + // canvas_draw_line(canvas, x - button_width - 2, y, x + button_width - 2, y + button_height - 1); + // canvas_draw_line(canvas, x - button_width - 3, y, x + button_width - 3, y + button_height - 2); canvas_invert_color(canvas); - canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str); - canvas_draw_icon(canvas, x - horizontal_offset - icon->width, y - icon_v_offset, icon); + canvas_draw_str(canvas, x - button_width + horizontal_offset, y + vertical_offset, str); + canvas_draw_icon(canvas, x - horizontal_offset - icon->width, y + icon_v_offset, icon); canvas_invert_color(canvas); } void subbrute_attack_view_draw(Canvas* canvas, void* context) { furi_assert(context); SubBruteAttackViewModel* model = (SubBruteAttackViewModel*)context; - //char buffer[64]; + char buffer[26]; - // Title const char* attack_name = NULL; attack_name = subbrute_get_menu_name(model->index); - canvas_set_color(canvas, ColorBlack); + // Title + if(model->is_attacking) { + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, attack_name); + } + // Value + canvas_set_font(canvas, FontBigNumbers); + snprintf(buffer, sizeof(buffer), "%04d/%04d", (int)model->current_step, (int)model->max_value); + canvas_draw_str_aligned(canvas, 64, 17, AlignCenter, AlignTop, buffer); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 20, 8, attack_name ? attack_name : "Sub-GHz Bruteforcer"); // Progress bar // Resolution: 128x64 px - float progress_value = model->max_value / model->current_step; - elements_progress_bar(canvas, 8, 30, 98, progress_value > 1 ? 1 : progress_value); - + if (model->is_attacking) { + float progress_value = (float)model->current_step / model->max_value; + elements_progress_bar(canvas, 8, 37, 110, progress_value > 1 ? 1 : progress_value); + } else { + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignBottom, attack_name); + } // Selected attack type // const char* attack_name = NULL; // attack_name = subbrute_get_menu_name(model->index); @@ -328,7 +398,7 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) { elements_button_right(canvas, "+1"); elements_button_center(canvas, "Start"); elements_button_top_left(canvas, "Save"); - elements_button_top_right(canvas, "Repeat"); + elements_button_top_right(canvas, "Resend"); } else { elements_button_center(canvas, "Stop"); } diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.h b/applications/plugins/subbrute/views/subbrute_attack_view.h index 253b42adf..3858f7ec2 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.h +++ b/applications/plugins/subbrute/views/subbrute_attack_view.h @@ -18,19 +18,20 @@ void subbrute_attack_view_set_callback( SubBruteAttackView* subbrute_attack_view_alloc(); void subbrute_attack_view_free(SubBruteAttackView* instance); View* subbrute_attack_view_get_view(SubBruteAttackView* instance); -void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint8_t current_step); -uint8_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance); +void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint64_t current_step); +uint64_t subbrute_attack_view_get_current_step(SubBruteAttackView* instance); void subbrute_attack_view_init_values( SubBruteAttackView* instance, uint8_t index, - uint8_t max_value, - uint8_t current_step); + uint64_t max_value, + uint64_t current_step, + bool is_attacking); void subbrute_attack_view_stop_worker(SubBruteAttackView* instance); bool subbrute_attack_view_can_send(SubBruteAttackView* instance); void subbrute_attack_view_start_worker( SubBruteAttackView* instance, uint32_t frequency, FuriHalSubGhzPreset preset, - string_t protocol_name); -bool subbrute_attack_view_transmit(SubBruteAttackView* instance, string_t payload); + const char* protocol_name); +bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* payload); bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance); \ No newline at end of file From 6f91fa42f07adf944692206c8c68639893086f92 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 18:26:10 +0400 Subject: [PATCH 06/29] Added additional graphic decorations --- .../subbrute/views/subbrute_attack_view.c | 64 +++++++++++++------ .../subbrute/views/subbrute_main_view.c | 40 +++++++++--- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index 395e4b06e..ca5f6981d 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -6,6 +6,7 @@ #include #include #include +#include #define TAG "SubBruteAttackView" @@ -21,6 +22,7 @@ typedef struct { uint64_t max_value; uint64_t current_step; bool is_attacking; + IconAnimation* icon; } SubBruteAttackViewModel; void subbrute_attack_view_set_callback( @@ -75,6 +77,8 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { with_view_model( instance->view, (SubBruteAttackViewModel * model) { model->is_attacking = true; + icon_animation_stop(model->icon); + icon_animation_start(model->icon); return true; }); instance->callback(SubBruteCustomEventTypeTransmitStarted, instance->context); @@ -135,6 +139,8 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { with_view_model( instance->view, (SubBruteAttackViewModel * model) { model->is_attacking = false; + icon_animation_stop(model->icon); + icon_animation_start(model->icon); return true; }); instance->callback(SubBruteCustomEventTypeTransmitNotStarted, instance->context); @@ -150,6 +156,14 @@ SubBruteAttackView* subbrute_attack_view_alloc() { instance->view = view_alloc(); view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubBruteAttackViewModel)); view_set_context(instance->view, instance); + + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + model->icon = icon_animation_alloc(&A_Sub1ghz_14); + view_tie_icon_animation(instance->view, model->icon); + return false; + }); + view_set_draw_callback(instance->view, (ViewDrawCallback)subbrute_attack_view_draw); view_set_input_callback(instance->view, subbrute_attack_view_input); view_set_enter_callback(instance->view, subbrute_attack_view_enter); @@ -176,6 +190,12 @@ void subbrute_attack_view_free(SubBruteAttackView* instance) { #endif subbrute_worker_free(instance->worker); + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + icon_animation_free(model->icon); + return false; + }); + view_free(instance->view); free(instance); } @@ -228,6 +248,11 @@ void subbrute_attack_view_init_values( model->index = index; model->current_step = current_step; model->is_attacking = is_attacking; + if(is_attacking) { + icon_animation_start(model->icon); + } else { + icon_animation_stop(model->icon); + } return true; }); } @@ -282,6 +307,12 @@ void subbrute_attack_view_exit(void* context) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_attack_view_exit"); #endif + with_view_model( + instance->view, (SubBruteAttackViewModel * model) { + icon_animation_stop(model->icon); + return false; + }); + // Just stop, make free in free method subbrute_worker_stop(instance->worker); } @@ -371,35 +402,30 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) { canvas_draw_str_aligned(canvas, 64, 17, AlignCenter, AlignTop, buffer); canvas_set_font(canvas, FontSecondary); - // Progress bar - // Resolution: 128x64 px - if (model->is_attacking) { - float progress_value = (float)model->current_step / model->max_value; - elements_progress_bar(canvas, 8, 37, 110, progress_value > 1 ? 1 : progress_value); - } else { + if(!model->is_attacking) { canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignBottom, attack_name); - } - // Selected attack type - // const char* attack_name = NULL; - // attack_name = subbrute_get_menu_name(model->index); - // - // canvas_set_font(canvas, FontSecondary); - // if(attack_name) { - // snprintf(buffer, sizeof(buffer), "%s", attack_name); - // } else { - // snprintf(buffer, sizeof(buffer), "%s", "Unknown"; - // } - // canvas_draw_str(canvas, 9, 42, buffer); - if(!model->is_attacking) { elements_button_left(canvas, "-1"); elements_button_right(canvas, "+1"); elements_button_center(canvas, "Start"); elements_button_top_left(canvas, "Save"); elements_button_top_right(canvas, "Resend"); } else { + // canvas_draw_icon_animation + const uint8_t icon_h_offset = 0; + const uint8_t icon_width_with_offset = model->icon->icon->width + icon_h_offset; + const uint8_t icon_v_offset = model->icon->icon->height; // + vertical_offset; + const uint8_t x = canvas_width(canvas); + const uint8_t y = canvas_height(canvas); + canvas_draw_icon_animation( + canvas, x - icon_width_with_offset, y - icon_v_offset, model->icon); + // Progress bar + // Resolution: 128x64 px + float progress_value = (float)model->current_step / model->max_value; + elements_progress_bar(canvas, 8, 37, 110, progress_value > 1 ? 1 : progress_value); + elements_button_center(canvas, "Stop"); } } diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index e1fc1a91b..968ec0733 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -3,6 +3,7 @@ #include #include +#include "assets_icons.h" #include #define STATUS_BAR_Y_SHIFT 14 @@ -35,7 +36,10 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { // Title canvas_set_font(canvas, FontPrimary); + canvas_draw_box(canvas, 0, 0, canvas_width(canvas), STATUS_BAR_Y_SHIFT); + canvas_invert_color(canvas); canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); + canvas_invert_color(canvas); // Menu canvas_set_color(canvas, ColorBlack); @@ -53,14 +57,33 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { const char* str = subbrute_get_menu_name(position); if(m->index == position) { canvas_draw_str_aligned( - canvas, 64, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); - elements_frame(canvas, 1, 2 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); + elements_frame( + canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); } else { canvas_draw_str_aligned( - canvas, 64, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); } } } + + elements_scrollbar_pos( + canvas, + canvas_width(canvas), + STATUS_BAR_Y_SHIFT + 2, + canvas_height(canvas) - STATUS_BAR_Y_SHIFT, + m->index, + SubBruteAttackTotalCount); } bool subbrute_main_view_input(InputEvent* event, void* context) { @@ -102,7 +125,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { ret = true; consumed = true; } - if (ret) { + if(ret) { model->window_position = model->index; if(model->window_position > 0) { model->window_position -= 1; @@ -113,8 +136,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { } else { if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = - (SubBruteAttackTotalCount - items_on_screen); + model->window_position = (SubBruteAttackTotalCount - items_on_screen); } } } @@ -212,10 +234,8 @@ void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { if(SubBruteAttackTotalCount <= items_on_screen) { model->window_position = 0; } else { - if(model->window_position >= - (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = - (SubBruteAttackTotalCount - items_on_screen); + if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = (SubBruteAttackTotalCount - items_on_screen); } } From 54757428e60fa39188f8c531f8e1d0b1235dc6a4 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 21:31:33 +0400 Subject: [PATCH 07/29] fix bug with return to main menu when choice file --- .../subbrute/helpers/subbrute_worker.c | 12 +- .../subbrute/helpers/subbrute_worker.h | 3 - .../scenes/subbrute_scene_load_file.c | 66 +++++---- .../scenes/subbrute_scene_save_name.c | 2 + .../scenes/subbrute_scene_setup_attack.c | 38 ++++-- .../subbrute/scenes/subbrute_scene_start.c | 8 +- .../plugins/subbrute/subbrute_device.c | 125 ++++++------------ .../plugins/subbrute/subbrute_device.h | 11 +- .../subbrute/views/subbrute_attack_view.c | 5 + .../subbrute/views/subbrute_main_view.c | 2 +- 10 files changed, 132 insertions(+), 140 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 1b7b0d564..8e1994b95 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -1,11 +1,9 @@ -#include -#include - -#include -#include - #include "subbrute_worker.h" +#include +#include +#include + #define TAG "SubBruteWorker" struct SubBruteWorker { @@ -135,7 +133,7 @@ bool subbrute_worker_start( instance->preset = preset; string_clear(instance->protocol_name); - string_init_set_str(instance->protocol_name, protocol_name); + string_init_printf(instance->protocol_name, "%s", protocol_name); bool res = false; diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h index 56f48743a..5d2a21831 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.h +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -1,9 +1,6 @@ #pragma once #include -#include -#include -#include typedef struct SubBruteWorker SubBruteWorker; /** diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c index 0fecb5b6e..f9bad3cea 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c @@ -1,7 +1,8 @@ -#include #include "../subbrute_i.h" #include "../subbrute_custom_event.h" -#include "../views/subbrute_main_view.h" +#include + +#define TAG "SubBruteSceneLoadFile" //void subbrute_scene_load_file_callback(SubBruteCustomEvent event, void* context) { //// furi_assert(context); @@ -13,41 +14,56 @@ void subbrute_scene_load_file_on_enter(void* context) { furi_assert(context); SubBruteState* instance = (SubBruteState*)context; - string_t file_path; - string_init(file_path); + + // Input events and views are managed by file_browser + string_t app_folder; + string_t load_path; + string_init(load_path); + string_init_set_str(app_folder, SUBBRUTE_PATH); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px); - // Input events and views are managed by file_select - bool res = dialog_file_browser_show( - instance->dialogs, - instance->device->load_path, - instance->device->load_path, - &browser_options); - + SubBruteFileResult load_result = SubBruteFileResultUnknown; + bool res = + dialog_file_browser_show(instance->dialogs, load_path, app_folder, &browser_options); +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, + "load_path: %s, app_folder: %s", + string_get_cstr(load_path), + string_get_cstr(app_folder)); +#endif if(res) { - SubBruteFileResult load_result = subbrute_device_load_protocol_from_file(instance->device); + load_result = subbrute_device_load_from_file(instance->device, load_path); if(load_result == SubBruteFileResultOk) { - scene_manager_search_and_switch_to_previous_scene( - instance->scene_manager, SubBruteSceneSetupAttack); - } else { - string_t dialog_msg; - string_init(dialog_msg); - string_cat_printf( - dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result)); - dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg)); - string_clear(dialog_msg); - res = false; + load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile); + if(load_result == SubBruteFileResultOk) { + // Ready to run! + instance->device->state = SubBruteDeviceStateReady; + FURI_LOG_I(TAG, "Ready to run"); + res = true; + } } } - string_clear(file_path); + if(load_result == SubBruteFileResultOk) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + } else { + FURI_LOG_E(TAG, "Returned error: %d", load_result); - if(!res) { + string_t dialog_msg; + string_init(dialog_msg); + string_cat_printf( + dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result)); + dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg)); + string_clear(dialog_msg); scene_manager_search_and_switch_to_previous_scene( - instance->scene_manager, SubBruteSceneLoadFile); + instance->scene_manager, SubBruteSceneStart); } + + string_clear(app_folder); + string_clear(load_path); } void subbrute_scene_load_file_on_exit(void* context) { diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c index 9dc8f7a77..88a497db5 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c @@ -82,4 +82,6 @@ void subbrute_scene_save_name_on_exit(void* context) { validator_is_file_free(validator_context); text_input_reset(instance->text_input); + + string_reset(instance->device->load_path); } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index 67bf3b4f9..1ce6a3cde 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -27,12 +27,7 @@ void subbrute_scene_setup_attack_on_enter(void* context) { instance->device->key_index, false); - // Run worker anyway - subbrute_attack_view_start_worker( - view, - instance->device->frequency, - instance->device->preset, - string_get_cstr(instance->device->protocol_name)); + subbrute_attack_view_stop_worker(view); instance->current_view = SubBruteViewAttack; subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); @@ -41,6 +36,9 @@ void subbrute_scene_setup_attack_on_enter(void* context) { void subbrute_scene_setup_attack_on_exit(void* context) { furi_assert(context); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit"); +#endif SubBruteState* instance = (SubBruteState*)context; notification_message(instance->notifications, &sequence_blink_stop); } @@ -53,11 +51,28 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeTransmitStarted) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); - } else if (event.event == SubBruteCustomEventTypeSaveFile) { + } else if(event.event == SubBruteCustomEventTypeSaveFile) { + subbrute_attack_view_stop_worker(view); + + subbrute_attack_view_init_values( + view, + instance->device->attack, + instance->device->max_value, + instance->device->key_index, + false); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName); } else if(event.event == SubBruteCustomEventTypeBackPressed) { - subbrute_attack_view_stop_worker(view); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "SubBruteCustomEventTypeBackPressed"); +#endif instance->device->key_index = 0x00; + subbrute_attack_view_stop_worker(view); + subbrute_attack_view_init_values( + view, + instance->device->attack, + instance->device->max_value, + instance->device->key_index, + false); scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { // +1 @@ -86,6 +101,13 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event // Blink notification_message(instance->notifications, &sequence_blink_green_100); + if(!subbrute_attack_view_is_worker_running(view)) { + subbrute_attack_view_start_worker( + view, + instance->device->frequency, + instance->device->preset, + string_get_cstr(instance->device->protocol_name)); + } subbrute_device_create_packet_parsed( instance->device, instance->device->key_index); subbrute_attack_view_transmit(view, instance->device->payload); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index beefafa58..eb00265b4 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -24,10 +24,8 @@ void subbrute_scene_start_on_enter(void* context) { instance->current_view = SubBruteViewMain; subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance); - subbrute_main_view_set_index(view, (uint8_t)instance->device->attack); -#ifdef FURI_DEBUG - FURI_LOG_I(TAG, "view_dispatcher_switch_to_view"); -#endif + subbrute_main_view_set_index(view, instance->device->attack); + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } @@ -49,7 +47,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.event == SubBruteCustomEventTypeMenuSelected) { SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main); - subbrute_device_attack_set(instance->device, attack, NULL); + subbrute_device_attack_set(instance->device, attack); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); consumed = true; diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 93ef80dc6..8c02beb62 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -51,7 +51,6 @@ SubBruteDevice* subbrute_device_alloc() { instance->state = SubBruteDeviceStateIDLE; instance->key_index = 0; - instance->dialogs = furi_record_open(RECORD_DIALOGS); string_init(instance->load_path); string_init(instance->preset_name); @@ -61,7 +60,7 @@ SubBruteDevice* subbrute_device_alloc() { instance->receiver = NULL; instance->environment = NULL; - subbrute_device_attack_set_default_values(instance); + subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307); return instance; } @@ -71,7 +70,6 @@ void subbrute_device_free(SubBruteDevice* instance) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_device_free"); #endif - furi_record_close(RECORD_DIALOGS); // I don't know how to free this instance->decoder_result = NULL; @@ -103,47 +101,6 @@ void subbrute_device_free(SubBruteDevice* instance) { free(instance); } -SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance) { - furi_assert(instance); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_device_load_protocol_from_file"); -#endif - // Input events and views are managed by file_browser - string_t app_directory; - string_init_set_str(app_directory, SUBBRUTE_PATH); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px); - - SubBruteFileResult load_result = SubBruteFileResultUnknown; - bool res = dialog_file_browser_show( - instance->dialogs, instance->load_path, app_directory, &browser_options); - - string_clear(app_directory); - if(res) { - load_result = subbrute_device_attack_set( - instance, SubBruteAttackLoadFile, string_get_cstr(instance->load_path)); - if(load_result == SubBruteFileResultOk) { - // Ready to run! - instance->state = SubBruteDeviceStateReady; - FURI_LOG_I(TAG, "Ready to run"); - } - } else { - FURI_LOG_I(TAG, "Returned error: %sd", load_result); - // res = false; - // - // char file_info_message[128]; - // snprintf( - // file_info_message, - // sizeof(file_info_message), - // "Can not load file\n%s", - // (char*)subbrute_device_error_get_desc(set_result)); - // dialog_message_show_storage_error(instance->dialogs, file_info_message); - } - - return load_result; -} - bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) { furi_assert(instance); @@ -249,7 +206,7 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste } char subbrute_payload_byte[4]; string_set_str(candidate, instance->file_key); - snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)instance->file_key[step]); + snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step); string_replace_at(candidate, step, 3, subbrute_payload_byte); //snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); } else { @@ -303,26 +260,21 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste return true; } -SubBruteFileResult subbrute_device_attack_set( - SubBruteDevice* instance, - SubBruteAttacks type, - const char* file_path) { +SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) { furi_assert(instance); #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_device_attack_set: %d", type); #endif - subbrute_device_attack_set_default_values(instance); - uint8_t file_result; - - instance->attack = type; - + subbrute_device_attack_set_default_values(instance, type); switch(type) { case SubBruteAttackLoadFile: - file_result = subbrute_device_load_from_file(instance, file_path); - if(file_result != SubBruteFileResultOk) { - // Failed load file so failed to set attack type - return file_result; // RETURN - } + // In this case values must be already set + // file_result = + // subbrute_device_load_from_file(instance, string_get_cstr(instance->load_path)); + // if(file_result != SubBruteFileResultOk) { + // // Failed load file so failed to set attack type + // return file_result; // RETURN + // } break; case SubBruteAttackCAME12bit307: case SubBruteAttackCAME12bit433: @@ -460,10 +412,10 @@ SubBruteFileResult subbrute_device_attack_set( return SubBruteFileResultOk; } -uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) { +uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_path) { furi_assert(instance); #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", file_path); + FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", string_get_cstr(file_path)); #endif SubBruteFileResult result = SubBruteFileResultUnknown; @@ -480,8 +432,8 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil furi_hal_subghz_reset(); do { - if(!flipper_format_file_open_existing(fff_data_file, file_path)) { - FURI_LOG_E(TAG, "Error open file %s", file_path); + if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_path))) { + FURI_LOG_E(TAG, "Error open file %s", string_get_cstr(file_path)); result = SubBruteFileResultErrorOpenFile; break; } @@ -504,21 +456,24 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil break; } // Preset - if(!flipper_format_read_string(fff_data_file, "Preset", instance->preset_name)) { + if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { FURI_LOG_E(TAG, "Preset FAIL"); result = SubBruteFileResultPresetInvalid; + } else { + string_init_set_str(instance->preset_name, string_get_cstr(temp_str)); } + // Protocol - if(!flipper_format_read_string(fff_data_file, "Protocol", instance->protocol_name)) { + if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { FURI_LOG_E(TAG, "Missing Protocol"); result = SubBruteFileResultMissingProtocol; break; - } + } else { + string_init_set_str(instance->protocol_name, string_get_cstr(temp_str)); #ifdef FURI_DEBUG - else { FURI_LOG_D(TAG, "Protocol: %s", string_get_cstr(instance->protocol_name)); - } #endif + } instance->decoder_result = subghz_receiver_search_decoder_base_by_name( instance->receiver, string_get_cstr(instance->protocol_name)); @@ -615,35 +570,39 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil return result; } -void subbrute_device_attack_set_default_values(SubBruteDevice* instance) { +void subbrute_device_attack_set_default_values( + SubBruteDevice* instance, + SubBruteAttacks default_attack) { furi_assert(instance); #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values"); #endif - instance->attack = SubBruteAttackCAME12bit307; - instance->max_value = 0; + instance->attack = default_attack; instance->key_index = 0x00; - memset(instance->file_template, 0, sizeof(instance->file_template)); memset(instance->current_key, 0, sizeof(instance->current_key)); - memset(instance->file_key, 0, sizeof(instance->file_key)); memset(instance->text_store, 0, sizeof(instance->text_store)); memset(instance->payload, 0, sizeof(instance->payload)); - string_clear(instance->protocol_name); - string_clear(instance->preset_name); - string_clear(instance->load_path); + if(default_attack != SubBruteAttackLoadFile) { + memset(instance->file_key, 0, sizeof(instance->file_key)); - string_init(instance->load_path); + instance->max_value = (uint64_t)0x00; - string_init_set_str(instance->protocol_name, protocol_raw); - string_init_set_str(instance->preset_name, preset_ook650_async); - instance->preset = FuriHalSubGhzPresetOok650Async; + string_clear(instance->protocol_name); + string_clear(instance->preset_name); - instance->repeat = 5; - instance->te = 0; - instance->has_tail = false; + string_clear(instance->load_path); + string_init(instance->load_path); + string_init_set_str(instance->protocol_name, protocol_raw); + string_init_set_str(instance->preset_name, preset_ook650_async); + instance->preset = FuriHalSubGhzPresetOok650Async; + + instance->repeat = 5; + instance->te = 0; + instance->has_tail = false; + } #ifdef FURI_DEBUG FURI_LOG_D( TAG, "subbrute_device_attack_set_default_values done. has_tail: %d", instance->has_tail); diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index a6fdeef58..f0d3d8a57 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -55,7 +55,6 @@ typedef enum { } SubBruteDeviceState; typedef struct { - DialogsApp* dialogs; SubBruteDeviceState state; // Current step @@ -89,14 +88,10 @@ typedef struct { SubBruteDevice* subbrute_device_alloc(); void subbrute_device_free(SubBruteDevice* instance); -SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance); bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name); const char* subbrute_device_error_get_desc(SubBruteFileResult error_id); bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint64_t step); -SubBruteFileResult subbrute_device_attack_set( - SubBruteDevice* context, - SubBruteAttacks type, - const char* file_path); -uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path); +SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type); +uint8_t subbrute_device_load_from_file(SubBruteDevice* context, string_t file_path); FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset); -void subbrute_device_attack_set_default_values(SubBruteDevice* context); \ No newline at end of file +void subbrute_device_attack_set_default_values(SubBruteDevice* context, SubBruteAttacks default_attack); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index ca5f6981d..069c7aac1 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -306,12 +306,17 @@ void subbrute_attack_view_exit(void* context) { SubBruteAttackView* instance = context; #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_attack_view_exit"); + furi_delay_ms(150); #endif with_view_model( instance->view, (SubBruteAttackViewModel * model) { icon_animation_stop(model->icon); return false; }); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_worker_stop"); + furi_delay_ms(150); +#endif // Just stop, make free in free method subbrute_worker_stop(instance->worker); diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 968ec0733..67342cc9c 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -216,7 +216,7 @@ View* subbrute_main_view_get_view(SubBruteMainView* instance) { void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { furi_assert(instance); - furi_assert(idx < SubBruteAttackTotalCount - 1); + furi_assert(idx < SubBruteAttackTotalCount); #ifdef FURI_DEBUG FURI_LOG_I(TAG, "Set index: %d", idx); #endif From 97e6fe8f4e9b400fc84e9721fc0637fc05918eeb Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 25 Sep 2022 20:39:22 +0300 Subject: [PATCH 08/29] update universal remote assets by @amec0e --- assets/resources/infrared/assets/ac.ir | 8 ++- assets/resources/infrared/assets/audio.ir | 62 ++++++++++++++++++++++- assets/resources/infrared/assets/fans.ir | 26 +++++++++- assets/resources/infrared/assets/tv.ir | 32 +++++++++++- 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index 8921275d8..8f219bb14 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -1,6 +1,6 @@ Filetype: IR library file Version: 1 -# Last Updated 17th Sept, 2022 +# Last Updated 20th Sept, 2022 # # ON name: POWER @@ -1227,3 +1227,9 @@ frequency: 38000 duty_cycle: 0.330000 data: 3120 1593 488 1180 489 1177 492 342 492 342 492 367 467 1174 485 349 485 349 485 1181 488 1179 490 343 491 1177 492 341 493 366 458 1183 486 1181 488 346 488 1179 490 1177 492 342 492 341 493 1174 485 349 485 347 487 1180 489 345 489 344 490 370 464 368 466 341 493 341 483 376 458 375 459 348 486 374 460 372 462 345 489 370 464 369 465 368 466 341 493 367 457 348 486 374 460 348 486 1179 490 343 491 343 491 1176 493 1174 485 349 485 349 485 374 460 373 461 373 461 346 488 371 463 371 463 369 465 1175 484 350 484 350 484 348 486 374 460 346 488 372 462 345 489 371 463 370 464 368 466 340 484 376 458 376 458 375 459 348 486 347 487 345 489 370 464 370 464 369 465 342 492 368 466 367 457 375 459 348 486 374 460 347 487 372 462 345 489 371 463 343 491 368 466 341 493 367 457 376 458 375 459 1181 488 346 488 345 489 1178 491 342 492 342 492 1175 494 1173 486 1182 487 346 488 346 488 1179 490 343 491 342 492 368 466 367 457 # +name: SWING +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 92 00 00 00 +# diff --git a/assets/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index a27283376..4e70779ce 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -1,6 +1,24 @@ Filetype: IR library file Version: 1 -# Last Updated 17th Sept, 2022 +# Last Updated 25th Sept, 2022 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9150 4435 643 1608 643 468 644 469 642 364 749 468 643 447 665 449 663 469 643 452 660 470 642 450 662 442 670 449 662 469 643 1579 672 1608 642 1580 671 1609 641 1607 643 1578 672 1607 643 1608 642 1606 644 1606 644 1606 644 1607 643 1576 675 1579 671 1605 674 438 645 466 673 438 646 466 674 437 673 439 672 439 673 438 646 1604 673 1577 673 1578 673 1577 674 1577 673 23799 9095 4485 616 +# +name: VOL+ +type: parsed +protocol: NEC42 +address: 01 00 00 00 +command: 0C 00 00 00 +# +name: VOL- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9151 4434 644 1608 643 376 737 379 733 446 666 449 663 468 644 469 643 468 644 468 644 468 644 447 665 448 664 468 644 450 662 1608 643 1607 644 1576 676 1607 644 1608 643 1578 674 1608 643 1577 674 1579 672 1607 643 1608 643 1607 644 1607 644 1608 643 448 664 1608 643 448 664 468 644 469 643 380 732 468 644 469 643 1607 644 468 644 1608 643 1608 644 1609 643 1608 643 23837 9152 4434 642 # name: POWER type: raw @@ -1430,3 +1448,45 @@ protocol: NEC address: 4D 00 00 00 command: 00 00 00 00 # +name: VOL+ +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 19 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 16 00 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 44 00 00 00 +# +name: VOL+ +type: parsed +protocol: NECext +address: 12 36 00 00 +command: 0A F5 00 00 +# +name: VOL- +type: parsed +protocol: NECext +address: 12 36 00 00 +command: 0B F4 00 00 +# +name: MUTE +type: parsed +protocol: NECext +address: 12 36 00 00 +command: 09 F6 00 00 +# +name: POWER +type: parsed +protocol: NECext +address: 12 36 00 00 +command: 01 FE 00 00 +# diff --git a/assets/resources/infrared/assets/fans.ir b/assets/resources/infrared/assets/fans.ir index f2cf34021..83c37d275 100644 --- a/assets/resources/infrared/assets/fans.ir +++ b/assets/resources/infrared/assets/fans.ir @@ -1,6 +1,6 @@ Filetype: IR library file Version: 1 -# Last Updated 18th Sept, 2022 +# Last Updated 22th Sept, 2022 # # TIMER UP name: TIMER @@ -956,3 +956,27 @@ protocol: NEC address: 80 00 00 00 command: 03 00 00 00 # +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1397 357 1370 357 500 1188 1427 331 1343 383 473 1240 476 1240 476 1240 475 1240 475 1240 475 1240 1370 7358 1367 361 1366 361 496 1220 1366 361 1366 361 496 1220 495 1220 495 1220 495 1221 494 1220 495 1220 1366 7361 1365 361 1366 361 495 1221 1365 362 1365 362 494 1221 494 1221 494 1220 495 1220 495 1221 494 1220 1365 7361 1364 361 1366 362 494 1221 1365 362 1365 362 494 1221 494 1221 494 1221 494 1221 494 1221 494 1221 1365 7361 1364 362 1364 362 494 1221 1364 362 1365 362 495 1221 494 1221 494 1221 494 1221 494 1221 494 1221 1364 7361 1364 363 1364 363 493 1222 1364 363 1363 363 493 1223 492 1223 492 1223 492 1247 468 1223 492 1247 1339 7386 1338 388 1338 388 468 1247 1339 388 1338 388 468 1248 467 1247 468 1247 468 1247 468 1248 467 1247 1338 7387 1337 389 1338 389 467 1248 1338 389 1337 389 467 1248 467 1248 467 1248 467 1248 467 1248 467 1248 1337 7388 1336 389 1337 389 467 1249 1336 390 1337 390 466 1249 466 1249 466 1249 466 1249 466 1249 466 1248 1337 7388 1312 414 1312 414 465 1251 1335 391 1337 390 441 1274 441 1274 465 1249 464 1250 442 1274 441 1273 1337 7388 1311 414 1312 415 441 1274 1311 415 1311 415 441 1274 441 1274 441 1274 441 1274 441 1274 441 1274 1311 7413 1311 415 1312 415 441 1274 1311 415 1311 416 440 1275 440 1275 440 1275 440 1275 440 1275 439 1275 1310 7414 1309 416 1310 417 439 1276 1310 417 1309 417 438 1277 438 1277 438 1277 438 1301 413 1301 414 1301 1285 7439 1284 442 1284 442 414 1301 1284 443 1283 443 413 1302 413 1302 413 1302 413 1302 412 1302 413 1302 1283 7441 1283 443 1284 443 412 1303 1283 444 1282 444 412 1303 411 1303 412 1303 412 1303 412 1303 412 1303 1283 7441 1282 445 1281 445 411 1304 1282 470 1256 471 385 1330 385 1330 385 1330 385 1330 385 1330 385 1330 1256 7468 1255 471 1256 471 384 1331 1255 471 1255 472 383 1331 384 1331 383 1332 383 1332 383 1331 383 1332 1254 7470 1253 498 1228 499 356 1358 1228 499 1227 499 356 1359 356 1359 356 1359 356 1359 355 1360 355 1359 1227 7497 1226 526 1200 527 327 1387 1200 527 1199 554 300 1414 301 1415 299 1415 299 1415 300 1416 299 1415 1172 7553 1170 609 1117 583 270 1471 1117 637 1089 692 118 10334 871 +# Osc +name: ROTATE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1395 358 1369 358 499 1215 1399 331 1341 384 472 1241 474 1240 475 1240 1345 383 473 1240 474 1240 474 8239 1366 387 1339 387 469 1246 1339 388 1339 387 469 1246 469 1246 469 1246 1339 388 469 1246 469 1246 469 8242 1339 387 1339 387 469 1246 1339 387 1339 387 469 1246 469 1246 469 1246 1339 387 469 1246 469 1246 468 8243 1338 388 1338 388 469 1246 1339 388 1338 388 468 1246 468 1246 469 1247 1338 388 468 1246 468 1247 468 8243 1338 388 1338 388 468 1246 1338 388 1338 388 468 1246 469 1246 468 1246 1339 387 469 1246 468 1246 468 8218 1363 363 1363 363 493 1222 1363 363 1363 363 493 1222 493 1222 492 1222 1363 363 493 1221 493 1222 493 8217 1363 363 1363 363 493 1222 1363 363 1363 363 493 1246 468 1223 492 1223 1361 375 481 1247 467 1247 467 8243 1337 388 1338 388 468 1247 1337 389 1337 388 468 1247 468 1247 468 1247 1337 389 467 1248 466 1248 466 8243 1337 389 1337 389 467 1248 1336 389 1337 390 466 1248 466 1248 466 1248 1336 390 466 1248 466 1248 466 8244 1336 390 1311 415 465 1249 1336 390 1336 391 465 1250 465 1249 465 1250 1310 415 465 1250 464 1250 439 8270 1310 416 1310 416 440 1275 1310 417 1309 417 438 1300 414 1301 413 1301 1284 442 414 1301 413 1301 413 8297 1284 442 1284 442 413 1301 1284 443 1283 443 413 1302 412 1302 412 1302 1282 443 413 1302 412 1302 412 8298 1282 443 1283 443 413 1302 1283 443 1283 444 412 1303 411 1303 411 1303 1282 444 412 1303 411 1303 411 8299 1280 445 1281 470 385 1329 1255 470 1256 471 384 1330 384 1329 385 1329 1255 471 385 1330 384 1330 384 8326 1253 472 1254 472 384 1331 1253 473 1253 499 356 1357 357 1358 356 1358 1226 499 356 1358 356 1359 355 8355 1224 502 1224 501 355 1385 1199 527 1199 527 328 1386 328 1386 328 1386 1199 527 328 1387 327 1387 327 8409 1171 554 1172 555 300 1414 1172 555 1171 555 300 1416 299 1416 298 1415 1171 556 298 1442 272 1442 272 8438 1143 583 1143 583 271 1471 1115 611 1115 664 179 1536 178 1563 122 1619 1006 +# +name: SPEED+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1395 359 1367 358 499 1213 1368 359 1366 359 473 1239 474 1239 474 1238 475 1238 1368 360 497 1215 497 8209 1362 364 1361 366 492 1221 1360 366 1359 366 491 1222 492 1222 491 1221 493 1245 1336 366 492 1222 492 8213 1360 366 1359 389 468 1222 1359 367 1358 390 467 1246 468 1246 468 1245 468 1246 1335 390 467 1246 467 8238 1335 390 1335 390 468 1246 1335 390 1335 390 467 1246 467 1246 468 1246 467 1246 1335 390 467 1246 467 8238 1334 390 1335 390 467 1247 1334 390 1335 391 466 1247 466 1247 466 1247 466 1247 1334 390 467 1247 466 8239 1334 391 1334 391 466 1247 1334 391 1334 391 467 1247 466 1247 466 1247 466 1248 1333 391 466 1248 465 8239 1333 392 1333 392 466 1248 1333 392 1333 392 465 1248 465 1248 465 1248 465 1248 1333 392 465 1248 465 8240 1332 392 1333 392 465 1248 1333 393 1332 393 464 1249 464 1249 464 1249 464 1249 1331 393 465 1249 464 8241 1331 393 1332 393 464 1250 1331 394 1331 394 463 1250 463 1251 462 1250 463 1251 1329 396 462 1251 462 8243 1305 420 1305 444 436 1277 1280 444 1281 445 435 1277 412 1301 436 1277 435 1277 1280 445 436 1277 436 8268 1280 445 1279 445 412 1301 1280 445 1280 445 411 1302 411 1302 411 1302 411 1302 1279 446 411 1302 411 8293 1278 446 1279 446 411 1303 1278 447 1277 447 410 1303 410 1304 409 1329 384 1329 1252 472 385 1329 384 8320 1252 473 1251 473 383 1330 1251 473 1252 473 384 1330 383 1330 383 1330 383 1330 1251 474 382 1330 383 8321 1250 474 1251 475 381 1331 1250 500 1224 500 356 1358 355 1358 355 1358 355 1358 1223 501 355 1358 355 8349 1223 502 1222 528 327 1386 1196 528 1196 530 326 1386 327 1387 326 1386 327 1413 1169 556 299 1414 299 8404 1169 556 1168 584 271 1441 1141 611 1113 637 216 1498 215 1524 178 1562 122 1564 1058 11171 970 +# +name: TIMER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1366 359 1366 360 496 1214 1367 360 1395 331 524 1185 474 1239 474 1238 475 1238 475 1238 1343 383 498 8205 1366 386 1338 386 470 1244 1338 386 1339 386 470 1243 470 1244 469 1244 469 1243 470 1244 1338 386 470 8234 1338 386 1339 386 469 1244 1338 386 1339 386 470 1243 470 1220 493 1219 494 1243 470 1244 1338 362 494 8233 1339 362 1363 386 469 1244 1338 386 1339 386 469 1244 469 1244 469 1244 469 1244 469 1244 1338 387 468 8234 1338 386 1338 387 468 1244 1338 387 1337 387 468 1244 469 1244 468 1245 469 1244 469 1244 1338 387 468 8234 1337 387 1338 387 465 1247 1338 387 1338 387 468 1245 468 1244 444 1269 468 1246 467 1245 1337 387 468 8235 1337 387 1337 388 468 1245 1336 388 1336 388 466 1246 467 1245 468 1245 467 1247 467 1245 1312 412 467 8235 1312 412 1312 412 443 1270 1335 390 1311 412 468 1246 466 1246 467 1246 467 1246 467 1246 1311 412 467 8236 1311 413 1311 413 442 1271 1311 413 1311 413 442 1271 466 1247 466 1246 442 1271 442 1271 1311 413 442 8260 1311 413 1311 413 442 1271 1311 413 1311 414 441 1271 442 1271 465 1248 464 1249 465 1247 1310 414 441 8261 1334 390 1310 414 466 1247 1335 390 1333 391 465 1248 465 1248 465 1248 465 1248 465 1248 1334 390 465 8237 1334 391 1333 390 465 1248 1309 415 1309 416 464 1249 464 1249 463 1250 462 1275 438 1274 1307 394 438 8287 1283 441 1283 441 438 1274 1283 441 1283 442 436 1276 414 1299 438 1275 413 1300 412 1300 1282 442 413 8289 1282 443 1281 443 412 1301 1281 443 1281 443 412 1301 411 1302 411 1302 410 1327 385 1327 1255 469 386 8316 1255 470 1254 470 385 1327 1255 470 1254 470 385 1327 385 1328 384 1328 385 1328 385 1328 1254 470 385 8317 1253 471 1253 470 385 1329 1253 471 1253 471 384 1329 383 1330 382 1330 382 1330 383 1330 1252 473 382 8344 1226 498 1226 498 357 1356 1226 498 1226 498 356 1356 356 1356 356 1356 356 1356 356 1356 1226 499 355 8346 1224 499 1225 525 329 1384 1198 526 1198 525 329 1384 328 1384 328 1384 328 1384 329 1384 1198 526 328 8373 1198 526 1198 527 327 1385 1197 553 1171 553 301 1412 300 1412 300 1412 300 1386 327 1412 1170 554 299 8401 1170 554 1170 555 298 1414 1169 581 1143 582 271 1440 272 1440 272 1440 272 1441 271 1441 1142 609 244 8458 1113 636 1088 663 178 1507 1088 691 1033 +# diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index 0e96f6c74..4a60dfdb4 100755 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,6 +1,36 @@ Filetype: IR library file Version: 1 -# Last Updated 18th Sept, 2022 +# Last Updated 25th Sept, 2022 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3398 1660 464 419 435 1253 434 423 441 417 436 420 434 424 440 417 437 421 433 424 440 417 437 421 433 425 439 418 436 1252 435 422 432 427 437 420 434 424 440 417 436 421 433 424 440 417 437 421 433 1255 432 426 438 419 435 423 431 426 438 420 434 423 431 427 437 421 433 1228 459 425 439 1249 438 1250 437 1225 462 1226 461 422 432 426 438 1224 463 421 433 1229 458 1230 457 1257 440 1221 466 392 462 1224 463 72803 3397 1661 463 421 433 1255 432 426 438 419 435 423 431 427 437 420 434 424 440 417 437 421 433 398 466 418 436 422 432 1256 431 427 437 421 433 424 440 418 436 422 432 425 439 419 435 423 431 426 438 1250 437 421 433 425 439 418 436 422 432 426 438 419 435 423 431 428 436 1252 435 422 432 1257 440 1248 439 1249 438 1224 463 395 458 425 439 1249 438 419 435 1227 460 1255 432 1256 431 1231 466 417 437 1249 438 72803 3398 1687 437 420 434 1255 432 425 439 419 434 397 457 427 437 420 434 424 440 417 436 421 432 425 439 418 436 422 432 1257 440 417 437 422 431 426 438 393 461 423 431 427 437 420 434 424 440 417 436 1225 462 422 432 426 438 419 435 423 431 426 438 420 434 424 440 418 436 1252 435 422 432 1257 440 1247 440 1248 439 1223 464 420 434 424 440 1222 465 418 435 1253 434 1254 433 1229 458 1256 431 427 437 1248 439 72798 3403 1682 432 426 438 1250 437 420 434 424 440 417 436 421 433 425 439 418 436 422 432 425 439 419 435 422 432 426 438 1250 437 420 434 425 439 418 436 422 432 425 439 419 435 422 432 426 438 419 434 1254 433 424 440 417 437 421 432 425 439 418 436 422 432 426 438 420 434 1254 433 425 439 1222 465 1223 464 1224 463 1252 435 422 432 426 438 1250 437 421 433 1255 432 1256 431 1257 440 1221 466 419 435 1250 437 72798 3402 1683 431 426 438 1250 437 421 433 425 439 418 436 422 432 425 439 419 435 423 431 426 438 420 434 423 431 427 437 1251 436 421 433 426 438 419 435 423 431 427 437 420 434 424 440 417 436 421 433 1255 432 425 439 419 435 422 432 426 438 419 435 423 431 427 437 421 433 1255 432 426 438 1250 437 1251 436 1252 435 1254 433 424 440 418 436 1252 435 423 431 1257 440 1247 440 1249 438 1250 437 421 433 1226 461 +# +name: VOL+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3405 1655 458 425 439 1248 438 420 433 424 440 417 436 421 433 425 439 418 435 422 431 426 438 420 433 423 441 417 436 1251 435 422 431 427 437 420 434 424 440 418 435 421 432 425 439 419 434 422 431 1257 440 417 436 421 433 424 440 417 436 421 432 425 439 418 435 423 430 426 438 420 434 424 440 417 436 421 433 1255 432 425 439 418 435 422 431 426 438 419 435 423 430 426 438 1250 437 421 432 1252 435 79433 3405 1680 434 424 440 1221 466 418 435 422 431 426 438 419 434 423 430 427 437 420 434 423 441 417 436 421 433 424 440 1248 439 419 434 423 431 427 437 420 433 424 440 417 436 421 432 424 440 418 435 1251 436 422 431 426 438 419 434 423 430 427 437 420 434 424 440 418 435 421 432 425 439 418 435 422 431 426 438 1223 464 420 434 424 440 417 436 420 434 424 440 417 436 421 432 1255 432 426 438 1247 440 79430 3397 1687 437 420 434 1254 433 425 439 419 434 422 432 426 438 420 433 423 441 417 436 420 433 424 440 417 436 421 432 1256 431 426 438 420 434 424 440 417 436 421 432 425 439 418 435 422 431 425 439 1249 438 420 433 424 440 417 436 421 433 425 439 418 435 422 432 426 438 419 434 423 441 417 436 420 433 424 440 1248 439 418 435 422 431 426 438 419 434 423 430 427 437 420 433 1254 433 425 439 1245 431 79441 3397 1687 437 420 433 1254 433 424 440 418 435 421 432 425 439 418 435 422 431 426 438 419 434 423 431 427 437 420 433 1254 433 425 439 419 434 422 431 426 438 419 434 423 430 427 437 420 433 424 440 1221 466 418 435 422 431 426 438 419 434 423 441 417 436 420 433 425 439 418 436 422 431 426 438 419 434 423 431 1257 440 417 436 421 432 425 439 418 435 422 431 426 438 419 434 1253 434 424 440 1245 431 79442 3395 1688 436 421 433 1255 432 426 438 419 434 423 430 427 437 420 433 424 440 417 436 420 434 424 440 417 436 421 432 1255 432 426 438 420 434 423 441 417 436 420 433 424 440 418 435 421 432 425 439 1249 438 419 435 423 431 427 437 420 434 424 440 417 436 421 433 425 439 418 435 422 432 426 438 419 435 423 430 1256 441 417 436 420 433 424 440 417 436 421 432 425 439 418 435 1253 434 423 441 1245 431 79441 3397 1687 437 421 432 1255 432 425 439 418 435 422 431 426 438 419 434 423 430 427 437 420 434 424 440 417 436 421 432 1255 432 425 439 419 434 423 431 426 438 420 434 423 441 417 436 420 434 424 440 1247 440 418 435 422 432 425 439 419 435 423 431 426 438 419 434 424 440 417 436 421 433 425 439 418 435 422 431 1256 431 426 438 420 433 423 441 417 436 420 434 424 440 417 436 1225 462 421 432 1253 434 79429 3399 1684 440 417 436 1225 462 421 432 425 439 418 435 422 431 425 439 418 435 422 431 426 438 419 435 422 432 426 438 1250 437 420 433 425 439 418 435 421 433 425 439 418 435 421 433 425 439 418 435 1252 435 423 431 426 438 419 434 423 431 427 437 420 434 424 440 417 436 421 432 425 439 418 436 421 432 425 439 1249 438 419 434 423 431 427 437 420 434 424 440 417 436 421 432 1255 432 425 439 1246 441 +# +name: VOL- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3396 1688 436 421 432 1256 431 426 438 420 433 424 440 417 436 421 432 424 440 418 435 422 431 425 439 419 434 422 431 1257 440 417 436 421 432 425 439 418 435 422 431 426 438 419 434 423 430 427 437 1250 436 421 432 425 439 419 434 423 430 426 438 420 434 424 440 418 435 1252 435 423 431 427 437 420 433 424 440 1247 440 418 435 422 431 1256 431 427 437 420 433 424 440 417 436 1252 434 423 430 1254 432 77786 3404 1681 433 425 439 1248 438 419 434 423 430 427 437 420 433 424 440 417 436 421 432 424 440 417 436 421 433 425 439 1248 438 419 434 424 440 417 436 421 432 425 439 418 435 422 431 426 438 420 433 1254 433 424 440 418 435 422 431 426 438 419 434 423 430 426 438 421 432 1254 432 425 439 419 434 423 430 426 438 1250 436 421 432 425 439 1248 438 419 434 423 441 417 436 421 432 1255 432 426 438 1246 441 77777 3402 1682 432 426 438 1250 436 420 433 424 440 417 436 421 432 425 439 419 434 422 431 426 438 419 434 423 441 417 436 1251 436 422 431 426 438 419 434 423 441 417 436 420 433 424 440 417 436 421 432 1255 432 426 438 420 433 423 441 417 436 421 432 424 440 418 435 422 431 1256 441 417 436 421 432 424 440 418 435 1252 435 422 431 426 438 1250 437 421 432 424 440 418 435 421 432 1256 430 426 438 1247 440 +# +name: CH+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3401 1683 431 426 438 1249 438 420 434 424 440 417 436 421 433 424 440 417 436 421 432 425 439 418 435 421 432 425 439 1248 439 418 435 423 431 426 438 420 434 423 431 427 437 420 434 423 431 427 437 1250 437 421 433 424 440 418 436 421 432 425 439 418 435 421 433 426 438 419 435 423 430 1256 431 427 437 1250 437 1224 463 422 432 425 439 419 435 422 431 1256 431 426 438 1249 438 1223 464 420 434 1251 436 76104 3396 1688 436 421 433 1255 432 425 439 418 435 422 432 425 439 419 435 422 431 426 438 419 434 422 432 426 438 419 434 1253 434 424 440 418 435 422 432 425 439 418 435 422 431 426 438 419 434 423 431 1257 440 417 436 421 433 424 440 417 437 421 433 424 440 417 436 422 432 425 439 418 435 1252 435 423 431 1256 441 1247 440 417 436 421 432 425 439 418 435 1252 435 422 432 1256 431 1256 441 417 437 1247 440 +# +name: CH- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3404 1652 462 422 432 1230 457 427 437 420 434 424 440 417 436 420 434 424 440 417 436 421 433 424 440 417 436 421 432 1228 459 425 439 419 434 422 432 426 438 419 434 422 431 426 438 419 435 422 431 1230 457 426 438 420 433 423 431 426 438 420 433 423 430 427 437 420 434 1228 459 424 440 1221 466 418 435 1225 462 1226 461 422 432 426 438 1224 463 420 433 1228 459 399 465 1222 465 1223 464 420 433 1225 462 # name: POWER type: parsed From be8f4090984ef73e2bd9470796484fab6b755915 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 25 Sep 2022 21:01:12 +0300 Subject: [PATCH 09/29] update changelog --- CHANGELOG.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26de6e5a8..721707abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,19 @@ ### New changes -* OFW: Fixed NFC Mifare classic dict attack uses wrong keys (OFW PR 1769) -* Infrared: removed duplicate function, moved reset to scene exit +* Infrared: Updated universal remote assets (by @Amec0e) +* OFW: Text input overwrite max size template +* OFW: Remove unused headers +* OFW: ELF-Loader: C++ plugin support, loader overhaul. +* OFW: Core: simplify record container #### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use .tgz file with qFlipper, or install automatically via web updater or use microSD update package** [- How to install](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md) -[- Download qFlipper 1.2.0-rc1 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0-rc1/) +[- Download qFlipper 1.2.0 (allows .tgz installation) (official link)](https://update.flipperzero.one/builds/qFlipper/1.2.0/) **Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed** Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for iOS mobile app / qFlipper -Update using qFlipper (1.2.0-rc1) is now possible with `.tgz` update package! Also you can use Web Updater or self-update package. +Update using qFlipper (1.2.0) is now possible with `.tgz` update package! Also you can use Web Updater or self-update package. From 8013aacd94a299f19ffe8bb4c1d41cb3fdff070a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 25 Sep 2022 21:03:32 +0300 Subject: [PATCH 10/29] oops --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 721707abe..97389f6c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### New changes * Infrared: Updated universal remote assets (by @Amec0e) +* OFW PR: SubGHz: Read RAW - datetime in default names (+ format changed) (OFW PR 1772 by Skorpionm) * OFW: Text input overwrite max size template * OFW: Remove unused headers * OFW: ELF-Loader: C++ plugin support, loader overhaul. From ea7f68fcab6f14f6411c8869739715e44c2bee33 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 23:12:31 +0400 Subject: [PATCH 11/29] fixed load existing dump --- .../subbrute/scenes/subbrute_scene_config.h | 1 + .../scenes/subbrute_scene_load_file.c | 2 +- .../scenes/subbrute_scene_load_select.c | 61 ++++ .../subbrute/scenes/subbrute_scene_start.c | 4 +- .../plugins/subbrute/subbrute_custom_event.h | 2 +- .../plugins/subbrute/subbrute_device.c | 9 +- .../plugins/subbrute/subbrute_device.h | 6 +- .../subbrute/views/subbrute_main_view.c | 320 ++++++++++++------ .../subbrute/views/subbrute_main_view.h | 6 +- 9 files changed, 303 insertions(+), 108 deletions(-) create mode 100644 applications/plugins/subbrute/scenes/subbrute_scene_load_select.c diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_config.h b/applications/plugins/subbrute/scenes/subbrute_scene_config.h index 40806279f..3541df9ac 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_config.h +++ b/applications/plugins/subbrute/scenes/subbrute_scene_config.h @@ -1,4 +1,5 @@ ADD_SCENE(subbrute, load_file, LoadFile) +ADD_SCENE(subbrute, load_select, LoadSelect) ADD_SCENE(subbrute, run_attack, RunAttack) ADD_SCENE(subbrute, save_name, SaveName) ADD_SCENE(subbrute, save_success, SaveSuccess) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c index f9bad3cea..6557b4ba1 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c @@ -48,7 +48,7 @@ void subbrute_scene_load_file_on_enter(void* context) { } if(load_result == SubBruteFileResultOk) { - scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadSelect); } else { FURI_LOG_E(TAG, "Returned error: %d", load_result); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c new file mode 100644 index 000000000..e3774e407 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c @@ -0,0 +1,61 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_main_view.h" + +#define TAG "SubBruteSceneStart" + +void subbrute_scene_load_select_callback(SubBruteCustomEvent event, void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_scene_load_select_callback"); +#endif + view_dispatcher_send_custom_event(instance->view_dispatcher, event); +} + +void subbrute_scene_load_select_on_enter(void* context) { + furi_assert(context); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_load_select_on_enter"); +#endif + SubBruteState* instance = (SubBruteState*)context; + SubBruteMainView* view = instance->view_main; + + instance->current_view = SubBruteViewMain; + subbrute_main_view_set_callback(view, subbrute_scene_load_select_callback, instance); + subbrute_main_view_set_index(view, 7, true, instance->device->file_key); + + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); +} + +void subbrute_scene_load_select_on_exit(void* context) { + UNUSED(context); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_load_select_on_exit"); +#endif +} + +bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubBruteCustomEventTypeIndexSelected) { + instance->device->load_index = subbrute_main_view_get_index(instance->view_main); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "load_index: %d", instance->device->load_index); +#endif + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(!scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneStart)) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); + } + consumed = true; + } + + return consumed; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index eb00265b4..fe3a5d8b4 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -24,7 +24,7 @@ void subbrute_scene_start_on_enter(void* context) { instance->current_view = SubBruteViewMain; subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance); - subbrute_main_view_set_index(view, instance->device->attack); + subbrute_main_view_set_index(view, instance->device->attack, false, NULL); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } @@ -55,7 +55,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); consumed = true; } - } else if (event.type == SceneManagerEventTypeBack) { + } else if(event.type == SceneManagerEventTypeBack) { //exit app scene_manager_stop(instance->scene_manager); view_dispatcher_stop(instance->view_dispatcher); diff --git a/applications/plugins/subbrute/subbrute_custom_event.h b/applications/plugins/subbrute/subbrute_custom_event.h index c3b04ebdf..5ddab7fa1 100644 --- a/applications/plugins/subbrute/subbrute_custom_event.h +++ b/applications/plugins/subbrute/subbrute_custom_event.h @@ -8,7 +8,7 @@ typedef enum { SubBruteCustomEventTypeReserved = 100, SubBruteCustomEventTypeBackPressed, - SubBruteCustomEventTypeTextEditResult, + SubBruteCustomEventTypeIndexSelected, SubBruteCustomEventTypeTransmitStarted, SubBruteCustomEventTypeTransmitFinished, SubBruteCustomEventTypeTransmitNotStarted, diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 8c02beb62..02913d577 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -207,7 +207,7 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste char subbrute_payload_byte[4]; string_set_str(candidate, instance->file_key); snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step); - string_replace_at(candidate, step, 3, subbrute_payload_byte); + string_replace_at(candidate, instance->load_index * 3, 3, subbrute_payload_byte); //snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); } else { //snprintf(step_payload, sizeof(step_payload), "%16X", step); @@ -512,6 +512,9 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p break; } else { instance->bit = temp_data32; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Bit: %d", instance->bit); +#endif } // Key @@ -522,6 +525,9 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p } else { snprintf( instance->file_key, sizeof(instance->file_key), "%s", string_get_cstr(temp_str)); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Key: %s", instance->file_key); +#endif } // TE @@ -579,6 +585,7 @@ void subbrute_device_attack_set_default_values( #endif instance->attack = default_attack; instance->key_index = 0x00; + instance->load_index = 0x00; memset(instance->file_template, 0, sizeof(instance->file_template)); memset(instance->current_key, 0, sizeof(instance->current_key)); memset(instance->text_store, 0, sizeof(instance->text_store)); diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index f0d3d8a57..625c53d2a 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -8,7 +8,7 @@ #include #include -#define SUBBRUTE_TEXT_STORE_SIZE 128 +#define SUBBRUTE_TEXT_STORE_SIZE 256 #define SUBBRUTE_MAX_LEN_NAME 64 #define SUBBRUTE_PATH EXT_PATH("subghz") @@ -60,6 +60,8 @@ typedef struct { // Current step uint64_t key_index; string_t load_path; + // Index of group to bruteforce in loaded file + uint8_t load_index; SubGhzReceiver* receiver; SubGhzProtocolDecoderBase* decoder_result; @@ -82,7 +84,7 @@ typedef struct { char current_key[SUBBRUTE_PAYLOAD_SIZE]; uint32_t te; - char file_key[SUBBRUTE_PAYLOAD_SIZE]; + char file_key[SUBBRUTE_MAX_LEN_NAME]; char text_store[SUBBRUTE_PAYLOAD_SIZE]; } SubBruteDevice; diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 67342cc9c..5275a9774 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -18,6 +18,8 @@ struct SubBruteMainView { typedef struct { uint8_t index; uint8_t window_position; + bool is_select_byte; + const char* key_field; } SubBruteMainViewModel; void subbrute_main_view_set_callback( @@ -31,6 +33,51 @@ void subbrute_main_view_set_callback( instance->context = context; } +void center_displayed_key(string_t result, const char* key_cstr, uint8_t index) { + uint8_t str_index = (index * 3); + + char display_menu[] = { + 'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'}; + + if(key_cstr != NULL) { + if(index > 1) { + display_menu[0] = key_cstr[str_index - 6]; + display_menu[1] = key_cstr[str_index - 5]; + } else { + display_menu[0] = ' '; + display_menu[1] = ' '; + } + + if(index > 0) { + display_menu[3] = key_cstr[str_index - 3]; + display_menu[4] = key_cstr[str_index - 2]; + } else { + display_menu[3] = ' '; + display_menu[4] = ' '; + } + + display_menu[7] = key_cstr[str_index]; + display_menu[8] = key_cstr[str_index + 1]; + + if((str_index + 4) <= (uint8_t)strlen(key_cstr)) { + display_menu[11] = key_cstr[str_index + 3]; + display_menu[12] = key_cstr[str_index + 4]; + } else { + display_menu[11] = ' '; + display_menu[12] = ' '; + } + + if((str_index + 8) <= (uint8_t)strlen(key_cstr)) { + display_menu[14] = key_cstr[str_index + 6]; + display_menu[15] = key_cstr[str_index + 7]; + } else { + display_menu[14] = ' '; + display_menu[15] = ' '; + } + } + string_init_set_str(result, display_menu); +} + void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { SubBruteMainViewModel* m = model; @@ -41,49 +88,72 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); canvas_invert_color(canvas); - // Menu - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - uint8_t items_on_screen = 3; - const uint8_t item_height = 16; + if(m->is_select_byte) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "key_field: %s", m->key_field); +#endif + char msg_index[18]; + snprintf(msg_index, sizeof(msg_index), "Field index : %d", m->index); + canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index); + + string_t menu_items; + string_init(menu_items); + + center_displayed_key(menu_items, m->key_field, m->index); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(menu_items)); + + elements_button_center(canvas, "Select"); + elements_button_left(canvas, "<"); + elements_button_right(canvas, ">"); + + string_reset(menu_items); + } else { + // Menu + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + uint8_t items_on_screen = 3; + const uint8_t item_height = 16; #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); + FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); #endif - for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { - uint8_t item_position = position - model->window_position; + for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { + uint8_t item_position = position - model->window_position; - if(item_position < items_on_screen) { - const char* str = subbrute_get_menu_name(position); - if(m->index == position) { - canvas_draw_str_aligned( - canvas, - 64, - 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, - AlignCenter, - str); - elements_frame( - canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); - } else { - canvas_draw_str_aligned( - canvas, - 64, - 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, - AlignCenter, - str); + if(item_position < items_on_screen) { + const char* str = subbrute_get_menu_name(position); + if(m->index == position) { + canvas_draw_str_aligned( + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); + elements_frame( + canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); + } else { + canvas_draw_str_aligned( + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); + } } } - } - elements_scrollbar_pos( - canvas, - canvas_width(canvas), - STATUS_BAR_Y_SHIFT + 2, - canvas_height(canvas) - STATUS_BAR_Y_SHIFT, - m->index, - SubBruteAttackTotalCount); + elements_scrollbar_pos( + canvas, + canvas_width(canvas), + STATUS_BAR_Y_SHIFT + 2, + canvas_height(canvas) - STATUS_BAR_Y_SHIFT, + m->index, + SubBruteAttackTotalCount); + } } bool subbrute_main_view_input(InputEvent* event, void* context) { @@ -101,66 +171,107 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { const uint8_t min_value = 0; const uint8_t correct_total = SubBruteAttackTotalCount - 1; uint8_t index = 0; - - bool consumed = false; - if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { - with_view_model( - instance->view, (SubBruteMainViewModel * model) { - bool ret = false; - uint8_t items_on_screen = 3; - if(event->key == InputKeyUp) { - if(model->index == min_value) { - model->index = correct_total; - } else { - model->index = CLAMP(model->index - 1, correct_total, min_value); - } - ret = true; - consumed = true; - } else if(event->key == InputKeyDown) { - if(model->index == correct_total) { - model->index = min_value; - } else { - model->index = CLAMP(model->index + 1, correct_total, min_value); - } - ret = true; - consumed = true; - } - if(ret) { - model->window_position = model->index; - if(model->window_position > 0) { - model->window_position -= 1; - } - - if(SubBruteAttackTotalCount <= items_on_screen) { - model->window_position = 0; - } else { - if(model->window_position >= - (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = (SubBruteAttackTotalCount - items_on_screen); - } - } - } - index = model->index; - return ret; - }); - } - -#ifdef FURI_DEBUG + bool is_select_byte = false; with_view_model( instance->view, (SubBruteMainViewModel * model) { - index = model->index; + is_select_byte = model->is_select_byte; return false; }); - FURI_LOG_I(TAG, "Index: %d", index); + + bool consumed = false; + if(!is_select_byte) { + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + bool ret = false; + uint8_t items_on_screen = 3; + if(event->key == InputKeyUp) { + if(model->index == min_value) { + model->index = correct_total; + } else { + model->index = CLAMP(model->index - 1, correct_total, min_value); + } + ret = true; + consumed = true; + } else if(event->key == InputKeyDown) { + if(model->index == correct_total) { + model->index = min_value; + } else { + model->index = CLAMP(model->index + 1, correct_total, min_value); + } + ret = true; + consumed = true; + } + if(ret) { + model->window_position = model->index; + if(model->window_position > 0) { + model->window_position -= 1; + } + + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= + (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = + (SubBruteAttackTotalCount - items_on_screen); + } + } + } + index = model->index; + return ret; + }); + } + +#ifdef FURI_DEBUG + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + index = model->index; + return false; + }); + FURI_LOG_I(TAG, "Index: %d", index); #endif - if(event->key == InputKeyOk && event->type == InputTypeShort) { - if(index == SubBruteAttackLoadFile) { - instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); - } else { - instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + if(event->key == InputKeyOk && event->type == InputTypeShort) { + if(index == SubBruteAttackLoadFile) { + instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); + } else { + instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + } + consumed = true; + } + } else { + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + if(event->key == InputKeyLeft) { + if(model->index > 0) { + model->index--; + } + } else if(event->key == InputKeyRight) { + if(model->index < 7) { + model->index++; + } + } + + index = model->index; + return true; + }); + } + +#ifdef FURI_DEBUG + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + index = model->index; + return false; + }); + FURI_LOG_I(TAG, "Index: %d", index); +#endif + + if(event->key == InputKeyOk && event->type == InputTypeShort) { + instance->callback(SubBruteCustomEventTypeIndexSelected, instance->context); + consumed = true; } - consumed = true; } return consumed; @@ -196,6 +307,8 @@ SubBruteMainView* subbrute_main_view_alloc() { instance->view, (SubBruteMainViewModel * model) { model->index = 0; model->window_position = 0; + model->key_field = NULL; + model->is_select_byte = false; return true; }); @@ -214,7 +327,11 @@ View* subbrute_main_view_get_view(SubBruteMainView* instance) { return instance->view; } -void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { +void subbrute_main_view_set_index( + SubBruteMainView* instance, + uint8_t idx, + bool is_select_byte, + const char* key_field) { furi_assert(instance); furi_assert(idx < SubBruteAttackTotalCount); #ifdef FURI_DEBUG @@ -222,23 +339,26 @@ void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { #endif with_view_model( instance->view, (SubBruteMainViewModel * model) { + model->is_select_byte = is_select_byte; + model->key_field = key_field; model->index = idx; model->window_position = idx; - uint8_t items_on_screen = 3; + if(!is_select_byte) { + uint8_t items_on_screen = 3; - if(model->window_position > 0) { - model->window_position -= 1; - } + if(model->window_position > 0) { + model->window_position -= 1; + } - if(SubBruteAttackTotalCount <= items_on_screen) { - model->window_position = 0; - } else { - if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = (SubBruteAttackTotalCount - items_on_screen); + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = (SubBruteAttackTotalCount - items_on_screen); + } } } - return true; }); } diff --git a/applications/plugins/subbrute/views/subbrute_main_view.h b/applications/plugins/subbrute/views/subbrute_main_view.h index bb0e30b00..55a8bf0c3 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.h +++ b/applications/plugins/subbrute/views/subbrute_main_view.h @@ -19,7 +19,11 @@ SubBruteMainView* subbrute_main_view_alloc(); void subbrute_main_view_free(SubBruteMainView* instance); View* subbrute_main_view_get_view(SubBruteMainView* instance); -void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx); +void subbrute_main_view_set_index( + SubBruteMainView* instance, + uint8_t idx, + bool is_select_byte, + const char* key_field); uint8_t subbrute_main_view_get_index(SubBruteMainView* instance); void subbrute_attack_view_enter(void* context); From ba5f590dab568ca6ca00f7ae01e8a1026bcae407 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Mon, 26 Sep 2022 00:07:14 +0400 Subject: [PATCH 12/29] switched to manual transmit --- .../subbrute/helpers/subbrute_worker.c | 87 +++++++++++++++++- .../subbrute/helpers/subbrute_worker.h | 7 +- .../scenes/subbrute_scene_run_attack.c | 88 ++----------------- .../scenes/subbrute_scene_setup_attack.c | 25 +++--- .../subbrute/views/subbrute_attack_view.c | 11 ++- .../subbrute/views/subbrute_attack_view.h | 6 ++ 6 files changed, 131 insertions(+), 93 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 8e1994b95..cb75876c4 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -9,6 +9,7 @@ struct SubBruteWorker { FuriThread* thread; volatile bool worker_running; + volatile bool worker_manual_mode; SubGhzEnvironment* environment; SubGhzTransmitter* transmitter; @@ -102,6 +103,7 @@ SubBruteWorker* subbrute_worker_alloc() { //instance->status = SubBruteWorkerStatusIDLE; instance->worker_running = false; + instance->worker_manual_mode = false; instance->flipper_format = flipper_format_string_alloc(); string_init(instance->protocol_name); @@ -127,7 +129,10 @@ bool subbrute_worker_start( FuriHalSubGhzPreset preset, const char* protocol_name) { furi_assert(instance); - furi_assert(!instance->worker_running); + + if (instance->worker_manual_mode) { + return false; + } instance->frequency = frequency; instance->preset = preset; @@ -203,5 +208,85 @@ bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) { stream_write_cstring(stream, payload); subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); + return true; +} + +bool subbrute_worker_single_transmit(SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name, + const char* payload) { + furi_assert(instance); + + if (instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "cannot transmit"); +#endif + return false; + } + if (instance->worker_running) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_worker_stop"); +#endif + subbrute_worker_stop(instance); + } + + instance->last_time_tx_data = furi_get_tick(); + instance->worker_manual_mode = true; + + instance->preset = preset; + instance->frequency = frequency; + + string_clear(instance->protocol_name); + string_init_printf(instance->protocol_name, "%s", protocol_name); + + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_preset(instance->preset); + + furi_hal_subghz_set_frequency_and_path(instance->frequency); + furi_hal_subghz_flush_rx(); + + if(!furi_hal_subghz_is_tx_allowed(frequency)) { + instance->frequency = frequency; + instance->worker_manual_mode = false; + return false; + } + +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Frequency: %d", frequency); +#endif + + instance->environment = subghz_environment_alloc(); + instance->transmitter = subghz_transmitter_alloc_init( + instance->environment, string_get_cstr(instance->protocol_name)); + + Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); + stream_clean(stream); + stream_write_cstring(stream, payload); + subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); + + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(instance->preset); + frequency = furi_hal_subghz_set_frequency_and_path(frequency); + + furi_hal_power_suppress_charge_enter(); + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter); + + while(!furi_hal_subghz_is_async_tx_complete()) { + furi_delay_ms(SUBBRUTE_SEND_DELAY); + } + furi_hal_subghz_stop_async_tx(); + furi_hal_subghz_sleep(); + + furi_hal_power_suppress_charge_exit(); + + subghz_transmitter_free(instance->transmitter); + instance->transmitter = NULL; + subghz_environment_free(instance->environment); + instance->environment = NULL; + + instance->worker_manual_mode = false; + return true; } \ No newline at end of file diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h index 5d2a21831..aa6c898bd 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.h +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -26,4 +26,9 @@ void subbrute_worker_stop(SubBruteWorker* instance); //bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size); bool subbrute_worker_is_running(SubBruteWorker* instance); bool subbrute_worker_can_transmit(SubBruteWorker* instance); -bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload); \ No newline at end of file +bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload); +bool subbrute_worker_single_transmit(SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name, + const char* payload); \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c index 55431cdd0..fbb6dccce 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -33,11 +33,11 @@ void subbrute_scene_run_attack_on_enter(void* context) { true); // Start worker if not started - subbrute_attack_view_start_worker( + /*subbrute_attack_view_start_worker( view, instance->device->frequency, instance->device->preset, - string_get_cstr(instance->device->protocol_name)); + string_get_cstr(instance->device->protocol_name));*/ } bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { @@ -58,7 +58,12 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) // Blink notification_message(instance->notifications, &sequence_blink_yellow_100); - if(subbrute_attack_view_transmit(view, instance->device->payload)) { + if(subbrute_attack_view_single_transmit( + view, + instance->device->frequency, + instance->device->preset, + string_get_cstr(instance->device->protocol_name), + instance->device->payload)) { // Make payload for new iteration or exit if(instance->device->key_index + 1 > instance->device->max_value) { // End of list @@ -79,81 +84,4 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) } return consumed; - - // if(event.evt_type == EventTypeKey) { - // if(event.input_type == InputTypeShort) { - // switch(event.key) { - // case InputKeyDown: - // break; - // case InputKeyUp: - // if(!context->is_attacking) { - // subbrute_send_packet_parsed(context); - // string_clear(context->flipper_format_string); - // toSave = true; - // context->current_scene = SceneSaveName; - // } - // break; - // case InputKeyLeft: - // if(!context->is_attacking && context->payload > 0x00) { - // context->payload--; - // subbrute_send_packet(context); - // notification_message(context->notify, &sequence_blink_blue_10); - // } else if(!context->is_attacking && context->payload == 0x00) { - // context->payload = max_value; - // subbrute_send_packet(context); - // notification_message(context->notify, &sequence_blink_blue_10); - // } - // break; - // case InputKeyRight: - // if(!context->is_attacking && context->payload < max_value) { - // context->payload++; - // subbrute_send_packet(context); - // notification_message(context->notify, &sequence_blink_blue_10); - // } else if(!context->is_attacking && context->payload == max_value) { - // context->payload = 0x00; - // subbrute_send_packet(context); - // notification_message(context->notify, &sequence_blink_blue_10); - // } - // break; - // case InputKeyOk: - // if(!context->is_attacking) { - // if(context->payload == max_value) { - // context->payload = 0x00; - // //subbrute_counter = 0; - // } - // context->is_attacking = true; - // start_bruthread(context); - // notification_message(context->notify, &sequence_blink_start_blue); - // } else { - // context->is_attacking = false; - // //context->close_thread_please = true; - // if(context->is_thread_running && context->bruthread) { - // furi_thread_join(context->bruthread); // wait until thread is finished - // } - // //context->close_thread_please = false; - // notification_message(context->notify, &sequence_blink_stop); - // notification_message(context->notify, &sequence_single_vibro); - // } - // break; - // case InputKeyBack: - // locked = false; - // //context->close_thread_please = true; - // context->is_attacking = false; - // if(context->is_thread_running && context->bruthread) { - // furi_thread_join(context->bruthread); // wait until thread is finished - // } - // //context->close_thread_please = false; - // string_reset(context->notification_msg); - // context->payload = 0x00; - // //subbrute_counter = 0; - // notification_message(context->notify, &sequence_blink_stop); - // if(context->attack == SubBruteAttackLoadFile) { - // context->current_scene = SceneSelectField; - // } else { - // context->current_scene = SceneEntryPoint; - // } - // break; - // } - // } - // } } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index 1ce6a3cde..0b3f8494e 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -52,7 +52,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event if(event.event == SubBruteCustomEventTypeTransmitStarted) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); } else if(event.event == SubBruteCustomEventTypeSaveFile) { - subbrute_attack_view_stop_worker(view); + //subbrute_attack_view_stop_worker(view); subbrute_attack_view_init_values( view, @@ -66,7 +66,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event FURI_LOG_D(TAG, "SubBruteCustomEventTypeBackPressed"); #endif instance->device->key_index = 0x00; - subbrute_attack_view_stop_worker(view); + //subbrute_attack_view_stop_worker(view); subbrute_attack_view_init_values( view, instance->device->attack, @@ -101,16 +101,21 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event // Blink notification_message(instance->notifications, &sequence_blink_green_100); - if(!subbrute_attack_view_is_worker_running(view)) { - subbrute_attack_view_start_worker( - view, - instance->device->frequency, - instance->device->preset, - string_get_cstr(instance->device->protocol_name)); - } + // if(!subbrute_attack_view_is_worker_running(view)) { + // subbrute_attack_view_start_worker( + // view, + // instance->device->frequency, + // instance->device->preset, + // string_get_cstr(instance->device->protocol_name)); + // } subbrute_device_create_packet_parsed( instance->device, instance->device->key_index); - subbrute_attack_view_transmit(view, instance->device->payload); + subbrute_attack_view_single_transmit( + view, + instance->device->frequency, + instance->device->preset, + string_get_cstr(instance->device->protocol_name), + instance->device->payload); // Stop notification_message(instance->notifications, &sequence_blink_stop); diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index 069c7aac1..7c86e7292 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -295,6 +295,16 @@ bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* pay return subbrute_worker_transmit(instance->worker, payload); } +bool subbrute_attack_view_single_transmit( + SubBruteAttackView* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name, + const char* payload) { + return subbrute_worker_single_transmit( + instance->worker, frequency, preset, protocol_name, payload); +} + bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance) { furi_assert(instance); @@ -306,7 +316,6 @@ void subbrute_attack_view_exit(void* context) { SubBruteAttackView* instance = context; #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_attack_view_exit"); - furi_delay_ms(150); #endif with_view_model( instance->view, (SubBruteAttackViewModel * model) { diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.h b/applications/plugins/subbrute/views/subbrute_attack_view.h index 3858f7ec2..067ecc2c7 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.h +++ b/applications/plugins/subbrute/views/subbrute_attack_view.h @@ -34,4 +34,10 @@ void subbrute_attack_view_start_worker( FuriHalSubGhzPreset preset, const char* protocol_name); bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* payload); +bool subbrute_attack_view_single_transmit( + SubBruteAttackView* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name, + const char* payload); bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance); \ No newline at end of file From a6b98ccbbe8b1aa7e3da4eefacca5987ad05b03e Mon Sep 17 00:00:00 2001 From: David Coles Date: Sun, 25 Sep 2022 14:06:46 -0700 Subject: [PATCH 13/29] Preliminary Rust support (#1781) * Add support for R_ARM_THM_MOVW_ABS_NC/THM_MOVT_ABS These are sometimes emitted by the Rust LLVM compiler. Ref: https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#56relocation * Discard LLVM bitcode from extension applications LLVM-based compilers may include uncompressed bitcode in object files to help with link-time optimization. However this can bloat binary sizes from KB to MB. * Expose alligned_malloc/free functions to applications This is required to implement a global allocator in Rust. --- firmware/targets/f7/api_symbols.csv | 4 +-- firmware/targets/f7/application-ext.ld | 2 ++ lib/flipper_application/elf/elf.h | 2 ++ lib/flipper_application/elf/elf_file.c | 41 ++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 39365c397..11b719ddb 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -433,8 +433,8 @@ Function,-,acoshl,long double,long double Function,-,acosl,long double,long double Function,+,acquire_mutex,void*,"ValueMutex*, uint32_t" Function,-,aligned_alloc,void*,"size_t, size_t" -Function,-,aligned_free,void,void* -Function,-,aligned_malloc,void*,"size_t, size_t" +Function,+,aligned_free,void,void* +Function,+,aligned_malloc,void*,"size_t, size_t" Function,-,arc4random,__uint32_t, Function,-,arc4random_buf,void,"void*, size_t" Function,-,arc4random_uniform,__uint32_t,__uint32_t diff --git a/firmware/targets/f7/application-ext.ld b/firmware/targets/f7/application-ext.ld index 8f79675be..01bb021b6 100644 --- a/firmware/targets/f7/application-ext.ld +++ b/firmware/targets/f7/application-ext.ld @@ -48,5 +48,7 @@ SECTIONS { *(.comment) *(.comment.*) + *(.llvmbc) + *(.llvmcmd) } } diff --git a/lib/flipper_application/elf/elf.h b/lib/flipper_application/elf/elf.h index f1697ba48..a36622b52 100644 --- a/lib/flipper_application/elf/elf.h +++ b/lib/flipper_application/elf/elf.h @@ -1116,6 +1116,8 @@ typedef struct { #define R_ARM_LDR_SBREL_11_0 35 #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_THM_MOVW_ABS_NC 47 /* Direct 16 bit (Thumb32 MOVW) */ +#define R_ARM_THM_MOVT_ABS 48 /* Direct high 16 bit */ #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index 202d0a875..e26165495 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -255,6 +255,42 @@ static void elf_relocate_jmp_call(ELFFile* elf, Elf32_Addr relAddr, int type, El (uint16_t)((lo & 0xc000) | (j1 << 13) | blx_bit | (j2 << 11) | imm11); } +static void elf_relocate_mov(Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { + uint16_t upper_insn = ((uint16_t*)relAddr)[0]; + uint16_t lower_insn = ((uint16_t*)relAddr)[1]; + + /* MOV* ,# + * + * i = upper[10] + * imm4 = upper[3:0] + * imm3 = lower[14:12] + * imm8 = lower[7:0] + * + * imm16 = imm4:i:imm3:imm8 + */ + uint32_t i = (upper_insn >> 10) & 1; /* upper[10] */ + uint32_t imm4 = upper_insn & 0x000F; /* upper[3:0] */ + uint32_t imm3 = (lower_insn >> 12) & 0x7; /* lower[14:12] */ + uint32_t imm8 = lower_insn & 0x00FF; /* lower[7:0] */ + + int32_t addend = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; /* imm16 */ + + uint32_t addr = (symAddr + addend); + if (type == R_ARM_THM_MOVT_ABS) { + addr >>= 16; /* upper 16 bits */ + } else { + addr &= 0x0000FFFF; /* lower 16 bits */ + } + + /* Re-encode */ + ((uint16_t*)relAddr)[0] = (upper_insn & 0xFBF0) + | (((addr >> 11) & 1) << 10) /* i */ + | ((addr >> 12) & 0x000F); /* imm4 */ + ((uint16_t*)relAddr)[1] = (lower_insn & 0x8F00) + | (((addr >> 8) & 0x7) << 12) /* imm3 */ + | (addr & 0x00FF); /* imm8 */ +} + static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf32_Addr symAddr) { switch(type) { case R_ARM_TARGET1: @@ -268,6 +304,11 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3 FURI_LOG_D( TAG, " R_ARM_THM_CALL/JMP relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); break; + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + elf_relocate_mov(relAddr, type, symAddr); + FURI_LOG_D(TAG, " R_ARM_THM_MOVW_ABS_NC/MOVT_ABS relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); + break; default: FURI_LOG_E(TAG, " Undefined relocation %d", type); return false; From 23f6ea2e05b1f9c844103088ccd0f9387a367198 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Mon, 26 Sep 2022 01:07:16 +0400 Subject: [PATCH 14/29] refactor worker moved it to SubBruteState --- .../subbrute/helpers/subbrute_worker.c | 116 ++++++++++++++---- .../subbrute/helpers/subbrute_worker.h | 11 +- .../scenes/subbrute_scene_run_attack.c | 16 +-- .../scenes/subbrute_scene_setup_attack.c | 18 +-- applications/plugins/subbrute/subbrute.c | 31 ++--- applications/plugins/subbrute/subbrute_i.h | 2 + .../subbrute/views/subbrute_attack_view.c | 71 ----------- .../subbrute/views/subbrute_attack_view.h | 17 +-- .../subbrute/views/subbrute_main_view.h | 2 - 9 files changed, 132 insertions(+), 152 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index cb75876c4..2e27638cc 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -10,6 +10,7 @@ struct SubBruteWorker { FuriThread* thread; volatile bool worker_running; volatile bool worker_manual_mode; + bool is_manual_init; SubGhzEnvironment* environment; SubGhzTransmitter* transmitter; @@ -30,7 +31,7 @@ struct SubBruteWorker { #define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048 #define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60 #define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 -#define SUBBRUTE_TX_TIMEOUT 200 +#define SUBBRUTE_TX_TIMEOUT 50 #define SUBBRUTE_SEND_DELAY 260 /** @@ -115,6 +116,16 @@ void subbrute_worker_free(SubBruteWorker* instance) { furi_assert(instance); furi_assert(!instance->worker_running); + if(instance->transmitter != NULL) { + subghz_transmitter_free(instance->transmitter); + instance->transmitter = NULL; + } + + if(instance->environment != NULL) { + subghz_environment_free(instance->environment); + instance->environment = NULL; + } + furi_thread_free(instance->thread); flipper_format_free(instance->flipper_format); @@ -130,7 +141,7 @@ bool subbrute_worker_start( const char* protocol_name) { furi_assert(instance); - if (instance->worker_manual_mode) { + if(instance->worker_manual_mode) { return false; } @@ -211,29 +222,39 @@ bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) { return true; } -bool subbrute_worker_single_transmit(SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name, - const char* payload) { - furi_assert(instance); - - if (instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) { +bool subbrute_worker_init_manual_transmit( + SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name) { +#ifdef FURI_DEBUG + FURI_LOG_D( + TAG, + "subbrute_worker_init_manual_transmit. frequency: %d, protocol: %s", + frequency, + protocol_name); +#endif + if(instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "cannot transmit"); #endif return false; } - if (instance->worker_running) { + if(instance->worker_running) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_worker_stop"); #endif subbrute_worker_stop(instance); } - instance->last_time_tx_data = furi_get_tick(); + // Not transmit at this period instance->worker_manual_mode = true; + if(instance->is_manual_init) { + FURI_LOG_E(TAG, "Trying to setup without normally shutdown prev transmit session!"); + subbrute_worker_manual_transmit_stop(instance); + } + instance->preset = preset; instance->frequency = frequency; @@ -248,6 +269,8 @@ bool subbrute_worker_single_transmit(SubBruteWorker* instance, furi_hal_subghz_flush_rx(); if(!furi_hal_subghz_is_tx_allowed(frequency)) { + FURI_LOG_E(TAG, "Frequency: %d invalid!", frequency); + instance->frequency = frequency; instance->worker_manual_mode = false; return false; @@ -261,30 +284,81 @@ bool subbrute_worker_single_transmit(SubBruteWorker* instance, instance->transmitter = subghz_transmitter_alloc_init( instance->environment, string_get_cstr(instance->protocol_name)); + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(instance->preset); + instance->frequency = furi_hal_subghz_set_frequency_and_path(frequency); + + instance->worker_manual_mode = false; + instance->is_manual_init = true; + + return true; +} + +void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_worker_manual_transmit_stop"); +#endif + if(!instance->is_manual_init) { + return; + } + + furi_hal_subghz_idle(); + furi_hal_subghz_sleep(); + + if(instance->transmitter != NULL) { + subghz_transmitter_free(instance->transmitter); + instance->transmitter = NULL; + } + subghz_environment_free(instance->environment); + instance->environment = NULL; + + instance->is_manual_init = false; +} + +bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload) { + furi_assert(instance); + + if(instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "cannot transmit"); +#endif + return false; + } + if(instance->worker_running) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_worker_stop"); +#endif + subbrute_worker_stop(instance); + } + if(!instance->is_manual_init) { + FURI_LOG_E(TAG, "Manually transmit doesn't set!"); + return false; + } + + instance->last_time_tx_data = furi_get_tick(); + instance->worker_manual_mode = true; + Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); stream_clean(stream); stream_write_cstring(stream, payload); - subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); + instance->transmitter = subghz_transmitter_alloc_init( + instance->environment, string_get_cstr(instance->protocol_name)); + subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); furi_hal_subghz_reset(); furi_hal_subghz_load_preset(instance->preset); - frequency = furi_hal_subghz_set_frequency_and_path(frequency); + instance->frequency = furi_hal_subghz_set_frequency_and_path(instance->frequency); - furi_hal_power_suppress_charge_enter(); furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter); while(!furi_hal_subghz_is_async_tx_complete()) { - furi_delay_ms(SUBBRUTE_SEND_DELAY); + furi_delay_ms(SUBBRUTE_TX_TIMEOUT); } furi_hal_subghz_stop_async_tx(); + furi_hal_subghz_sleep(); - - furi_hal_power_suppress_charge_exit(); - subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; - subghz_environment_free(instance->environment); - instance->environment = NULL; instance->worker_manual_mode = false; diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h index aa6c898bd..37875fa12 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.h +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -27,8 +27,9 @@ void subbrute_worker_stop(SubBruteWorker* instance); bool subbrute_worker_is_running(SubBruteWorker* instance); bool subbrute_worker_can_transmit(SubBruteWorker* instance); bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload); -bool subbrute_worker_single_transmit(SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name, - const char* payload); \ No newline at end of file +bool subbrute_worker_init_manual_transmit(SubBruteWorker* instance, + uint32_t frequency, + FuriHalSubGhzPreset preset, + const char* protocol_name); +bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload); +void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance); \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c index fbb6dccce..36a9e86f9 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -1,6 +1,7 @@ #include "../subbrute_i.h" #include "../subbrute_custom_event.h" #include "../views/subbrute_attack_view.h" +#include "../helpers/subbrute_worker.h" static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void* context) { furi_assert(context); @@ -33,11 +34,11 @@ void subbrute_scene_run_attack_on_enter(void* context) { true); // Start worker if not started - /*subbrute_attack_view_start_worker( - view, + subbrute_worker_init_manual_transmit( + instance->worker, instance->device->frequency, instance->device->preset, - string_get_cstr(instance->device->protocol_name));*/ + string_get_cstr(instance->device->protocol_name)); } bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { @@ -54,16 +55,11 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { - if(subbrute_attack_view_can_send(view)) { + if(subbrute_worker_can_transmit(instance->worker)) { // Blink notification_message(instance->notifications, &sequence_blink_yellow_100); - if(subbrute_attack_view_single_transmit( - view, - instance->device->frequency, - instance->device->preset, - string_get_cstr(instance->device->protocol_name), - instance->device->payload)) { + if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) { // Make payload for new iteration or exit if(instance->device->key_index + 1 > instance->device->max_value) { // End of list diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index 0b3f8494e..c7a96c751 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -27,7 +27,11 @@ void subbrute_scene_setup_attack_on_enter(void* context) { instance->device->key_index, false); - subbrute_attack_view_stop_worker(view); + subbrute_worker_init_manual_transmit( + instance->worker, + instance->device->frequency, + instance->device->preset, + string_get_cstr(instance->device->protocol_name)); instance->current_view = SubBruteViewAttack; subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); @@ -40,6 +44,7 @@ void subbrute_scene_setup_attack_on_exit(void* context) { FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit"); #endif SubBruteState* instance = (SubBruteState*)context; + subbrute_worker_manual_transmit_stop(instance->worker); notification_message(instance->notifications, &sequence_blink_stop); } @@ -52,7 +57,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event if(event.event == SubBruteCustomEventTypeTransmitStarted) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); } else if(event.event == SubBruteCustomEventTypeSaveFile) { - //subbrute_attack_view_stop_worker(view); + subbrute_worker_manual_transmit_stop(instance->worker); subbrute_attack_view_init_values( view, @@ -97,7 +102,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event instance->device->max_value; subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { - if(subbrute_attack_view_can_send(view)) { + if(subbrute_worker_can_transmit(instance->worker)) { // Blink notification_message(instance->notifications, &sequence_blink_green_100); @@ -110,12 +115,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event // } subbrute_device_create_packet_parsed( instance->device, instance->device->key_index); - subbrute_attack_view_single_transmit( - view, - instance->device->frequency, - instance->device->preset, - string_get_cstr(instance->device->protocol_name), - instance->device->payload); + subbrute_worker_manual_transmit(instance->worker, instance->device->payload); // Stop notification_message(instance->notifications, &sequence_blink_stop); diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index b54911fdb..fb6e15882 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -92,6 +92,9 @@ SubBruteState* subbrute_alloc() { // Devices instance->device = subbrute_device_alloc(); + // Worker + instance->worker = subbrute_worker_alloc(); + // TextInput instance->text_input = text_input_alloc(); view_dispatcher_add_view( @@ -145,6 +148,13 @@ void subbrute_free(SubBruteState* instance) { #endif subbrute_device_free(instance->device); + // SubBruteWorker +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteDevice"); +#endif + subbrute_worker_stop(instance->worker); + subbrute_worker_free(instance->worker); + // Notifications #ifdef FURI_DEBUG FURI_LOG_D(TAG, "free Notifications"); @@ -280,31 +290,16 @@ const char* subbrute_get_small_menu_name(SubBruteAttacks index) { // ENTRYPOINT int32_t subbrute_app(void* p) { UNUSED(p); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_app"); -#endif + SubBruteState* instance = subbrute_alloc(); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Starting subbrute_alloc done"); -#endif view_dispatcher_attach_to_gui( instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "scene_manager_next_scene set"); -#endif + furi_hal_power_suppress_charge_enter(); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "view_dispatcher_run"); -#endif view_dispatcher_run(instance->view_dispatcher); furi_hal_power_suppress_charge_exit(); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "before subbrute_free"); -#endif subbrute_free(instance); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "return 0"); -#endif + return 0; } \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_i.h b/applications/plugins/subbrute/subbrute_i.h index 51c84c898..28a9a73e3 100644 --- a/applications/plugins/subbrute/subbrute_i.h +++ b/applications/plugins/subbrute/subbrute_i.h @@ -31,6 +31,7 @@ #include #include "subbrute_device.h" +#include "helpers/subbrute_worker.h" #include "subbrute.h" #include "scenes/subbrute_scene.h" #include "views/subbrute_attack_view.h" @@ -68,6 +69,7 @@ struct SubBruteState { SceneManager* scene_manager; SubBruteDevice* device; + SubBruteWorker* worker; //Menu stuff // TODO: Do we need it? diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index 7c86e7292..4f43f786d 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -1,6 +1,5 @@ #include "subbrute_attack_view.h" #include "../subbrute_i.h" -#include "../helpers/subbrute_worker.h" #include "assets_icons.h" #include @@ -14,7 +13,6 @@ struct SubBruteAttackView { View* view; SubBruteAttackViewCallback callback; void* context; - SubBruteWorker* worker; }; typedef struct { @@ -89,14 +87,8 @@ bool subbrute_attack_view_input(InputEvent* event, void* context) { // instance->callback(SubBruteCustomEventTypeBackPressed, instance->context); // } } else if(event->key == InputKeyUp) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "InputKey: %d UP", event->key); -#endif instance->callback(SubBruteCustomEventTypeSaveFile, instance->context); } else if(event->key == InputKeyDown) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "InputKey: %d DOWN", event->key); -#endif instance->callback(SubBruteCustomEventTypeTransmitCustom, instance->context); } else if(event->type == InputTypeShort) { if(event->key == InputKeyLeft) { @@ -169,7 +161,6 @@ SubBruteAttackView* subbrute_attack_view_alloc() { view_set_enter_callback(instance->view, subbrute_attack_view_enter); view_set_exit_callback(instance->view, subbrute_attack_view_exit); - instance->worker = subbrute_worker_alloc(); return instance; } @@ -188,7 +179,6 @@ void subbrute_attack_view_free(SubBruteAttackView* instance) { #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_attack_view_free"); #endif - subbrute_worker_free(instance->worker); with_view_model( instance->view, (SubBruteAttackViewModel * model) { @@ -257,60 +247,6 @@ void subbrute_attack_view_init_values( }); } -void subbrute_attack_view_stop_worker(SubBruteAttackView* instance) { - furi_assert(instance); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_attack_view_stop_worker"); -#endif - subbrute_worker_stop(instance->worker); -} - -bool subbrute_attack_view_can_send(SubBruteAttackView* instance) { - furi_assert(instance); - return subbrute_worker_can_transmit(instance->worker); -} - -void subbrute_attack_view_start_worker( - SubBruteAttackView* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name) { - furi_assert(instance); -#ifdef FURI_DEBUG - FURI_LOG_D( - TAG, - "start_worker. frequency: %d, preset: %d, protocol_name: %s", - frequency, - preset, - protocol_name); -#endif - if(!subbrute_worker_is_running(instance->worker)) { - subbrute_worker_start(instance->worker, frequency, preset, protocol_name); - } -} - -bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* payload) { - furi_assert(instance); - - return subbrute_worker_transmit(instance->worker, payload); -} - -bool subbrute_attack_view_single_transmit( - SubBruteAttackView* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name, - const char* payload) { - return subbrute_worker_single_transmit( - instance->worker, frequency, preset, protocol_name, payload); -} - -bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance) { - furi_assert(instance); - - return subbrute_worker_is_running(instance->worker); -} - void subbrute_attack_view_exit(void* context) { furi_assert(context); SubBruteAttackView* instance = context; @@ -322,13 +258,6 @@ void subbrute_attack_view_exit(void* context) { icon_animation_stop(model->icon); return false; }); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_worker_stop"); - furi_delay_ms(150); -#endif - - // Just stop, make free in free method - subbrute_worker_stop(instance->worker); } void elements_button_top_left(Canvas* canvas, const char* str) { diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.h b/applications/plugins/subbrute/views/subbrute_attack_view.h index 067ecc2c7..e72d69d4c 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.h +++ b/applications/plugins/subbrute/views/subbrute_attack_view.h @@ -25,19 +25,4 @@ void subbrute_attack_view_init_values( uint8_t index, uint64_t max_value, uint64_t current_step, - bool is_attacking); -void subbrute_attack_view_stop_worker(SubBruteAttackView* instance); -bool subbrute_attack_view_can_send(SubBruteAttackView* instance); -void subbrute_attack_view_start_worker( - SubBruteAttackView* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name); -bool subbrute_attack_view_transmit(SubBruteAttackView* instance, const char* payload); -bool subbrute_attack_view_single_transmit( - SubBruteAttackView* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name, - const char* payload); -bool subbrute_attack_view_is_worker_running(SubBruteAttackView* instance); \ No newline at end of file + bool is_attacking); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_main_view.h b/applications/plugins/subbrute/views/subbrute_main_view.h index 55a8bf0c3..02eb3305a 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.h +++ b/applications/plugins/subbrute/views/subbrute_main_view.h @@ -18,14 +18,12 @@ void subbrute_main_view_set_callback( SubBruteMainView* subbrute_main_view_alloc(); void subbrute_main_view_free(SubBruteMainView* instance); View* subbrute_main_view_get_view(SubBruteMainView* instance); - void subbrute_main_view_set_index( SubBruteMainView* instance, uint8_t idx, bool is_select_byte, const char* key_field); uint8_t subbrute_main_view_get_index(SubBruteMainView* instance); - void subbrute_attack_view_enter(void* context); void subbrute_attack_view_exit(void* context); bool subbrute_attack_view_input(InputEvent* event, void* context); From 6f92cd645e6a76563fda35bfc0c49c47b02fb485 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Mon, 26 Sep 2022 01:09:00 +0400 Subject: [PATCH 15/29] fixed frame width to scroll --- applications/plugins/subbrute/views/subbrute_main_view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 5275a9774..141e3ce27 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -133,7 +133,7 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { AlignCenter, str); elements_frame( - canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); + canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 124, 15); } else { canvas_draw_str_aligned( canvas, From add1ad69495d8caa973f09bb6a2b9de8e5e8ff4f Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 01:48:51 +0400 Subject: [PATCH 16/29] fix manual select key on max and min values --- .../scenes/subbrute_scene_setup_attack.c | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index c7a96c751..1eaa48ba5 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -81,25 +81,49 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { // +1 - instance->device->key_index = - (instance->device->key_index + 1) % instance->device->max_value; + if ((instance->device->key_index + 1) - instance->device->max_value == 1) { + instance->device->key_index = 0x00; + } else { + uint64_t value = instance->device->key_index + 1; + if(value == instance->device->max_value) { + instance->device->key_index = value; + } else { + instance->device->key_index = value % instance->device->max_value; + } + } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) { // +100 - instance->device->key_index = - (instance->device->key_index + 100) % instance->device->max_value; + uint64_t value = instance->device->key_index + 100; + if(value == instance->device->max_value) { + instance->device->key_index += value; + } else { + instance->device->key_index = value % instance->device->max_value; + } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { // -1 - instance->device->key_index = - ((instance->device->key_index - 1) + instance->device->max_value) % - instance->device->max_value; + if (instance->device->key_index - 1 == 0) { + instance->device->key_index = 0x00; + } else if (instance->device->key_index == 0) { + instance->device->key_index = instance->device->max_value; + } else { + uint64_t value = ((instance->device->key_index - 1) + instance->device->max_value); + if(value == instance->device->max_value) { + instance->device->key_index = value; + } else { + instance->device->key_index = value % instance->device->max_value; + } + } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) { // -100 - instance->device->key_index = - ((instance->device->key_index - 100) + instance->device->max_value) % - instance->device->max_value; + uint64_t value = ((instance->device->key_index - 100) + instance->device->max_value); + if(value == instance->device->max_value) { + instance->device->key_index = value; + } else { + instance->device->key_index = value % instance->device->max_value; + } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { if(subbrute_worker_can_transmit(instance->worker)) { From 08084d5763d7a5d23e6260110fe25d43a6c4be4a Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 02:03:36 +0400 Subject: [PATCH 17/29] fix first send signal equals last transferred or 0x00 --- .../plugins/subbrute/scenes/subbrute_scene_setup_attack.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index 1eaa48ba5..22d0a3a5f 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -55,6 +55,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeTransmitStarted) { + subbrute_device_create_packet_parsed(instance->device, instance->device->key_index); scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); } else if(event.event == SubBruteCustomEventTypeSaveFile) { subbrute_worker_manual_transmit_stop(instance->worker); @@ -81,7 +82,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { // +1 - if ((instance->device->key_index + 1) - instance->device->max_value == 1) { + if((instance->device->key_index + 1) - instance->device->max_value == 1) { instance->device->key_index = 0x00; } else { uint64_t value = instance->device->key_index + 1; @@ -103,9 +104,9 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { // -1 - if (instance->device->key_index - 1 == 0) { + if(instance->device->key_index - 1 == 0) { instance->device->key_index = 0x00; - } else if (instance->device->key_index == 0) { + } else if(instance->device->key_index == 0) { instance->device->key_index = instance->device->max_value; } else { uint64_t value = ((instance->device->key_index - 1) + instance->device->max_value); From f2fd97d9c5a8b98b9570233b011959d8344a9577 Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 02:36:38 +0400 Subject: [PATCH 18/29] fix memory leaks --- applications/plugins/subbrute/helpers/subbrute_worker.c | 2 ++ applications/plugins/subbrute/subbrute_device.c | 1 + 2 files changed, 3 insertions(+) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 2e27638cc..c77dacfbf 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -360,6 +360,8 @@ bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* paylo subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; + stream_clean(stream); + instance->worker_manual_mode = false; return true; diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 02913d577..28b47562b 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -564,6 +564,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p subghz_environment_free(instance->environment); subghz_receiver_free(instance->receiver); + instance->decoder_result = NULL; instance->receiver = NULL; instance->environment = NULL; From 22dc5190d118da4e7771af13335749a61fed1937 Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 02:39:17 +0400 Subject: [PATCH 19/29] remove furi_hal_power_suppress_charge_enter/exit from other places --- applications/plugins/subbrute/helpers/subbrute_worker.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index c77dacfbf..bbfa1c32d 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -63,8 +63,6 @@ int32_t subbrute_worker_thread(void* context) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_cc1101_g0, true); - furi_hal_power_suppress_charge_enter(); - // Set ready to transmit value instance->last_time_tx_data = furi_get_tick() - SUBBRUTE_SEND_DELAY; @@ -80,8 +78,6 @@ int32_t subbrute_worker_thread(void* context) { furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); furi_hal_subghz_sleep(); - furi_hal_power_suppress_charge_exit(); - subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; subghz_environment_free(instance->environment); From ad9e1ce4dfacd4851dfe7006e0d35e27ebedf47f Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 02:42:39 +0400 Subject: [PATCH 20/29] set furi_hal_subghz_set_path to FuriHalSubGhzPathIsolate on each manual iteration --- applications/plugins/subbrute/helpers/subbrute_worker.c | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index bbfa1c32d..1701ba6eb 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -352,6 +352,7 @@ bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* paylo } furi_hal_subghz_stop_async_tx(); + furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); furi_hal_subghz_sleep(); subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; From 0c99cb52ec9237d614c543fcebb4905897679a54 Mon Sep 17 00:00:00 2001 From: derskythe Date: Mon, 26 Sep 2022 02:45:09 +0400 Subject: [PATCH 21/29] free transmitter during subbrute_worker_init_manual_transmit --- applications/plugins/subbrute/helpers/subbrute_worker.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 1701ba6eb..22e0e7ec4 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -284,6 +284,11 @@ bool subbrute_worker_init_manual_transmit( furi_hal_subghz_load_preset(instance->preset); instance->frequency = furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); + furi_hal_subghz_sleep(); + subghz_transmitter_free(instance->transmitter); + instance->transmitter = NULL; + instance->worker_manual_mode = false; instance->is_manual_init = true; From 5e30b14d90cc040d27c240706725e81fb6d844d4 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Sep 2022 02:12:11 +0300 Subject: [PATCH 22/29] update changelog --- CHANGELOG.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97389f6c2..c9ef2b85d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,6 @@ ### New changes -* Infrared: Updated universal remote assets (by @Amec0e) -* OFW PR: SubGHz: Read RAW - datetime in default names (+ format changed) (OFW PR 1772 by Skorpionm) -* OFW: Text input overwrite max size template -* OFW: Remove unused headers -* OFW: ELF-Loader: C++ plugin support, loader overhaul. -* OFW: Core: simplify record container +* PR: SubGHz bruteforcer plugin - deep refactoring (huge thanks to @derskythe ! | PR #75) +* OFW: Preliminary Rust support #### **DFU files no longer included in releases to avoid issues with wrong manual installation of assets - use .tgz file with qFlipper, or install automatically via web updater or use microSD update package** From 61fee8e2693ad45f8ddb9a26fe75e5001360e154 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Sep 2022 06:24:47 +0300 Subject: [PATCH 23/29] some fixes, trying to speed up bruteforce(unsuccessful) --- .../subbrute/helpers/subbrute_worker.c | 27 ++++++++++--------- .../scenes/subbrute_scene_run_attack.c | 6 +++-- .../scenes/subbrute_scene_setup_attack.c | 10 +++---- applications/plugins/subbrute/subbrute.c | 12 ++++----- .../plugins/subbrute/subbrute_device.c | 14 +++++----- .../subbrute/views/subbrute_main_view.c | 8 +++--- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 22e0e7ec4..c821506a2 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -31,7 +31,7 @@ struct SubBruteWorker { #define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048 #define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60 #define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 -#define SUBBRUTE_TX_TIMEOUT 50 +#define SUBBRUTE_TX_TIMEOUT 1 #define SUBBRUTE_SEND_DELAY 260 /** @@ -52,7 +52,7 @@ int32_t subbrute_worker_thread(void* context) { FURI_LOG_I(TAG, "Worker start"); #endif - instance->environment = subghz_environment_alloc(); + //instance->environment = subghz_environment_alloc(); instance->transmitter = subghz_transmitter_alloc_init( instance->environment, string_get_cstr(instance->protocol_name)); @@ -64,7 +64,7 @@ int32_t subbrute_worker_thread(void* context) { furi_hal_gpio_write(&gpio_cc1101_g0, true); // Set ready to transmit value - instance->last_time_tx_data = furi_get_tick() - SUBBRUTE_SEND_DELAY; + //instance->last_time_tx_data = furi_get_tick() - SUBBRUTE_SEND_DELAY; while(instance->worker_running) { // Transmit @@ -80,8 +80,8 @@ int32_t subbrute_worker_thread(void* context) { subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; - subghz_environment_free(instance->environment); - instance->environment = NULL; + /*subghz_environment_free(instance->environment); + instance->environment = NULL;*/ #ifdef FURI_DEBUG FURI_LOG_I(TAG, "Worker stop"); @@ -117,10 +117,10 @@ void subbrute_worker_free(SubBruteWorker* instance) { instance->transmitter = NULL; } - if(instance->environment != NULL) { + /*if(instance->environment != NULL) { subghz_environment_free(instance->environment); instance->environment = NULL; - } + }*/ furi_thread_free(instance->thread); flipper_format_free(instance->flipper_format); @@ -190,9 +190,10 @@ bool subbrute_worker_is_running(SubBruteWorker* instance) { } bool subbrute_worker_can_transmit(SubBruteWorker* instance) { - furi_assert(instance); - - return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY; + UNUSED(instance); + return true; + //furi_assert(instance); + //return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY; } bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) { @@ -276,7 +277,7 @@ bool subbrute_worker_init_manual_transmit( FURI_LOG_I(TAG, "Frequency: %d", frequency); #endif - instance->environment = subghz_environment_alloc(); + //instance->environment = subghz_environment_alloc(); instance->transmitter = subghz_transmitter_alloc_init( instance->environment, string_get_cstr(instance->protocol_name)); @@ -310,8 +311,8 @@ void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance) { subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; } - subghz_environment_free(instance->environment); - instance->environment = NULL; + /*subghz_environment_free(instance->environment); + instance->environment = NULL;*/ instance->is_manual_init = false; } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c index 36a9e86f9..209eb9df8 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -39,6 +39,8 @@ void subbrute_scene_run_attack_on_enter(void* context) { instance->device->frequency, instance->device->preset, string_get_cstr(instance->device->protocol_name)); + + notification_message(instance->notifications, &sequence_blink_start_magenta); } bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { @@ -57,12 +59,13 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) } else if(event.type == SceneManagerEventTypeTick) { if(subbrute_worker_can_transmit(instance->worker)) { // Blink - notification_message(instance->notifications, &sequence_blink_yellow_100); if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) { // Make payload for new iteration or exit if(instance->device->key_index + 1 > instance->device->max_value) { // End of list + notification_message(instance->notifications, &sequence_single_vibro); + notification_message(instance->notifications, &sequence_blink_stop); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); } else { instance->device->key_index++; @@ -73,7 +76,6 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) } // Stop - notification_message(instance->notifications, &sequence_blink_stop); } consumed = true; diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index 22d0a3a5f..7929b5d73 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -94,8 +94,8 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) { - // +100 - uint64_t value = instance->device->key_index + 100; + // +50 + uint64_t value = instance->device->key_index + 50; if(value == instance->device->max_value) { instance->device->key_index += value; } else { @@ -118,8 +118,8 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event } subbrute_attack_view_set_current_step(view, instance->device->key_index); } else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) { - // -100 - uint64_t value = ((instance->device->key_index - 100) + instance->device->max_value); + // -50 + uint64_t value = ((instance->device->key_index - 50) + instance->device->max_value); if(value == instance->device->max_value) { instance->device->key_index = value; } else { @@ -129,7 +129,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { if(subbrute_worker_can_transmit(instance->worker)) { // Blink - notification_message(instance->notifications, &sequence_blink_green_100); + notification_message(instance->notifications, &sequence_blink_magenta_10); // if(!subbrute_attack_view_is_worker_running(view)) { // subbrute_attack_view_start_worker( diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index fb6e15882..b3cc25caf 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -142,12 +142,6 @@ SubBruteState* subbrute_alloc() { void subbrute_free(SubBruteState* instance) { furi_assert(instance); - // SubBruteDevice -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteDevice"); -#endif - subbrute_device_free(instance->device); - // SubBruteWorker #ifdef FURI_DEBUG FURI_LOG_D(TAG, "free SubBruteDevice"); @@ -155,6 +149,12 @@ void subbrute_free(SubBruteState* instance) { subbrute_worker_stop(instance->worker); subbrute_worker_free(instance->worker); + // SubBruteDevice +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "free SubBruteDevice"); +#endif + subbrute_device_free(instance->device); + // Notifications #ifdef FURI_DEBUG FURI_LOG_D(TAG, "free Notifications"); diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 28b47562b..e8b33a9ec 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -60,6 +60,8 @@ SubBruteDevice* subbrute_device_alloc() { instance->receiver = NULL; instance->environment = NULL; + instance->environment = subghz_environment_alloc(); + subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307); return instance; @@ -337,7 +339,7 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute } // For non-file types we didn't set SubGhzProtocolDecoderBase - instance->environment = subghz_environment_alloc(); + //instance->environment = subghz_environment_alloc(); instance->receiver = subghz_receiver_alloc_init(instance->environment); subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); furi_hal_subghz_reset(); @@ -359,10 +361,10 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute protocol_check_result = SubBruteFileResultOk; } - subghz_environment_free(instance->environment); + //subghz_environment_free(instance->environment); subghz_receiver_free(instance->receiver); instance->receiver = NULL; - instance->environment = NULL; + //instance->environment = NULL; if(protocol_check_result != SubBruteFileResultOk) { return SubBruteFileResultProtocolNotFound; @@ -426,7 +428,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p string_init(temp_str); uint32_t temp_data32; - instance->environment = subghz_environment_alloc(); + //instance->environment = subghz_environment_alloc(); instance->receiver = subghz_receiver_alloc_init(instance->environment); subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); furi_hal_subghz_reset(); @@ -561,12 +563,12 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); - subghz_environment_free(instance->environment); + //subghz_environment_free(instance->environment); subghz_receiver_free(instance->receiver); instance->decoder_result = NULL; instance->receiver = NULL; - instance->environment = NULL; + //instance->environment = NULL; if(result == SubBruteFileResultOk) { #ifdef FURI_DEBUG diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 141e3ce27..8d8bf477e 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -127,9 +127,9 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { if(m->index == position) { canvas_draw_str_aligned( canvas, - 64, + 4, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, + AlignLeft, AlignCenter, str); elements_frame( @@ -137,9 +137,9 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { } else { canvas_draw_str_aligned( canvas, - 64, + 4, 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, + AlignLeft, AlignCenter, str); } From efb09380bd4fcc5e2702ddf66d67db89f9772443 Mon Sep 17 00:00:00 2001 From: hedger Date: Mon, 26 Sep 2022 15:03:21 +0400 Subject: [PATCH 24/29] [FL-2836] Fast flash programming mode (#1782) * updater: lowered logging level for resources unpacking; hal: implemented fast flash write mode * hal: reworked fast flash programming; clearing most error flags on flash init; changed some flash functions return type from bool to void; scripts: fixed malformed CRC values in update bundles in certain cases; * hal: flash: larger critical section * hal: flash: enabling fast write inside critical section * api_symbols: bump minor version --- .../services/storage/storages/storage_int.c | 14 +- .../updater/util/update_task_worker_flasher.c | 12 +- firmware/targets/f7/api_symbols.csv | 8 +- firmware/targets/f7/furi_hal/furi_hal_flash.c | 143 +++++++++++------- firmware/targets/f7/furi_hal/furi_hal_flash.h | 12 +- lib/toolbox/tar/tar_archive.c | 2 +- scripts/update.py | 2 +- 7 files changed, 110 insertions(+), 83 deletions(-) diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c index cae61f16e..758397354 100644 --- a/applications/services/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -109,10 +109,7 @@ static int storage_int_device_prog( int ret = 0; while(size > 0) { - if(!furi_hal_flash_write_dword(address, *(uint64_t*)buffer)) { - ret = -1; - break; - } + furi_hal_flash_write_dword(address, *(uint64_t*)buffer); address += c->prog_size; buffer += c->prog_size; size -= c->prog_size; @@ -127,16 +124,13 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc FURI_LOG_D(TAG, "Device erase: page %d, translated page: %x", block, page); - if(furi_hal_flash_erase(page)) { - return 0; - } else { - return -1; - } + furi_hal_flash_erase(page); + return 0; } static int storage_int_device_sync(const struct lfs_config* c) { UNUSED(c); - FURI_LOG_D(TAG, "Device sync: skipping, cause "); + FURI_LOG_D(TAG, "Device sync: skipping"); return 0; } diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index d56b4ae0a..7b598c50b 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -52,11 +52,19 @@ static bool check_address_boundaries(const size_t address) { return ((address >= min_allowed_address) && (address < max_allowed_address)); } +static bool update_task_flash_program_page( + const uint8_t i_page, + const uint8_t* update_block, + uint16_t update_block_len) { + furi_hal_flash_program_page(i_page, update_block, update_block_len); + return true; +} + static bool update_task_write_dfu(UpdateTask* update_task) { DfuUpdateTask page_task = { .address_cb = &check_address_boundaries, .progress_cb = &update_task_file_progress, - .task_cb = &furi_hal_flash_program_page, + .task_cb = &update_task_flash_program_page, .context = update_task, }; @@ -117,7 +125,7 @@ static bool update_task_write_stack_data(UpdateTask* update_task) { furi_hal_flash_get_page_number(update_task->manifest->radio_address + element_offs); CHECK_RESULT(i_page >= 0); - CHECK_RESULT(furi_hal_flash_program_page(i_page, fw_block, bytes_read)); + furi_hal_flash_program_page(i_page, fw_block, bytes_read); element_offs += bytes_read; update_task_set_progress( diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 11b719ddb..c8e6a6cf4 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.10,, +Version,+,1.11,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -986,7 +986,7 @@ Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, Function,-,furi_hal_deinit_early,void, -Function,-,furi_hal_flash_erase,_Bool,uint8_t +Function,-,furi_hal_flash_erase,void,uint8_t Function,-,furi_hal_flash_get_base,size_t, Function,-,furi_hal_flash_get_cycles_count,size_t, Function,-,furi_hal_flash_get_free_end_address,const void*, @@ -1001,8 +1001,8 @@ Function,-,furi_hal_flash_init,void, Function,-,furi_hal_flash_ob_apply,void, Function,-,furi_hal_flash_ob_get_raw_ptr,const FuriHalFlashRawOptionByteData*, Function,-,furi_hal_flash_ob_set_word,_Bool,"size_t, const uint32_t" -Function,-,furi_hal_flash_program_page,_Bool,"const uint8_t, const uint8_t*, uint16_t" -Function,-,furi_hal_flash_write_dword,_Bool,"size_t, uint64_t" +Function,-,furi_hal_flash_program_page,void,"const uint8_t, const uint8_t*, uint16_t" +Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index 9e05dc123..f99cf8c3d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -21,7 +21,6 @@ (FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_SIZERR | \ FLASH_SR_PGSERR | FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_RDERR | FLASH_SR_OPTVERR) -//#define FURI_HAL_FLASH_OB_START_ADDRESS 0x1FFF8000 #define FURI_HAL_FLASH_OPT_KEY1 0x08192A3B #define FURI_HAL_FLASH_OPT_KEY2 0x4C5D6E7F #define FURI_HAL_FLASH_OB_TOTAL_WORDS (0x80 / (sizeof(uint32_t) * 2)) @@ -80,9 +79,13 @@ size_t furi_hal_flash_get_free_page_count() { } void furi_hal_flash_init() { - // Errata 2.2.9, Flash OPTVERR flag is always set after system reset - WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR); - //__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR); + /* Errata 2.2.9, Flash OPTVERR flag is always set after system reset */ + // WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR); + /* Actually, reset all error flags on start */ + if(READ_BIT(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS)) { + FURI_LOG_E(TAG, "FLASH->SR 0x%08X", FLASH->SR); + WRITE_REG(FLASH->SR, FURI_HAL_FLASH_SR_ERRORS); + } } static void furi_hal_flash_unlock() { @@ -91,6 +94,7 @@ static void furi_hal_flash_unlock() { /* Authorize the FLASH Registers access */ WRITE_REG(FLASH->KEYR, FURI_HAL_FLASH_KEY1); + __ISB(); WRITE_REG(FLASH->KEYR, FURI_HAL_FLASH_KEY2); /* verify Flash is unlocked */ @@ -110,38 +114,38 @@ static void furi_hal_flash_lock(void) { } static void furi_hal_flash_begin_with_core2(bool erase_flag) { - // Take flash controller ownership + /* Take flash controller ownership */ while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) { furi_thread_yield(); } - // Unlock flash operation + /* Unlock flash operation */ furi_hal_flash_unlock(); - // Erase activity notification + /* Erase activity notification */ if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON); - // 64mHz 5us core2 flag protection + /* 64mHz 5us core2 flag protection */ for(volatile uint32_t i = 0; i < 35; i++) ; while(true) { - // Wait till flash controller become usable + /* Wait till flash controller become usable */ while(LL_FLASH_IsActiveFlag_OperationSuspended()) { furi_thread_yield(); }; - // Just a little more love + /* Just a little more love */ taskENTER_CRITICAL(); - // Actually we already have mutex for it, but specification is specification + /* Actually we already have mutex for it, but specification is specification */ if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { taskEXIT_CRITICAL(); furi_thread_yield(); continue; } - // Take sempahopre and prevent core2 from anything funky + /* Take sempahopre and prevent core2 from anything funky */ if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) { taskEXIT_CRITICAL(); furi_thread_yield(); @@ -153,10 +157,10 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) { } static void furi_hal_flash_begin(bool erase_flag) { - // Acquire dangerous ops mutex + /* Acquire dangerous ops mutex */ furi_hal_bt_lock_core2(); - // If Core2 is running use IPC locking + /* If Core2 is running use IPC locking */ if(furi_hal_bt_is_alive()) { furi_hal_flash_begin_with_core2(erase_flag); } else { @@ -165,36 +169,36 @@ static void furi_hal_flash_begin(bool erase_flag) { } static void furi_hal_flash_end_with_core2(bool erase_flag) { - // Funky ops are ok at this point + /* Funky ops are ok at this point */ LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0); - // Task switching is ok + /* Task switching is ok */ taskEXIT_CRITICAL(); - // Doesn't make much sense, does it? + /* Doesn't make much sense, does it? */ while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) { furi_thread_yield(); } - // Erase activity over, core2 can continue + /* Erase activity over, core2 can continue */ if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF); - // Lock flash controller + /* Lock flash controller */ furi_hal_flash_lock(); - // Release flash controller ownership + /* Release flash controller ownership */ LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0); } static void furi_hal_flash_end(bool erase_flag) { - // If Core2 is running use IPC locking + /* If Core2 is running - use IPC locking */ if(furi_hal_bt_is_alive()) { furi_hal_flash_end_with_core2(erase_flag); } else { furi_hal_flash_lock(); } - // Release dangerous ops mutex + /* Release dangerous ops mutex */ furi_hal_bt_unlock_core2(); } @@ -226,9 +230,9 @@ bool furi_hal_flash_wait_last_operation(uint32_t timeout) { uint32_t error = 0; uint32_t countdown = 0; - // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. - // Even if the FLASH operation fails, the BUSY flag will be reset and an error - // flag will be set + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ countdown = timeout; while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) { if(LL_SYSTICK_IsActiveCounterFlag()) { @@ -269,10 +273,10 @@ bool furi_hal_flash_wait_last_operation(uint32_t timeout) { return true; } -bool furi_hal_flash_erase(uint8_t page) { +void furi_hal_flash_erase(uint8_t page) { furi_hal_flash_begin(true); - // Ensure that controller state is valid + /* Ensure that controller state is valid */ furi_check(FLASH->SR == 0); /* Verify that next operation can be proceed */ @@ -292,30 +296,31 @@ bool furi_hal_flash_erase(uint8_t page) { furi_hal_flush_cache(); furi_hal_flash_end(true); - - return true; } -static inline bool furi_hal_flash_write_dword_internal(size_t address, uint64_t* data) { +static inline void furi_hal_flash_write_dword_internal_nowait(size_t address, uint64_t* data) { /* Program first word */ *(uint32_t*)address = (uint32_t)*data; - // Barrier to ensure programming is performed in 2 steps, in right order - // (independently of compiler optimization behavior) + /* Barrier to ensure programming is performed in 2 steps, in right order + (independently of compiler optimization behavior) */ __ISB(); /* Program second word */ *(uint32_t*)(address + 4U) = (uint32_t)(*data >> 32U); +} + +static inline void furi_hal_flash_write_dword_internal(size_t address, uint64_t* data) { + furi_hal_flash_write_dword_internal_nowait(address, data); /* Wait for last operation to be completed */ furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); - return true; } -bool furi_hal_flash_write_dword(size_t address, uint64_t data) { +void furi_hal_flash_write_dword(size_t address, uint64_t data) { furi_hal_flash_begin(false); - // Ensure that controller state is valid + /* Ensure that controller state is valid */ furi_check(FLASH->SR == 0); /* Check the parameters */ @@ -326,7 +331,7 @@ bool furi_hal_flash_write_dword(size_t address, uint64_t data) { SET_BIT(FLASH->CR, FLASH_CR_PG); /* Do the thing */ - furi_check(furi_hal_flash_write_dword_internal(address, &data)); + furi_hal_flash_write_dword_internal(address, &data); /* If the program operation is completed, disable the PG or FSTPG Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_PG); @@ -335,14 +340,13 @@ bool furi_hal_flash_write_dword(size_t address, uint64_t data) { /* Wait for last operation to be completed */ furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); - return true; } static size_t furi_hal_flash_get_page_address(uint8_t page) { return furi_hal_flash_get_base() + page * FURI_HAL_FLASH_PAGE_SIZE; } -bool furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16_t _length) { +void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16_t _length) { uint16_t length = _length; furi_check(length <= FURI_HAL_FLASH_PAGE_SIZE); @@ -350,37 +354,63 @@ bool furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16 furi_hal_flash_begin(false); - // Ensure that controller state is valid + furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); + + /* Ensure that controller state is valid */ furi_check(FLASH->SR == 0); size_t page_start_address = furi_hal_flash_get_page_address(page); - /* Set PG bit */ - SET_BIT(FLASH->CR, FLASH_CR_PG); - size_t i_dwords = 0; - for(i_dwords = 0; i_dwords < (length / 8); ++i_dwords) { - /* Do the thing */ - size_t data_offset = i_dwords * 8; - furi_check(furi_hal_flash_write_dword_internal( - page_start_address + data_offset, (uint64_t*)&data[data_offset])); + size_t length_written = 0; + + const uint16_t FAST_PROG_BLOCK_SIZE = 512; + const uint8_t DWORD_PROG_BLOCK_SIZE = 8; + + /* Write as much data as we can in fast mode */ + if(length >= FAST_PROG_BLOCK_SIZE) { + taskENTER_CRITICAL(); + /* Enable fast flash programming mode */ + SET_BIT(FLASH->CR, FLASH_CR_FSTPG); + + while(length_written < (length / FAST_PROG_BLOCK_SIZE * FAST_PROG_BLOCK_SIZE)) { + /* No context switch in the middle of the operation */ + furi_hal_flash_write_dword_internal_nowait( + page_start_address + length_written, (uint64_t*)(data + length_written)); + length_written += DWORD_PROG_BLOCK_SIZE; + + if((length_written % FAST_PROG_BLOCK_SIZE) == 0) { + /* Wait for block operation to be completed */ + furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); + } + } + CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG); + taskEXIT_CRITICAL(); } - if((length % 8) != 0) { + + /* Enable regular (dword) programming mode */ + SET_BIT(FLASH->CR, FLASH_CR_PG); + if((length % FAST_PROG_BLOCK_SIZE) != 0) { + /* Write tail in regular, dword mode */ + while(length_written < (length / DWORD_PROG_BLOCK_SIZE * DWORD_PROG_BLOCK_SIZE)) { + furi_hal_flash_write_dword_internal( + page_start_address + length_written, (uint64_t*)&data[length_written]); + length_written += DWORD_PROG_BLOCK_SIZE; + } + } + + if((length % DWORD_PROG_BLOCK_SIZE) != 0) { /* there are more bytes, not fitting into dwords */ uint64_t tail_data = 0; - size_t data_offset = i_dwords * 8; - for(int32_t tail_i = 0; tail_i < (length % 8); ++tail_i) { - tail_data |= (((uint64_t)data[data_offset + tail_i]) << (tail_i * 8)); + for(int32_t tail_i = 0; tail_i < (length % DWORD_PROG_BLOCK_SIZE); ++tail_i) { + tail_data |= (((uint64_t)data[length_written + tail_i]) << (tail_i * 8)); } - furi_check( - furi_hal_flash_write_dword_internal(page_start_address + data_offset, &tail_data)); + furi_hal_flash_write_dword_internal(page_start_address + length_written, &tail_data); } - - /* If the program operation is completed, disable the PG or FSTPG Bit */ + /* Disable the PG Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_PG); furi_hal_flash_end(false); - return true; } int16_t furi_hal_flash_get_page_number(size_t address) { @@ -462,6 +492,7 @@ static const FuriHalFlashObMapping furi_hal_flash_ob_reg_map[FURI_HAL_FLASH_OB_T OB_REG_DEF(FuriHalFlashObRegisterSecureFlash, (NULL)), OB_REG_DEF(FuriHalFlashObRegisterC2Opts, (NULL)), }; +#undef OB_REG_DEF void furi_hal_flash_ob_apply() { furi_hal_flash_ob_unlock(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.h b/firmware/targets/f7/furi_hal/furi_hal_flash.h index 1ed4c0399..9fa8f94af 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.h +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.h @@ -90,10 +90,8 @@ size_t furi_hal_flash_get_free_page_count(); * @warning locking operation with critical section, stalls execution * * @param page The page to erase - * - * @return true on success */ -bool furi_hal_flash_erase(uint8_t page); +void furi_hal_flash_erase(uint8_t page); /** Write double word (64 bits) * @@ -101,10 +99,8 @@ bool furi_hal_flash_erase(uint8_t page); * * @param address destination address, must be double word aligned. * @param data data to write - * - * @return true on success */ -bool furi_hal_flash_write_dword(size_t address, uint64_t data); +void furi_hal_flash_write_dword(size_t address, uint64_t data); /** Write aligned page data (up to page size) * @@ -113,10 +109,8 @@ bool furi_hal_flash_write_dword(size_t address, uint64_t data); * @param address destination address, must be page aligned. * @param data data to write * @param length data length - * - * @return true on success */ -bool furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16_t length); +void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16_t length); /** Get flash page number for address * diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 0d42d162c..f51d62317 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -209,7 +209,7 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header, path_concat(op_params->work_dir, string_get_cstr(converted_fname), full_extracted_fname); string_clear(converted_fname); - FURI_LOG_I(TAG, "Extracting %d bytes to '%s'", header->size, header->name); + FURI_LOG_D(TAG, "Extracting %d bytes to '%s'", header->size, header->name); File* out_file = storage_file_alloc(archive->storage); uint8_t* readbuf = malloc(FILE_BLOCK_SIZE); diff --git a/scripts/update.py b/scripts/update.py index ee485f44d..52391965b 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -229,7 +229,7 @@ class Main(App): @staticmethod def int2ffhex(value: int, n_hex_syms=8): if value: - n_hex_syms = math.ceil(math.ceil(math.log2(value)) / 8) * 2 + n_hex_syms = max(math.ceil(math.ceil(math.log2(value)) / 8) * 2, n_hex_syms) fmtstr = f"%0{n_hex_syms}X" hexstr = fmtstr % value return " ".join(list(Main.batch(hexstr, 2))[::-1]) From 3e3a167764132a426752cb5bed52afeaf3e93f3e Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Mon, 26 Sep 2022 16:49:18 +0300 Subject: [PATCH 25/29] [FL-2852] Update Universal Remote documentation (#1786) * Update Universal Remote documentation * Change formatting --- documentation/UniversalRemotes.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/UniversalRemotes.md b/documentation/UniversalRemotes.md index ac98d451f..6ecf3b11b 100644 --- a/documentation/UniversalRemotes.md +++ b/documentation/UniversalRemotes.md @@ -32,5 +32,7 @@ Finally, record the `Off` signal: The resulting remote file should now contain 6 signals. Any of them can be omitted, but that will mean that this functionality will not be used. Test the file against the actual device. Every signal must do what it's supposed to. -If everything checks out, add these signals to the [A/C universal remote file](/assets/resources/infrared/assets/ac.ir) -and open a pull request. + +If everything checks out, add these signals to the [A/C universal remote file](/assets/resources/infrared/assets/ac.ir). +Keep the signals of the same type grouped together (e.g. an `Off` signal must follow a previous `Off` one). +When done, open a pull request containing the changed file. From 9f501034c3240c3d9506cf07270aa4b0818e5e02 Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Mon, 26 Sep 2022 11:34:59 -0400 Subject: [PATCH 26/29] Power: Also ask charger if charge done (#1378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * power: Also ask charger if charge done * F7: bump API Symbols version * Lib: remove double include in bq25896.c Co-authored-by: あく --- applications/services/power/power_service/power.c | 2 +- firmware/targets/f7/api_symbols.csv | 3 ++- firmware/targets/f7/furi_hal/furi_hal_power.c | 7 +++++++ firmware/targets/furi_hal_include/furi_hal_power.h | 6 ++++++ lib/drivers/bq25896.c | 14 +++++++++++--- lib/drivers/bq25896.h | 8 ++++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 757d7718a..89886b0f8 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -96,7 +96,7 @@ void power_free(Power* power) { static void power_check_charging_state(Power* power) { if(furi_hal_power_is_charging()) { - if(power->info.charge == 100) { + if((power->info.charge == 100) || (furi_hal_power_is_charging_done())) { if(power->state != PowerStateCharged) { notification_internal_message(power->notification, &sequence_charged); power->state = PowerStateCharged; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index c8e6a6cf4..c18780acb 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.11,, +Version,+,1.12,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1141,6 +1141,7 @@ Function,+,furi_hal_power_insomnia_enter,void, Function,+,furi_hal_power_insomnia_exit,void, Function,-,furi_hal_power_insomnia_level,uint16_t, Function,+,furi_hal_power_is_charging,_Bool, +Function,+,furi_hal_power_is_charging_done,_Bool, Function,+,furi_hal_power_is_otg_enabled,_Bool, Function,+,furi_hal_power_off,void, Function,+,furi_hal_power_reset,void, diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 246383921..524fae0b1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -266,6 +266,13 @@ bool furi_hal_power_is_charging() { return ret; } +bool furi_hal_power_is_charging_done() { + furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); + bool ret = bq25896_is_charging_done(&furi_hal_i2c_handle_power); + furi_hal_i2c_release(&furi_hal_i2c_handle_power); + return ret; +} + void furi_hal_power_shutdown() { furi_hal_power_insomnia_enter(); diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 3ab30c424..f8eaa5c3a 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -85,6 +85,12 @@ uint8_t furi_hal_power_get_bat_health_pct(); */ bool furi_hal_power_is_charging(); +/** Get charge complete status + * + * @return true if done charging and connected to charger + */ +bool furi_hal_power_is_charging_done(); + /** Switch MCU to SHUTDOWN */ void furi_hal_power_shutdown(); diff --git a/lib/drivers/bq25896.c b/lib/drivers/bq25896.c index 73135d93a..1fb9d53e7 100644 --- a/lib/drivers/bq25896.c +++ b/lib/drivers/bq25896.c @@ -1,5 +1,4 @@ #include "bq25896.h" -#include "bq25896_reg.h" #include @@ -81,7 +80,7 @@ void bq25896_poweroff(FuriHalI2cBusHandle* handle) { handle, BQ25896_ADDRESS, 0x09, *(uint8_t*)&bq25896_regs.r09, BQ25896_I2C_TIMEOUT); } -bool bq25896_is_charging(FuriHalI2cBusHandle* handle) { +ChrgStat bq25896_get_charge_status(FuriHalI2cBusHandle* handle) { furi_hal_i2c_read_mem( handle, BQ25896_ADDRESS, @@ -91,7 +90,16 @@ bool bq25896_is_charging(FuriHalI2cBusHandle* handle) { BQ25896_I2C_TIMEOUT); furi_hal_i2c_read_reg_8( handle, BQ25896_ADDRESS, 0x0B, (uint8_t*)&bq25896_regs.r0B, BQ25896_I2C_TIMEOUT); - return bq25896_regs.r0B.CHRG_STAT != ChrgStatNo; + return bq25896_regs.r0B.CHRG_STAT; +} + +bool bq25896_is_charging(FuriHalI2cBusHandle* handle) { + // Include precharge, fast charging, and charging termination done as "charging" + return bq25896_get_charge_status(handle) != ChrgStatNo; +} + +bool bq25896_is_charging_done(FuriHalI2cBusHandle* handle) { + return bq25896_get_charge_status(handle) == ChrgStatDone; } void bq25896_enable_charging(FuriHalI2cBusHandle* handle) { diff --git a/lib/drivers/bq25896.h b/lib/drivers/bq25896.h index 39d343c33..c8da0a064 100644 --- a/lib/drivers/bq25896.h +++ b/lib/drivers/bq25896.h @@ -1,5 +1,7 @@ #pragma once +#include "bq25896_reg.h" + #include #include #include @@ -10,9 +12,15 @@ void bq25896_init(FuriHalI2cBusHandle* handle); /** Send device into shipping mode */ void bq25896_poweroff(FuriHalI2cBusHandle* handle); +/** Get charging status */ +ChrgStat bq25896_get_charge_status(FuriHalI2cBusHandle* handle); + /** Is currently charging */ bool bq25896_is_charging(FuriHalI2cBusHandle* handle); +/** Is charging completed while connected to charger */ +bool bq25896_is_charging_done(FuriHalI2cBusHandle* handle); + /** Enable charging */ void bq25896_enable_charging(FuriHalI2cBusHandle* handle); From f201062819d75035e4e5529e6cb33015e652f59e Mon Sep 17 00:00:00 2001 From: phreakocious Date: Mon, 26 Sep 2022 10:42:29 -0500 Subject: [PATCH 27/29] Add Hisense A/C IR signals.. (#1773) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add Hisense A/C IR signals.. note that using any will toggle the power and apply the settings * re-order the entries to be grouped by function Co-authored-by: あく --- assets/resources/infrared/assets/ac.ir | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index b1075b2f3..49586b555 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -7,32 +7,68 @@ frequency: 38000 duty_cycle: 0.33 data: 502 3436 510 475 509 476 508 477 507 477 507 479 505 480 504 480 504 490 504 481 502 482 501 483 563 420 511 474 510 475 509 476 508 485 561 423 508 476 508 477 507 478 506 479 505 480 504 481 503 517 508 476 508 478 506 479 505 479 505 481 503 483 521 1456 501 498 507 479 505 480 504 481 503 482 501 483 563 421 562 422 509 499 506 479 505 480 504 481 503 482 502 484 510 1451 506 479 505 1542 562 1396 509 471 502 476 508 469 504 3425 511 # +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8974 4505 598 1647 595 1651 591 539 592 542 600 537 594 547 595 549 593 1662 591 532 599 1649 593 1659 594 540 602 538 593 548 594 552 600 535 596 528 593 535 596 536 595 540 602 538 593 548 593 551 601 532 599 525 596 1651 591 539 592 543 599 1660 593 1669 594 1672 601 533 598 526 595 533 598 533 598 536 595 543 599 543 599 547 595 540 602 524 597 530 601 530 601 534 597 541 601 541 601 545 597 522 599 7938 591 532 599 528 593 537 594 541 601 537 594 546 596 549 593 1663 600 524 597 530 601 530 601 533 598 540 591 550 592 553 599 536 595 528 593 536 595 536 595 540 591 547 595 548 593 552 600 535 596 529 592 536 595 535 596 538 593 545 597 546 596 550 592 542 600 524 597 531 600 531 600 534 597 542 600 542 600 545 597 538 593 530 601 526 595 537 594 540 591 547 595 546 595 550 592 543 599 526 595 532 599 531 601 535 596 542 600 542 600 546 596 538 593 531 600 1648 594 536 595 539 592 1669 594 1669 594 1671 602 1637 595 7947 592 532 599 529 592 539 592 543 599 540 591 551 601 544 598 537 594 531 600 1647 595 535 596 539 592 545 597 546 596 550 592 543 599 526 595 533 598 534 597 538 593 545 597 546 596 550 602 534 597 527 594 533 598 533 598 536 595 544 598 543 599 547 595 540 591 533 598 529 592 539 592 1663 600 538 593 547 595 551 591 543 599 524 597 530 591 539 592 542 600 537 594 547 595 550 592 542 600 525 596 1651 592 538 593 1662 591 546 596 545 597 548 594 523 629 +# name: Dh type: raw frequency: 38000 duty_cycle: 0.33 data: 507 3430 506 479 505 480 504 481 503 481 503 483 501 485 509 1453 504 1465 503 482 502 483 511 473 500 485 509 476 508 477 507 478 506 487 507 477 507 478 506 479 505 480 504 482 502 483 501 484 500 523 503 482 502 484 500 485 509 476 508 476 508 478 506 1456 501 501 504 482 502 483 501 484 500 485 509 476 508 477 507 1455 502 509 506 479 505 1457 500 485 509 476 508 1454 503 482 502 483 501 568 499 1459 509 1450 507 471 502 474 510 3421 505 # +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8990 4494 599 1648 595 1654 599 533 598 537 594 544 598 544 598 548 594 1662 601 523 598 1651 592 1660 593 542 600 539 593 550 592 553 599 536 596 527 594 531 601 1648 595 538 593 542 600 540 592 551 601 532 600 1643 600 1650 593 538 593 542 600 1660 593 1671 592 1673 601 534 598 527 594 534 597 533 599 536 595 543 599 542 600 545 597 537 595 530 591 536 596 535 596 538 593 544 598 543 599 546 596 522 599 7935 595 530 591 536 596 536 596 539 592 545 597 544 598 547 595 1660 593 530 591 536 596 535 596 536 595 542 600 541 591 552 600 534 597 525 596 531 601 529 592 541 601 537 595 546 596 548 594 540 591 532 600 527 594 536 595 538 594 544 598 543 599 546 596 538 594 531 600 527 594 536 595 539 593 545 597 543 599 546 596 538 593 530 591 535 596 532 599 532 600 536 595 543 599 544 598 535 596 525 596 530 591 538 593 538 593 542 600 540 591 551 601 532 600 1640 593 1651 592 1655 598 535 596 1657 596 1663 601 1661 592 1641 592 7941 599 526 595 533 599 532 600 535 597 541 601 541 601 544 598 537 595 1651 592 535 597 535 597 538 594 545 597 545 597 548 594 540 592 532 600 528 593 539 593 542 600 539 592 549 593 551 601 533 598 524 597 528 593 536 595 538 593 544 598 543 599 546 596 539 593 531 601 528 593 538 593 1661 592 546 596 545 597 547 595 539 592 532 600 527 594 536 596 538 593 543 599 542 600 544 598 535 596 1646 597 531 601 529 592 1663 601 537 595 547 595 550 592 524 597 +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.33 data: 504 3433 503 482 502 484 510 474 510 475 509 476 508 478 506 1456 564 1405 510 475 509 476 508 502 482 477 507 478 506 479 505 480 504 489 505 480 504 481 503 482 502 483 511 473 511 474 510 475 509 509 506 479 505 480 504 481 503 482 512 473 511 474 510 476 508 1469 509 475 509 476 508 477 507 478 506 479 505 480 504 481 503 505 510 475 509 502 482 503 481 504 480 505 478 507 477 1459 509 560 507 1451 506 473 511 493 480 1450 507 3422 503 # +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8982 4489 604 1643 600 1649 594 537 594 540 602 537 594 547 595 550 592 1664 599 525 596 1652 601 1651 592 542 600 538 593 549 593 552 600 534 597 1646 597 530 601 1651 602 534 597 541 601 541 601 544 598 537 594 529 592 1655 598 533 598 536 595 542 600 542 600 546 596 539 592 532 599 527 594 537 594 540 591 546 596 545 597 548 594 540 602 523 598 529 592 539 592 542 600 539 592 549 593 550 592 524 597 7929 600 525 596 532 599 533 598 537 594 543 599 542 600 544 598 1654 599 524 597 530 591 538 593 540 591 544 598 543 599 544 598 535 596 526 595 531 600 529 592 544 598 541 601 542 600 546 596 540 602 522 599 529 602 530 601 534 597 541 601 541 601 545 597 539 592 532 599 528 593 539 592 541 601 537 594 547 595 551 601 535 596 529 592 536 595 537 594 541 601 538 593 549 593 553 599 536 595 529 592 536 595 534 597 537 594 544 598 543 599 546 596 539 592 1653 600 1650 593 1660 593 543 599 541 601 541 601 546 596 1643 600 7943 596 529 602 527 594 538 593 541 601 538 593 549 593 553 599 536 595 1649 594 535 596 535 596 539 592 546 596 546 596 549 593 542 600 525 596 531 600 530 601 533 598 540 602 539 592 552 600 535 596 527 594 533 598 533 598 536 595 543 599 543 599 545 597 537 594 530 601 526 595 536 595 1660 593 546 596 547 595 550 602 533 598 526 595 533 598 534 597 538 593 546 596 547 595 551 601 534 597 1647 596 532 599 532 599 1656 597 541 601 542 600 545 597 522 599 +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.33 data: 525 3615 530 506 561 474 562 474 562 473 563 473 531 505 562 1502 528 1542 562 474 562 474 530 505 531 504 532 504 532 504 616 419 533 510 589 447 526 509 527 509 527 509 527 508 528 508 528 507 529 542 525 510 526 509 527 509 527 509 527 508 528 508 528 1535 527 524 533 503 533 503 533 502 534 502 534 502 534 501 535 501 525 534 533 502 534 502 534 501 535 502 534 1529 533 503 533 503 533 587 533 497 528 501 524 1536 526 501 524 3609 526 # +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8967 4495 597 1645 597 1648 594 535 596 537 594 542 600 541 601 543 599 1655 598 525 596 1651 592 1658 595 539 592 545 597 544 598 546 596 538 593 1648 595 532 599 1648 594 539 592 545 597 543 599 545 597 536 595 528 593 1651 592 538 593 541 601 1654 599 1661 592 1671 592 541 601 523 598 529 592 538 593 541 601 536 595 544 598 547 595 539 592 531 600 526 595 535 596 537 594 543 599 541 601 543 598 518 593 7937 602 522 599 528 593 537 594 539 592 545 597 544 598 546 596 1656 597 525 596 530 601 528 593 539 592 544 598 543 599 544 598 535 596 526 595 531 600 530 601 532 599 538 593 547 595 549 593 540 602 521 600 526 595 535 596 537 594 543 599 541 601 543 599 536 595 527 594 532 600 530 601 532 599 538 593 546 596 548 594 539 592 531 600 525 596 534 597 535 596 540 591 549 593 551 601 532 599 524 597 529 592 537 594 538 593 543 599 540 591 551 601 532 599 1641 591 1654 599 1650 593 540 591 1664 599 1660 593 1671 592 1643 600 7922 596 528 593 533 598 532 599 535 596 540 591 549 593 552 600 533 598 1644 599 529 592 538 593 539 592 544 598 541 590 550 592 539 592 528 593 531 590 537 594 536 595 539 592 546 596 546 596 536 595 526 595 529 592 535 596 535 596 538 593 546 596 546 596 535 596 524 597 527 594 533 598 1649 593 541 601 538 593 549 593 538 593 528 593 532 599 528 593 539 592 542 600 538 593 548 594 538 593 1643 599 525 596 532 599 1649 593 541 601 538 593 548 594 520 591 +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.33 data: 531 3406 530 455 529 456 528 457 537 447 537 448 535 450 534 1429 528 1442 536 448 536 449 534 451 532 452 532 453 530 454 530 455 529 464 530 454 529 456 528 457 537 448 536 449 535 450 533 451 533 490 535 449 534 450 534 451 533 452 532 453 531 455 529 1433 534 1443 535 449 535 450 534 452 531 453 530 454 530 455 529 456 538 472 532 452 532 454 530 1433 535 1427 530 1432 536 1427 530 1431 537 1511 530 448 536 1422 535 1423 534 1422 535 3395 530 # +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8970 4496 597 1648 595 1652 601 530 602 533 598 541 601 541 601 543 599 1652 601 523 598 1649 594 1656 597 538 593 545 597 545 597 549 593 541 601 523 598 529 592 1658 595 540 592 546 596 545 597 548 594 541 601 523 598 529 592 539 593 542 600 538 593 1668 595 1670 593 1662 591 533 599 529 592 539 593 542 600 538 593 547 595 549 593 542 600 524 597 530 602 529 592 543 599 539 593 549 593 551 601 516 595 7937 593 532 599 527 594 536 596 539 592 546 596 545 597 548 594 1661 592 532 600 528 593 538 593 541 601 537 594 547 595 550 602 533 599 526 595 533 599 533 599 536 595 543 599 541 601 544 598 536 595 529 592 535 596 535 596 538 594 544 598 544 598 547 595 541 601 523 598 528 593 537 594 540 602 536 595 546 596 550 602 533 598 526 595 532 600 531 600 534 597 541 601 541 601 545 597 539 593 532 600 528 593 538 593 541 601 537 594 547 595 550 602 532 599 523 598 527 594 1653 600 533 598 538 593 1664 599 1662 591 523 598 7926 593 529 592 534 597 532 599 534 597 538 593 546 596 547 595 537 594 1648 595 532 600 532 599 536 595 543 599 543 599 546 596 540 602 522 599 529 592 538 594 541 601 536 595 546 596 549 593 542 600 523 598 529 592 538 593 541 601 538 593 548 594 552 600 534 597 527 594 534 597 534 597 1657 596 543 599 543 599 548 594 542 600 524 597 530 601 530 602 533 598 538 593 547 595 551 601 533 599 1644 599 528 593 538 593 1661 592 545 597 545 597 548 594 524 597 +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.33 data: 506 3430 506 478 506 479 505 480 504 481 503 482 502 484 500 1463 505 1465 503 482 502 483 501 484 500 485 509 476 508 477 507 478 506 486 508 477 507 478 506 479 505 480 504 481 503 482 502 483 500 523 502 482 502 483 501 484 500 485 509 476 508 478 506 1455 502 498 507 478 506 479 505 481 503 482 501 483 500 484 500 485 509 500 505 481 502 482 502 1461 507 1455 502 1459 509 476 508 477 507 563 504 1453 504 1454 503 1454 503 1453 504 3426 499 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8972 4491 592 1651 592 1655 598 532 599 535 597 542 600 541 601 544 598 1656 597 526 595 1652 591 1658 595 539 593 545 597 545 597 546 596 537 594 529 592 535 596 1653 600 534 597 541 601 539 592 552 600 533 598 525 596 530 591 538 593 539 592 1665 598 1662 591 1673 601 533 598 526 595 533 598 532 600 534 597 540 591 548 594 550 592 542 600 523 598 528 593 536 595 537 594 543 599 542 600 543 599 517 594 7937 593 531 601 526 595 535 597 537 594 542 600 541 601 543 599 1654 599 523 598 528 593 536 596 538 594 542 600 541 590 552 600 532 599 524 597 528 593 536 595 537 595 541 601 539 593 551 591 542 600 522 599 527 594 536 595 537 594 543 599 540 591 552 600 532 600 523 598 527 594 535 596 537 595 542 600 540 591 552 600 532 600 523 598 528 593 536 595 538 593 543 599 541 601 543 599 535 596 527 594 532 600 531 601 534 597 540 592 549 593 552 600 534 597 525 596 529 592 1655 598 534 597 1656 597 1661 592 1671 592 1644 599 7934 596 529 592 535 597 535 597 538 593 544 598 543 599 545 597 538 593 1650 593 535 596 534 597 536 595 540 591 547 595 547 595 536 595 526 595 529 592 536 595 535 596 539 593 546 596 547 595 538 593 528 593 531 601 529 592 541 601 536 596 545 597 548 594 540 592 532 600 526 595 535 596 1656 597 541 601 540 592 553 599 534 597 526 595 532 599 531 600 533 598 539 593 548 594 552 600 535 596 1647 596 531 590 538 593 1656 597 538 594 545 597 545 597 518 593 From 5bb7cabea6cb02ce2ad281484da70db4e83d2df1 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Tue, 27 Sep 2022 01:59:28 +1000 Subject: [PATCH 28/29] Applications loader: do not use view dispatcher queue #1788 --- applications/main/fap_loader/fap_loader_app.c | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 9050ddf78..c0f60ceca 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -15,6 +15,9 @@ typedef struct { DialogsApp* dialogs; Gui* gui; string_t fap_path; + + ViewDispatcher* view_dispatcher; + Loading* loading; } FapLoader; static bool @@ -144,12 +147,12 @@ int32_t fap_loader_app(void* p) { loader->dialogs = furi_record_open(RECORD_DIALOGS); loader->gui = furi_record_open(RECORD_GUI); - ViewDispatcher* view_dispatcher = view_dispatcher_alloc(); - Loading* loading = loading_alloc(); + loader->view_dispatcher = view_dispatcher_alloc(); + loader->loading = loading_alloc(); - view_dispatcher_enable_queue(view_dispatcher); - view_dispatcher_attach_to_gui(view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_add_view(view_dispatcher, 0, loading_get_view(loading)); + view_dispatcher_attach_to_gui( + loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_add_view(loader->view_dispatcher, 0, loading_get_view(loader->loading)); if(p) { string_init_set(loader->fap_path, (const char*)p); @@ -158,14 +161,14 @@ int32_t fap_loader_app(void* p) { string_init_set(loader->fap_path, EXT_PATH("apps")); while(fap_loader_select_app(loader)) { - view_dispatcher_switch_to_view(view_dispatcher, 0); + view_dispatcher_switch_to_view(loader->view_dispatcher, 0); fap_loader_run_selected_app(loader); }; } - view_dispatcher_remove_view(view_dispatcher, 0); - loading_free(loading); - view_dispatcher_free(view_dispatcher); + view_dispatcher_remove_view(loader->view_dispatcher, 0); + loading_free(loader->loading); + view_dispatcher_free(loader->view_dispatcher); string_clear(loader->fap_path); furi_record_close(RECORD_GUI); From 60242cd7c4c87b87f58f1405dc82a3fb2d8b25aa Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Sep 2022 19:46:12 +0300 Subject: [PATCH 29/29] =?UTF-8?q?fix=20nfc=20device=20typo,=20doesn?= =?UTF-8?q?=E2=80=99t=20affect=20resulting=20keys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/nfc/nfc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index dd78e2daf..45d05a55b 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -925,7 +925,7 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { flipper_format_write_hex(file, string_get_cstr(temp_str), sec_tr->key_a, 6); } if(!key_save_success) break; - if(FURI_BIT(data->key_a_mask, i)) { + if(FURI_BIT(data->key_b_mask, i)) { string_printf(temp_str, "Key B sector %d", i); key_save_success = flipper_format_write_hex(file, string_get_cstr(temp_str), sec_tr->key_b, 6);