diff --git a/application.fam b/application.fam index 7b7b441d76e..455bb822f99 100644 --- a/application.fam +++ b/application.fam @@ -7,7 +7,7 @@ App( requires=["gui","dialogs"], stack_size=2 * 1024, order=11, - fap_icon="subbrute_10px.png", + fap_icon="images/subbrute_10px.png", fap_category="Tools", fap_icon_assets="images", ) diff --git a/helpers/gui_top_buttons.c b/helpers/gui_top_buttons.c new file mode 100644 index 00000000000..0415c5ae7b6 --- /dev/null +++ b/helpers/gui_top_buttons.c @@ -0,0 +1,59 @@ +#include "gui_top_buttons.h" + +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_get_width(icon) + icon_h_offset; + const uint8_t icon_v_offset = icon_get_height(icon) + 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 + button_height; + + uint8_t line_x = x + button_width; + uint8_t line_y = y - button_height; + canvas_draw_box(canvas, x, line_y, button_width, button_height); + canvas_draw_line(canvas, line_x + 0, line_y, line_x + 0, y - 1); + canvas_draw_line(canvas, line_x + 1, line_y, line_x + 1, y - 2); + canvas_draw_line(canvas, line_x + 2, line_y, line_x + 2, y - 3); + + 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_get_width(icon) + icon_h_offset; + const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset + 1; + 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 + button_height; + + uint8_t line_x = x - button_width; + uint8_t line_y = y - button_height; + canvas_draw_box(canvas, line_x, line_y, button_width, button_height); + canvas_draw_line(canvas, line_x - 1, line_y, line_x - 1, y - 1); + canvas_draw_line(canvas, line_x - 2, line_y, line_x - 2, y - 2); + canvas_draw_line(canvas, line_x - 3, line_y, line_x - 3, y - 3); + + 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_get_width(icon), y - icon_v_offset, icon); + canvas_invert_color(canvas); +} \ No newline at end of file diff --git a/helpers/gui_top_buttons.h b/helpers/gui_top_buttons.h new file mode 100644 index 00000000000..b5ca507b7eb --- /dev/null +++ b/helpers/gui_top_buttons.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include +#include + +/** + * Thanks to the author of metronome + * @param canvas + * @param str + */ +void elements_button_top_left(Canvas* canvas, const char* str); + +/** + * Thanks to the author of metronome + * @param canvas + * @param str + */ +void elements_button_top_right(Canvas* canvas, const char* str); \ No newline at end of file diff --git a/helpers/subbrute_worker.c b/helpers/subbrute_worker.c index 4a9ad17da9c..6bf0cd0285c 100644 --- a/helpers/subbrute_worker.c +++ b/helpers/subbrute_worker.c @@ -96,8 +96,11 @@ bool subbrute_worker_init_default_attack( instance->te = protocol->te; instance->repeat = protocol->repeat + extra_repeats; instance->load_index = 0; - instance->file_key = NULL; - instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits); + instance->file_key = 0; + instance->two_bytes = false; + + instance->max_value = + subbrute_protocol_calc_max_value(instance->attack, instance->bits, instance->two_bytes); instance->initiated = true; instance->state = SubBruteWorkerStateReady; @@ -122,9 +125,10 @@ bool subbrute_worker_init_file_attack( SubBruteWorker* instance, uint64_t step, uint8_t load_index, - const char* file_key, + uint64_t file_key, SubBruteProtocol* protocol, - uint8_t extra_repeats) { + uint8_t extra_repeats, + bool two_bytes) { furi_assert(instance); if(instance->worker_running) { @@ -142,7 +146,10 @@ bool subbrute_worker_init_file_attack( instance->load_index = load_index; instance->repeat = protocol->repeat + extra_repeats; instance->file_key = file_key; - instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits); + instance->two_bytes = two_bytes; + + instance->max_value = + subbrute_protocol_calc_max_value(instance->attack, instance->bits, instance->two_bytes); instance->initiated = true; instance->state = SubBruteWorkerStateReady; @@ -150,14 +157,15 @@ bool subbrute_worker_init_file_attack( #ifdef FURI_DEBUG FURI_LOG_I( TAG, - "subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld", + "subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld, key: %llX", subbrute_protocol_name(instance->attack), instance->bits, subbrute_protocol_preset(instance->preset), subbrute_protocol_file(instance->file), instance->te, instance->repeat, - instance->max_value); + instance->max_value, + instance->file_key); #endif return true; @@ -244,7 +252,8 @@ bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t ste instance->te, instance->repeat, instance->load_index, - instance->file_key); + instance->file_key, + instance->two_bytes); } else { subbrute_protocol_default_payload( stream, step, instance->bits, instance->te, instance->repeat); @@ -373,7 +382,8 @@ int32_t subbrute_worker_thread(void* context) { instance->te, instance->repeat, instance->load_index, - instance->file_key); + instance->file_key, + instance->two_bytes); } else { subbrute_protocol_default_payload( stream, instance->step, instance->bits, instance->te, instance->repeat); diff --git a/helpers/subbrute_worker.h b/helpers/subbrute_worker.h index 31c5eab1625..4046f997c4e 100644 --- a/helpers/subbrute_worker.h +++ b/helpers/subbrute_worker.h @@ -28,9 +28,10 @@ bool subbrute_worker_init_file_attack( SubBruteWorker* instance, uint64_t step, uint8_t load_index, - const char* file_key, + uint64_t file_key, SubBruteProtocol* protocol, - uint8_t extra_repeats); + uint8_t extra_repeats, + bool two_bytes); bool subbrute_worker_start(SubBruteWorker* instance); void subbrute_worker_stop(SubBruteWorker* instance); bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step); diff --git a/helpers/subbrute_worker_private.h b/helpers/subbrute_worker_private.h index cebda8585b4..eb12be284e8 100644 --- a/helpers/subbrute_worker_private.h +++ b/helpers/subbrute_worker_private.h @@ -31,8 +31,9 @@ struct SubBruteWorker { uint8_t te; uint8_t repeat; uint8_t load_index; // Index of group to bruteforce in loaded file - const char* file_key; + uint64_t file_key; uint64_t max_value; // Max step + bool two_bytes; // Manual transmit uint32_t last_time_tx_data; diff --git a/subbrute_10px.png b/images/subbrute_10px.png similarity index 100% rename from subbrute_10px.png rename to images/subbrute_10px.png diff --git a/scenes/subbrute_scene_load_file.c b/scenes/subbrute_scene_load_file.c index 3ddcecf9016..8aae1bcadf4 100644 --- a/scenes/subbrute_scene_load_file.c +++ b/scenes/subbrute_scene_load_file.c @@ -3,13 +3,6 @@ #define TAG "SubBruteSceneLoadFile" -//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; @@ -24,8 +17,14 @@ void subbrute_scene_load_file_on_enter(void* context) { dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px); SubBruteFileResult load_result = SubBruteFileResultUnknown; + // TODO: DELETE IT +#ifdef SUBBRUTE_FAST_TRACK + bool res = true; + furi_string_printf(load_path, "%s", "/ext/subghz/princeton.sub"); +#else bool res = dialog_file_browser_show(instance->dialogs, load_path, app_folder, &browser_options); +#endif #ifdef FURI_DEBUG FURI_LOG_D( TAG, @@ -44,11 +43,12 @@ void subbrute_scene_load_file_on_enter(void* context) { if(load_result == SubBruteFileResultOk) { if(!subbrute_worker_init_file_attack( instance->worker, - instance->device->key_index, - instance->device->load_index, - instance->device->file_key, + instance->device->current_step, + instance->device->bit_index, + instance->device->key_from_file, instance->device->file_protocol_info, - extra_repeats)) { + extra_repeats, + instance->device->two_bytes)) { furi_crash("Invalid attack set!"); } // Ready to run! diff --git a/scenes/subbrute_scene_load_select.c b/scenes/subbrute_scene_load_select.c index 0ec9fbc9196..d018e8b4d6e 100644 --- a/scenes/subbrute_scene_load_select.c +++ b/scenes/subbrute_scene_load_select.c @@ -20,7 +20,8 @@ void subbrute_scene_load_select_on_enter(void* context) { 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); + subbrute_main_view_set_index( + view, 7, true, instance->device->two_bytes, instance->device->key_from_file); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } @@ -38,21 +39,37 @@ bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeIndexSelected) { - instance->device->load_index = subbrute_main_view_get_index(instance->view_main); + /*#ifdef FURI_DEBUG && !SUBBRUTE_FAST_TRACK + view_dispatcher_stop(instance->view_dispatcher); + consumed = true; +#else*/ + instance->device->current_step = 0; + instance->device->bit_index = subbrute_main_view_get_index(instance->view_main); + instance->device->two_bytes = subbrute_main_view_get_two_bytes(instance->view_main); uint8_t extra_repeats = subbrute_main_view_get_extra_repeats(instance->view_main); + instance->device->max_value = subbrute_protocol_calc_max_value( + instance->device->attack, + instance->device->bit_index, + instance->device->two_bytes); if(!subbrute_worker_init_file_attack( instance->worker, - instance->device->key_index, - instance->device->load_index, - instance->device->file_key, + instance->device->current_step, + instance->device->bit_index, + instance->device->key_from_file, instance->device->file_protocol_info, - extra_repeats)) { + extra_repeats, + instance->device->two_bytes)) { furi_crash("Invalid attack set!"); } scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + /*#endif*/ consumed = true; - } + } /* else if(event.event == SubBruteCustomEventTypeChangeStepUp) { + instance->device->two_bytes = true; + } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { + instance->device->two_bytes = false; + }*/ } else if(event.type == SceneManagerEventTypeBack) { if(!scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, SubBruteSceneStart)) { diff --git a/scenes/subbrute_scene_run_attack.c b/scenes/subbrute_scene_run_attack.c index 1138b4585dd..2f22c25d4c1 100644 --- a/scenes/subbrute_scene_run_attack.c +++ b/scenes/subbrute_scene_run_attack.c @@ -45,7 +45,7 @@ void subbrute_scene_run_attack_on_enter(void* context) { instance->worker, subbrute_scene_run_attack_device_state_changed, instance); if(!subbrute_worker_is_running(instance->worker)) { - subbrute_worker_set_step(instance->worker, instance->device->key_index); + subbrute_worker_set_step(instance->worker, instance->device->current_step); if(!subbrute_worker_start(instance->worker)) { view_dispatcher_send_custom_event( instance->view_dispatcher, SubBruteCustomEventTypeError); @@ -64,7 +64,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { uint64_t step = subbrute_worker_get_step(instance->worker); - instance->device->key_index = step; + instance->device->current_step = step; subbrute_attack_view_set_current_step(view, step); if(event.event == SubBruteCustomEventTypeTransmitFinished) { @@ -89,12 +89,12 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, SubBruteSceneSetupAttack); } else if(event.event == SubBruteCustomEventTypeUpdateView) { - //subbrute_attack_view_set_current_step(view, instance->device->key_index); + //subbrute_attack_view_set_current_step(view, instance->device->current_step); } consumed = true; } else if(event.type == SceneManagerEventTypeTick) { uint64_t step = subbrute_worker_get_step(instance->worker); - instance->device->key_index = step; + instance->device->current_step = step; subbrute_attack_view_set_current_step(view, step); consumed = true; diff --git a/scenes/subbrute_scene_setup_attack.c b/scenes/subbrute_scene_setup_attack.c index bdbe2eccd84..c2877c7cb6f 100644 --- a/scenes/subbrute_scene_setup_attack.c +++ b/scenes/subbrute_scene_setup_attack.c @@ -37,14 +37,14 @@ void subbrute_scene_setup_attack_on_enter(void* context) { instance->worker, subbrute_scene_setup_attack_device_state_changed, context); if(subbrute_worker_is_running(instance->worker)) { subbrute_worker_stop(instance->worker); - instance->device->key_index = subbrute_worker_get_step(instance->worker); + instance->device->current_step = subbrute_worker_get_step(instance->worker); } subbrute_attack_view_init_values( view, instance->device->attack, instance->device->max_value, - instance->device->key_index, + instance->device->current_step, false, instance->device->extra_repeats); @@ -77,7 +77,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event view, instance->device->attack, instance->device->max_value, - instance->device->key_index, + instance->device->current_step, false, instance->device->extra_repeats); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName); @@ -86,7 +86,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event view, instance->device->attack, instance->device->max_value, - instance->device->key_index, + instance->device->current_step, false, instance->device->extra_repeats); scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); @@ -99,7 +99,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event // Blink notification_message(instance->notifications, &sequence_blink_green_100); subbrute_worker_transmit_current_key( - instance->worker, instance->device->key_index); + instance->worker, instance->device->current_step); // Stop notification_message(instance->notifications, &sequence_blink_stop); } @@ -128,9 +128,9 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event consumed = true; } else if(event.type == SceneManagerEventTypeTick) { if(subbrute_worker_is_running(instance->worker)) { - instance->device->key_index = subbrute_worker_get_step(instance->worker); + instance->device->current_step = subbrute_worker_get_step(instance->worker); } - subbrute_attack_view_set_current_step(view, instance->device->key_index); + subbrute_attack_view_set_current_step(view, instance->device->current_step); consumed = true; } diff --git a/scenes/subbrute_scene_start.c b/scenes/subbrute_scene_start.c index 9ac29d37fa2..866ae34a0a4 100644 --- a/scenes/subbrute_scene_start.c +++ b/scenes/subbrute_scene_start.c @@ -23,9 +23,14 @@ 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, false, NULL); + subbrute_main_view_set_index(view, instance->device->attack, false, instance->device->two_bytes, 0); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); + + // TODO: DELETE IT +#ifdef SUBBRUTE_FAST_TRACK + scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); +#endif } void subbrute_scene_start_on_exit(void* context) { @@ -57,7 +62,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { (!subbrute_worker_init_default_attack( instance->worker, attack, - instance->device->key_index, + instance->device->current_step, instance->device->protocol_info, instance->device->extra_repeats))) { furi_crash("Invalid attack set!"); diff --git a/subbrute_device.c b/subbrute_device.c index 8cc98b9d953..ea5483852a6 100644 --- a/subbrute_device.c +++ b/subbrute_device.c @@ -12,7 +12,7 @@ SubBruteDevice* subbrute_device_alloc() { SubBruteDevice* instance = malloc(sizeof(SubBruteDevice)); - instance->key_index = 0; + instance->current_step = 0; instance->protocol_info = NULL; instance->file_protocol_info = NULL; @@ -23,7 +23,7 @@ SubBruteDevice* subbrute_device_alloc() { instance->environment, (void*)&subghz_protocol_registry); #ifdef FURI_DEBUG - subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); + subbrute_device_attack_set_default_values(instance, SubBruteAttackLoadFile); #else subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); #endif @@ -51,32 +51,32 @@ void subbrute_device_free(SubBruteDevice* instance) { uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) { if(step > 0) { - if((instance->key_index + step) - instance->max_value == 1) { - instance->key_index = 0x00; + if((instance->current_step + step) - instance->max_value == 1) { + instance->current_step = 0x00; } else { - uint64_t value = instance->key_index + step; + uint64_t value = instance->current_step + step; if(value == instance->max_value) { - instance->key_index = value; + instance->current_step = value; } else { - instance->key_index = value % instance->max_value; + instance->current_step = value % instance->max_value; } } } else { - if(instance->key_index + step == 0) { - instance->key_index = 0x00; - } else if(instance->key_index == 0) { - instance->key_index = instance->max_value; + if(instance->current_step + step == 0) { + instance->current_step = 0x00; + } else if(instance->current_step == 0) { + instance->current_step = instance->max_value; } else { - uint64_t value = ((instance->key_index + step) + instance->max_value); + uint64_t value = ((instance->current_step + step) + instance->max_value); if(value == instance->max_value) { - instance->key_index = value; + instance->current_step = value; } else { - instance->key_index = value % instance->max_value; + instance->current_step = value % instance->max_value; } } } - return instance->key_index; + return instance->current_step; } bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) { @@ -101,19 +101,20 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na instance->file_protocol_info->frequency, instance->file_protocol_info->preset, instance->file_protocol_info->file, - instance->key_index, + instance->current_step, instance->file_protocol_info->bits, instance->file_protocol_info->te, instance->file_protocol_info->repeat, - instance->load_index, - instance->file_key); + instance->bit_index, + instance->key_from_file, + instance->two_bytes); } else { subbrute_protocol_default_generate_file( stream, instance->protocol_info->frequency, instance->protocol_info->preset, instance->protocol_info->file, - instance->key_index, + instance->current_step, instance->protocol_info->bits, instance->protocol_info->te, instance->protocol_info->repeat); @@ -174,8 +175,8 @@ SubBruteFileResult subbrute_device_attack_set( protocol_check_result = SubBruteFileResultOk; // Calc max value - instance->max_value = - subbrute_protocol_calc_max_value(instance->attack, instance->protocol_info->bits); + instance->max_value = subbrute_protocol_calc_max_value( + instance->attack, instance->protocol_info->bits, instance->two_bytes); } #ifdef FURI_DEBUG bits = instance->protocol_info->bits; @@ -189,8 +190,8 @@ SubBruteFileResult subbrute_device_attack_set( protocol_check_result = SubBruteFileResultOk; // Calc max value - instance->max_value = - subbrute_protocol_calc_max_value(instance->attack, instance->file_protocol_info->bits); + instance->max_value = subbrute_protocol_calc_max_value( + instance->attack, instance->file_protocol_info->bits, instance->two_bytes); #ifdef FURI_DEBUG bits = instance->file_protocol_info->bits; te = instance->file_protocol_info->te; @@ -257,25 +258,24 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil } // Frequency - if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - instance->file_protocol_info->frequency = temp_data32; - if(!furi_hal_subghz_is_tx_allowed(instance->file_protocol_info->frequency)) { - result = SubBruteFileResultFrequencyNotAllowed; - break; - } - } else { + if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { FURI_LOG_E(TAG, "Missing or incorrect Frequency"); result = SubBruteFileResultMissingOrIncorrectFrequency; break; } + instance->file_protocol_info->frequency = temp_data32; + if(!furi_hal_subghz_is_tx_allowed(instance->file_protocol_info->frequency)) { + result = SubBruteFileResultFrequencyNotAllowed; + break; + } // Preset if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { FURI_LOG_E(TAG, "Preset FAIL"); result = SubBruteFileResultPresetInvalid; - } else { - instance->file_protocol_info->preset = subbrute_protocol_convert_preset(temp_str); + break; } + instance->file_protocol_info->preset = subbrute_protocol_convert_preset(temp_str); const char* protocol_file = NULL; // Protocol @@ -283,13 +283,12 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil FURI_LOG_E(TAG, "Missing Protocol"); result = SubBruteFileResultMissingProtocol; break; - } else { - instance->file_protocol_info->file = subbrute_protocol_file_protocol_name(temp_str); - protocol_file = subbrute_protocol_file(instance->file_protocol_info->file); + } + instance->file_protocol_info->file = subbrute_protocol_file_protocol_name(temp_str); + protocol_file = subbrute_protocol_file(instance->file_protocol_info->file); #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Protocol: %s", protocol_file); + FURI_LOG_D(TAG, "Protocol: %s", protocol_file); #endif - } instance->decoder_result = subghz_receiver_search_decoder_base_by_name( instance->receiver, furi_string_get_cstr(temp_str)); @@ -307,9 +306,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil break; } #ifdef FURI_DEBUG - else { - FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name); - } + FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name); #endif // Bit @@ -317,28 +314,120 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil FURI_LOG_E(TAG, "Missing or incorrect Bit"); result = SubBruteFileResultMissingOrIncorrectBit; break; - } else { - instance->file_protocol_info->bits = temp_data32; + } + instance->file_protocol_info->bits = temp_data32; #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Bit: %d", instance->file_protocol_info->bits); + FURI_LOG_D(TAG, "Bit: %d", instance->file_protocol_info->bits); #endif - } + // TODO: Delete this // Key - if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { - FURI_LOG_E(TAG, "Missing or incorrect 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->current_key_from_file, + // sizeof(instance->current_key_from_file), + // "%s", + // furi_string_get_cstr(temp_str)); + // #ifdef FURI_DEBUG + // FURI_LOG_D(TAG, "Key: %s", instance->current_key_from_file); + // #endif + // } + // + // flipper_format_rewind(fff_data_file); + + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_format_read_hex(fff_data_file, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Missing Key"); result = SubBruteFileResultMissingOrIncorrectKey; break; - } else { - snprintf( - instance->file_key, - sizeof(instance->file_key), - "%s", - furi_string_get_cstr(temp_str)); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Key: %s", instance->file_key); -#endif } + uint64_t data = 0; + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + data = (data << 8) | key_data[i]; + } +#if FURI_DEBUG + FURI_LOG_D(TAG, "Key: %.16llX", data); +#endif + instance->key_from_file = data; + + // uint16_t add_value = 0x0001; + // uint8_t bit_index = 7; + // bool two_bytes = true; + // uint8_t p[8]; + // for(int i = 0; i < 8; i++) { + // p[i] = (uint8_t)(instance->key_from_file >> 8 * (7 - i)) & 0xFF; + // } + // uint16_t num = two_bytes ? (p[bit_index - 1] << 8) | p[bit_index] : p[bit_index]; + // FURI_LOG_D(TAG, "num: 0x%04X", num); + // num += add_value; + // FURI_LOG_D(TAG, "num added: 0x%04X", num); + // uint8_t low_byte = num & (0xff); + // uint8_t high_byte = (num >> 8) & 0xff; + + // data = 0; + // for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + // if(i == bit_index - 1 && two_bytes) { + // data = (data << 8) | high_byte; + // data = (data << 8) | low_byte; + // i++; + // } else if(i == bit_index) { + // data = (data << 8) | low_byte; + // } else { + // data = (data << 8) | p[i]; + // } + // } + // #if FURI_DEBUG + // furi_string_printf(temp_str, "Key: %lX", (uint32_t)(data & 0xFFFFFFFF)); + // FURI_LOG_D( + // TAG, "H: 0x%02X, L: 0x%02X, %s", high_byte, low_byte, furi_string_get_cstr(temp_str)); + // #endif + // uint8_t key_data[sizeof(uint64_t)] = {0}; + // if(!flipper_format_read_hex(fff_data_file, "Key", key_data, sizeof(uint64_t))) { + // FURI_LOG_E(TAG, "Missing Key"); + // result = SubBruteFileResultMissingOrIncorrectKey; + // break; + // } + // uint64_t data = 0; + // for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + // data = (data << 8) | key_data[i]; + // } + // instance->key_from_file = data; + + // uint16_t add_value = 0x0001; + // uint8_t bit_index = 7; + // bool two_bytes = true; + + // uint8_t p[8]; + // for(int i = 0; i < 8; i++) { + // p[i] = (uint8_t)(instance->key_from_file >> 8 * (7 - i)) & 0xFF; + // } + // uint16_t num = two_bytes ? (p[bit_index - 1] << 8) | p[bit_index] : p[bit_index]; + // FURI_LOG_D(TAG, "num: 0x%04X", num); + // num += add_value; + // FURI_LOG_D(TAG, "num added: 0x%04X", num); + // uint8_t low_byte = num & (0xff); + // uint8_t high_byte = (num >> 8) & 0xff; + + // data = 0; + // for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + // if(i == bit_index - 1 && two_bytes) { + // data = (data << 8) | high_byte; + // data = (data << 8) | low_byte; + // i++; + // } else if(i == bit_index) { + // data = (data << 8) | low_byte; + // } else { + // data = (data << 8) | p[i]; + // } + // } + + // furi_string_printf(temp_str, "Key: %lX", (uint32_t)(data & 0xFFFFFFFF)); + // FURI_LOG_D( + // TAG, "H: 0x%02X, L: 0x%02X, %s", high_byte, low_byte, furi_string_get_cstr(temp_str)); // TE if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { @@ -394,15 +483,15 @@ void subbrute_device_attack_set_default_values( FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values"); #endif instance->attack = default_attack; - instance->key_index = 0x00; - instance->load_index = 0x00; + instance->current_step = 0x00; + instance->bit_index = 0x00; instance->extra_repeats = 0; + instance->two_bytes = false; memset(instance->current_key, 0, sizeof(instance->current_key)); if(default_attack != SubBruteAttackLoadFile) { - memset(instance->file_key, 0, sizeof(instance->file_key)); - - instance->max_value = (uint64_t)0x00; + instance->max_value = subbrute_protocol_calc_max_value( + instance->attack, instance->bit_index, instance->two_bytes); } } diff --git a/subbrute_device.h b/subbrute_device.h index 311b8a72bc6..e8b96a755f9 100644 --- a/subbrute_device.h +++ b/subbrute_device.h @@ -36,9 +36,7 @@ typedef struct { SubBruteProtocol* file_protocol_info; // Current step - uint64_t key_index; - // Index of group to bruteforce in loaded file - uint8_t load_index; + uint64_t current_step; // SubGhz SubGhzReceiver* receiver; @@ -52,7 +50,11 @@ typedef struct { // Loaded info for attack type char current_key[SUBBRUTE_PAYLOAD_SIZE]; - char file_key[SUBBRUTE_MAX_LEN_NAME]; + uint64_t key_from_file; + uint64_t current_key_from_file; + bool two_bytes; + // Index of group to bruteforce in loaded file + uint8_t bit_index; } SubBruteDevice; SubBruteDevice* subbrute_device_alloc(); diff --git a/subbrute_i.h b/subbrute_i.h index 7bb91dde81a..24f2c57c0c3 100644 --- a/subbrute_i.h +++ b/subbrute_i.h @@ -16,7 +16,7 @@ #include #include -#include +#include "SubGHz_Bruteforcer_icons.h" #include @@ -29,6 +29,10 @@ #include "views/subbrute_attack_view.h" #include "views/subbrute_main_view.h" +#ifdef FURI_DEBUG +//#define SUBBRUTE_FAST_TRACK false +#endif + typedef enum { SubBruteViewNone, SubBruteViewMain, diff --git a/subbrute_protocols.c b/subbrute_protocols.c index d049c7e7099..b1351e0d65f 100644 --- a/subbrute_protocols.c +++ b/subbrute_protocols.c @@ -25,6 +25,17 @@ const SubBruteProtocol subbrute_protocol_came_12bit_307 = { .preset = FuriHalSubGhzPresetOok650Async, .file = CAMEFileProtocol}; +/** + * CAME 12bit 315MHz + */ +const SubBruteProtocol subbrute_protocol_came_12bit_315 = { + .frequency = 315000000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = CAMEFileProtocol}; + /** * CAME 12bit 433MHz */ @@ -243,6 +254,7 @@ const SubBruteProtocol subbrute_protocol_load_file = static const char* subbrute_protocol_names[] = { [SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz", [SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz", + [SubBruteAttackCAME12bit315] = "CAME 12bit 315MHz", [SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz", [SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz", [SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz", @@ -279,6 +291,7 @@ static const char* subbrute_protocol_presets[] = { const SubBruteProtocol* subbrute_protocol_registry[] = { [SubBruteAttackCAME12bit303] = &subbrute_protocol_came_12bit_303, [SubBruteAttackCAME12bit307] = &subbrute_protocol_came_12bit_307, + [SubBruteAttackCAME12bit315] = &subbrute_protocol_came_12bit_315, [SubBruteAttackCAME12bit433] = &subbrute_protocol_came_12bit_433, [SubBruteAttackCAME12bit868] = &subbrute_protocol_came_12bit_868, [SubBruteAttackNICE12bit433] = &subbrute_protocol_nice_12bit_433, @@ -366,27 +379,74 @@ SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) { return UnknownFileProtocol; } -void subbrute_protocol_default_payload( - Stream* stream, +void subbrute_protocol_create_candidate_for_existing_file( + FuriString* candidate, uint64_t step, - uint8_t bits, - uint8_t te, - uint8_t repeat) { - FuriString* candidate = furi_string_alloc_set_str(" "); + uint8_t bit_index, + uint64_t file_key, + bool two_bytes) { + uint8_t p[8]; + for(int i = 0; i < 8; i++) { + p[i] = (uint8_t)(file_key >> 8 * (7 - i)) & 0xFF; + } + uint8_t low_byte = step & (0xff); + uint8_t high_byte = (step >> 8) & 0xff; + + size_t size = sizeof(uint64_t); + for(uint8_t i = 0; i < size; i++) { + if(i == bit_index - 1 && two_bytes) { + furi_string_cat_printf(candidate, "%02X %02X", high_byte, low_byte); + i++; + } else if(i == bit_index) { + furi_string_cat_printf(candidate, "%02X", low_byte); + } else if(p[i] != 0) { + furi_string_cat_printf(candidate, "%02X", p[i]); + } else { + furi_string_cat_printf(candidate, "%s", "00"); + } + + if(i < size - 1) { + furi_string_push_back(candidate, ' '); + } + } + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "file candidate: %s, step: %lld", furi_string_get_cstr(candidate), step); +#endif +} - FuriString* buffer = furi_string_alloc_printf("%16llX", step); - int j = 0; - for(uint8_t i = 0; i < 16; i++) { - if(furi_string_get_char(buffer, i) != ' ') { - furi_string_set_char(candidate, i + j, furi_string_get_char(buffer, i)); +void subbrute_protocol_create_candidate_for_default(FuriString* candidate, uint64_t step) { + uint8_t p[8]; + for(int i = 0; i < 8; i++) { + p[i] = (uint8_t)(step >> 8 * (7 - i)) & 0xFF; + } + + size_t size = sizeof(uint64_t); + for(uint8_t i = 0; i < size; i++) { + if(p[i] != 0) { + furi_string_cat_printf(candidate, "%02X", p[i]); } else { - furi_string_set_char(candidate, i + j, '0'); + furi_string_cat_printf(candidate, "%s", "00"); } - if(i % 2 != 0) { - j++; + + if(i < size - 1) { + furi_string_push_back(candidate, ' '); } } - furi_string_free(buffer); + +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step); +#endif +} + +void subbrute_protocol_default_payload( + Stream* stream, + uint64_t step, + uint8_t bits, + uint8_t te, + uint8_t repeat) { + FuriString* candidate = furi_string_alloc(); + subbrute_protocol_create_candidate_for_default(candidate, step); #ifdef FURI_DEBUG FURI_LOG_D( @@ -420,13 +480,12 @@ void subbrute_protocol_file_payload( uint8_t bits, uint8_t te, uint8_t repeat, - uint8_t load_index, - const char* file_key) { + uint8_t bit_index, + uint64_t file_key, + bool two_bytes) { FuriString* candidate = furi_string_alloc(); - char subbrute_payload_byte[4]; - furi_string_set_str(candidate, file_key); - snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step); - furi_string_replace_at(candidate, load_index * 3, 3, subbrute_payload_byte); + subbrute_protocol_create_candidate_for_existing_file( + candidate, step, bit_index, file_key, two_bytes); #ifdef FURI_DEBUG FURI_LOG_D( @@ -464,21 +523,8 @@ void subbrute_protocol_default_generate_file( uint8_t bits, uint8_t te, uint8_t repeat) { - FuriString* candidate = furi_string_alloc_set_str(" "); - - FuriString* buffer = furi_string_alloc_printf("%16llX", step); - int j = 0; - for(uint8_t i = 0; i < 16; i++) { - if(furi_string_get_char(buffer, i) != ' ') { - furi_string_set_char(candidate, i + j, furi_string_get_char(buffer, i)); - } else { - furi_string_set_char(candidate, i + j, '0'); - } - if(i % 2 != 0) { - j++; - } - } - furi_string_free(buffer); + FuriString* candidate = furi_string_alloc(); + subbrute_protocol_create_candidate_for_default(candidate, step); #ifdef FURI_DEBUG FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step); @@ -520,17 +566,15 @@ void subbrute_protocol_file_generate_file( uint8_t bits, uint8_t te, uint8_t repeat, - uint8_t load_index, - const char* file_key) { + uint8_t bit_index, + uint64_t file_key, + bool two_bytes) { FuriString* candidate = furi_string_alloc(); - char subbrute_payload_byte[4]; - furi_string_set_str(candidate, file_key); - snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step); - furi_string_replace_at(candidate, load_index * 3, 3, subbrute_payload_byte); + // char subbrute_payload_byte[8]; + //furi_string_set_str(candidate, file_key); + subbrute_protocol_create_candidate_for_existing_file( + candidate, step, bit_index, file_key, two_bytes); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step); -#endif stream_clean(stream); if(te) { stream_write_format( @@ -558,10 +602,11 @@ void subbrute_protocol_file_generate_file( furi_string_free(candidate); } -uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) { +uint64_t + subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes) { uint64_t max_value; if(attack_type == SubBruteAttackLoadFile) { - max_value = 0xFF; + max_value = two_bytes ? 0xFFFF : 0xFF; } else { FuriString* max_value_s; max_value_s = furi_string_alloc(); diff --git a/subbrute_protocols.h b/subbrute_protocols.h index 3d25310de66..8ecc951ca30 100644 --- a/subbrute_protocols.h +++ b/subbrute_protocols.h @@ -26,6 +26,7 @@ typedef enum { typedef enum { SubBruteAttackCAME12bit303, SubBruteAttackCAME12bit307, + SubBruteAttackCAME12bit315, SubBruteAttackCAME12bit433, SubBruteAttackCAME12bit868, SubBruteAttackNICE12bit433, @@ -78,8 +79,9 @@ void subbrute_protocol_file_payload( uint8_t bits, uint8_t te, uint8_t repeat, - uint8_t load_index, - const char* file_key); + uint8_t bit_index, + uint64_t file_key, + bool two_bytes); void subbrute_protocol_default_generate_file( Stream* stream, uint32_t frequency, @@ -98,6 +100,8 @@ void subbrute_protocol_file_generate_file( uint8_t bits, uint8_t te, uint8_t repeat, - uint8_t load_index, - const char* file_key); -uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits); \ No newline at end of file + uint8_t bit_index, + uint64_t file_key, + bool two_bytes); +uint64_t + subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes); \ No newline at end of file diff --git a/views/subbrute_attack_view.c b/views/subbrute_attack_view.c index 00a9e1b2ad8..d7770bb4420 100644 --- a/views/subbrute_attack_view.c +++ b/views/subbrute_attack_view.c @@ -1,6 +1,7 @@ #include "subbrute_attack_view.h" #include "../subbrute_i.h" #include "../subbrute_protocols.h" +#include "../helpers/gui_top_buttons.h" #include #include @@ -255,74 +256,6 @@ void subbrute_attack_view_exit(void* context) { false); } -/** - * Thanks to the author of metronome - * @param canvas - * @param str - */ -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_get_width(icon) + icon_h_offset; - const uint8_t icon_v_offset = icon_get_height(icon) + 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 + button_height; - - uint8_t line_x = x + button_width; - uint8_t line_y = y - button_height; - canvas_draw_box(canvas, x, line_y, button_width, button_height); - canvas_draw_line(canvas, line_x + 0, line_y, line_x + 0, y - 1); - canvas_draw_line(canvas, line_x + 1, line_y, line_x + 1, y - 2); - canvas_draw_line(canvas, line_x + 2, line_y, line_x + 2, y - 3); - - 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); -} - -/** - * Thanks to the author of metronome - * @param canvas - * @param str - */ -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_get_width(icon) + icon_h_offset; - const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset + 1; - 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 + button_height; - - uint8_t line_x = x - button_width; - uint8_t line_y = y - button_height; - canvas_draw_box(canvas, line_x, line_y, button_width, button_height); - canvas_draw_line(canvas, line_x - 1, line_y, line_x - 1, y - 1); - canvas_draw_line(canvas, line_x - 2, line_y, line_x - 2, y - 2); - canvas_draw_line(canvas, line_x - 3, line_y, line_x - 3, y - 3); - - 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_get_width(icon), 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; @@ -339,9 +272,27 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) { } // Current Step / Max 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); + const uint8_t y_frequency = 17; + if(model->max_value > 9999) { + canvas_set_font(canvas, FontBigNumbers); + snprintf(buffer, sizeof(buffer), "%05d/", (int)model->current_step); + canvas_draw_str_aligned(canvas, 5, y_frequency, AlignLeft, AlignTop, buffer); + + // Second part with another font, because BigNumber is out of screen bounds + canvas_set_font(canvas, FontPrimary); + snprintf(buffer, sizeof(buffer), "%05d", (int)model->max_value); + canvas_draw_str_aligned(canvas, 107, y_frequency + 13, AlignRight, AlignBottom, buffer); + } else if(model->max_value <= 0xFF) { + canvas_set_font(canvas, FontBigNumbers); + snprintf( + buffer, sizeof(buffer), "%03d/%03d", (int)model->current_step, (int)model->max_value); + canvas_draw_str_aligned(canvas, 64, y_frequency, AlignCenter, AlignTop, buffer); + } else { + 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, y_frequency, AlignCenter, AlignTop, buffer); + } canvas_set_font(canvas, FontSecondary); memset(buffer, 0, sizeof(buffer)); diff --git a/views/subbrute_main_view.c b/views/subbrute_main_view.c index 287a33f2b2e..d87d249fbc3 100644 --- a/views/subbrute_main_view.c +++ b/views/subbrute_main_view.c @@ -1,6 +1,7 @@ #include "subbrute_main_view.h" #include "../subbrute_i.h" #include "../subbrute_protocols.h" +#include "../helpers/gui_top_buttons.h" #include #include @@ -10,6 +11,15 @@ #define TAG "SubBruteMainView" #define ITEMS_ON_SCREEN 3 +#define ITEMS_INTERVAL 1 +#define ITEM_WIDTH 14 +#define ITEM_Y 27 +#define ITEM_HEIGHT 13 +#define TEXT_X 6 +#define TEXT_Y 37 +#define TEXT_INTERVAL 3 +#define TEXT_WIDTH 12 +#define ITEM_FRAME_RADIUS 2 struct SubBruteMainView { View* view; @@ -17,7 +27,8 @@ struct SubBruteMainView { void* context; uint8_t index; bool is_select_byte; - const char* key_field; + bool two_bytes; + uint64_t key_from_file; uint8_t extra_repeats; uint8_t window_position; }; @@ -27,7 +38,8 @@ typedef struct { uint8_t extra_repeats; uint8_t window_position; bool is_select_byte; - const char* key_field; + bool two_bytes; + uint64_t key_from_file; } SubBruteMainViewModel; void subbrute_main_view_set_callback( @@ -41,84 +53,105 @@ void subbrute_main_view_set_callback( instance->context = context; } -FuriString* center_displayed_key(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]; +void subbrute_main_view_center_displayed_key( + Canvas* canvas, + uint64_t key, + uint8_t index, + bool two_bytes) { + uint8_t text_x = TEXT_X; + uint8_t item_x = TEXT_X - ITEMS_INTERVAL; + canvas_set_font(canvas, FontSecondary); + + for(int i = 0; i < 8; i++) { + char current_value[3] = {0}; + uint8_t byte_value = (uint8_t)(key >> 8 * (7 - i)) & 0xFF; + snprintf(current_value, sizeof(current_value), "%02X", byte_value); + + // For two bytes we need to select prev location + if(!two_bytes && i == index) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox( + canvas, item_x - 1, ITEM_Y, ITEM_WIDTH + 1, ITEM_HEIGHT, ITEM_FRAME_RADIUS); + canvas_set_color(canvas, ColorWhite); + canvas_draw_str(canvas, text_x, TEXT_Y, current_value); + } else if(two_bytes && (i == index || i == index - 1)) { + if(i == index) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox( + canvas, + item_x - ITEMS_INTERVAL - ITEM_WIDTH - 1, + ITEM_Y, + ITEM_WIDTH * 2 + ITEMS_INTERVAL * 2 + 1, + ITEM_HEIGHT, + ITEM_FRAME_RADIUS); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_str(canvas, text_x, TEXT_Y, current_value); + + // Redraw prev element with white + memset(current_value, 0, sizeof(current_value)); + byte_value = (uint8_t)(key >> 8 * (7 - i + 1)) & 0xFF; + snprintf(current_value, sizeof(current_value), "%02X", byte_value); + canvas_draw_str( + canvas, text_x - (TEXT_WIDTH + TEXT_INTERVAL), TEXT_Y, current_value); + } else { + canvas_set_color(canvas, ColorWhite); + canvas_draw_str(canvas, text_x, TEXT_Y, current_value); + } } else { - display_menu[14] = ' '; - display_menu[15] = ' '; + canvas_set_color(canvas, ColorBlack); + canvas_draw_str(canvas, text_x, TEXT_Y, current_value); } + text_x = text_x + TEXT_WIDTH + TEXT_INTERVAL; + item_x = item_x + ITEM_WIDTH + ITEMS_INTERVAL; } - return furi_string_alloc_set(display_menu); + + // Return normal color + canvas_set_color(canvas, ColorBlack); } 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, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer 3.2"); - canvas_invert_color(canvas); - uint16_t screen_width = canvas_width(canvas); uint16_t screen_height = canvas_height(canvas); if(model->is_select_byte) { #ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "key_field: %s", model->key_field); + //FURI_LOG_D(TAG, "key_from_file: %s", model->key_from_file); #endif - char msg_index[18]; - snprintf(msg_index, sizeof(msg_index), "Field index : %d", model->index); - canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index); - - FuriString* menu_items; - - menu_items = center_displayed_key(model->key_field, model->index); + //char msg_index[18]; + //snprintf(msg_index, sizeof(msg_index), "Field index: %d", model->index); canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned( - canvas, 64, 40, AlignCenter, AlignTop, furi_string_get_cstr(menu_items)); + canvas, 64, 17, AlignCenter, AlignTop, "Please select values to calc:"); - elements_button_center(canvas, "Select"); - elements_button_left(canvas, "<"); - elements_button_right(canvas, ">"); + subbrute_main_view_center_displayed_key( + canvas, model->key_from_file, model->index, model->two_bytes); + //const char* line = furi_string_get_cstr(menu_items); + //canvas_set_font(canvas, FontSecondary); + //canvas_draw_str_aligned( + // canvas, 64, 37, AlignCenter, AlignTop, furi_string_get_cstr(menu_items)); - furi_string_reset(menu_items); - furi_string_free(menu_items); + elements_button_center(canvas, "Select"); + if(model->index > 0) { + elements_button_left(canvas, " "); + } + if(model->index < 7) { + elements_button_right(canvas, " "); + } + // Switch to another mode + if(model->two_bytes) { + elements_button_top_left(canvas, "One byte"); + } else { + elements_button_top_left(canvas, "Two bytes"); + } } else { + // 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, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer 3.3"); + canvas_invert_color(canvas); + // Menu canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); @@ -257,18 +290,34 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { } } } - } else { - if(event->key == InputKeyLeft && is_short) { - if(instance->index > 0) { + } else if(is_short) { + if(event->key == InputKeyLeft) { + if((instance->index > 0 && !instance->two_bytes) || + (instance->two_bytes && instance->index > 1)) { instance->index--; } updated = true; - } else if(event->key == InputKeyRight && is_short) { + consumed = true; + } else if(event->key == InputKeyRight) { if(instance->index < 7) { instance->index++; } updated = true; - } else if(event->key == InputKeyOk && is_short) { + consumed = true; + } else if(event->key == InputKeyUp) { + instance->two_bytes = !instance->two_bytes; + // Because index is changing + if(instance->two_bytes && instance->index < 7) { + instance->index++; + } + // instance->callback( + // instance->two_bytes ? SubBruteCustomEventTypeChangeStepUp : + // SubBruteCustomEventTypeChangeStepDown, + // instance->context); + + updated = true; + consumed = true; + } else if(event->key == InputKeyOk) { instance->callback(SubBruteCustomEventTypeIndexSelected, instance->context); consumed = true; updated = true; @@ -282,8 +331,9 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { { model->index = instance->index; model->window_position = instance->window_position; - model->key_field = instance->key_field; + model->key_from_file = instance->key_from_file; model->is_select_byte = instance->is_select_byte; + model->two_bytes = instance->two_bytes; model->extra_repeats = instance->extra_repeats; }, true); @@ -318,24 +368,25 @@ 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); + instance->index = 0; + instance->window_position = 0; + instance->key_from_file = 0; + instance->is_select_byte = false; + instance->two_bytes = false; + instance->extra_repeats = 0; with_view_model( instance->view, SubBruteMainViewModel * model, { - model->index = 0; - model->window_position = 0; - model->key_field = NULL; - model->is_select_byte = false; - model->extra_repeats = 0; + model->index = instance->index; + model->window_position = instance->window_position; + model->key_from_file = instance->key_from_file; + model->is_select_byte = instance->is_select_byte; + model->two_bytes = instance->two_bytes; + model->extra_repeats = instance->extra_repeats; }, true); - instance->index = 0; - instance->window_position = 0; - instance->key_field = NULL; - instance->is_select_byte = false; - instance->extra_repeats = 0; - return instance; } @@ -355,14 +406,16 @@ void subbrute_main_view_set_index( SubBruteMainView* instance, uint8_t idx, bool is_select_byte, - const char* key_field) { + bool two_bytes, + uint64_t key_from_file) { furi_assert(instance); furi_assert(idx < SubBruteAttackTotalCount); #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "Set index: %d, IS_SELECT_BYTE: %d", idx, is_select_byte); + FURI_LOG_I(TAG, "Set index: %d, is_select_byte: %d", idx, is_select_byte); #endif instance->is_select_byte = is_select_byte; - instance->key_field = key_field; + instance->two_bytes = two_bytes; + instance->key_from_file = key_from_file; instance->index = idx; instance->window_position = idx; @@ -386,8 +439,9 @@ void subbrute_main_view_set_index( { model->index = instance->index; model->window_position = instance->window_position; - model->key_field = instance->key_field; + model->key_from_file = instance->key_from_file; model->is_select_byte = instance->is_select_byte; + model->two_bytes = instance->two_bytes; model->extra_repeats = instance->extra_repeats; }, true); @@ -401,4 +455,9 @@ SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance) { uint8_t subbrute_main_view_get_extra_repeats(SubBruteMainView* instance) { furi_assert(instance); return instance->extra_repeats; +} + +bool subbrute_main_view_get_two_bytes(SubBruteMainView* instance) { + furi_assert(instance); + return instance->two_bytes; } \ No newline at end of file diff --git a/views/subbrute_main_view.h b/views/subbrute_main_view.h index 6aa11cec82a..003cd9817db 100644 --- a/views/subbrute_main_view.h +++ b/views/subbrute_main_view.h @@ -21,9 +21,11 @@ void subbrute_main_view_set_index( SubBruteMainView* instance, uint8_t idx, bool is_select_byte, - const char* key_field); + bool two_bytes, + uint64_t file_key); SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance); uint8_t subbrute_main_view_get_extra_repeats(SubBruteMainView* instance); +bool subbrute_main_view_get_two_bytes(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);