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);