From ec9ce0cad7332d5bd2e93df33e2e653daad3df99 Mon Sep 17 00:00:00 2001 From: DerSkythe Date: Sun, 25 Sep 2022 17:05:52 +0400 Subject: [PATCH] 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