mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-27 15:00:46 +00:00
fix bug with return to main menu when choice file
This commit is contained in:
parent
6f91fa42f0
commit
54757428e6
10 changed files with 132 additions and 140 deletions
|
@ -1,11 +1,9 @@
|
|||
#include <flipper_format.h>
|
||||
#include <flipper_format_i.h>
|
||||
|
||||
#include <subghz/types.h>
|
||||
#include <lib/subghz/protocols/raw.h>
|
||||
|
||||
#include "subbrute_worker.h"
|
||||
|
||||
#include <subghz/environment.h>
|
||||
#include <subghz/transmitter.h>
|
||||
#include <flipper_format_i.h>
|
||||
|
||||
#define TAG "SubBruteWorker"
|
||||
|
||||
struct SubBruteWorker {
|
||||
|
@ -135,7 +133,7 @@ bool subbrute_worker_start(
|
|||
instance->preset = preset;
|
||||
|
||||
string_clear(instance->protocol_name);
|
||||
string_init_set_str(instance->protocol_name, protocol_name);
|
||||
string_init_printf(instance->protocol_name, "%s", protocol_name);
|
||||
|
||||
bool res = false;
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal_subghz.h>
|
||||
#include <subghz/environment.h>
|
||||
#include <subghz/transmitter.h>
|
||||
#include <subghz/receiver.h>
|
||||
|
||||
typedef struct SubBruteWorker SubBruteWorker;
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include <lib/subghz/protocols/registry.h>
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "../views/subbrute_main_view.h"
|
||||
#include <lib/subghz/protocols/registry.h>
|
||||
|
||||
#define TAG "SubBruteSceneLoadFile"
|
||||
|
||||
//void subbrute_scene_load_file_callback(SubBruteCustomEvent event, void* context) {
|
||||
//// furi_assert(context);
|
||||
|
@ -13,41 +14,56 @@
|
|||
void subbrute_scene_load_file_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
string_t file_path;
|
||||
string_init(file_path);
|
||||
|
||||
// Input events and views are managed by file_browser
|
||||
string_t app_folder;
|
||||
string_t load_path;
|
||||
string_init(load_path);
|
||||
string_init_set_str(app_folder, SUBBRUTE_PATH);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px);
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
bool res = dialog_file_browser_show(
|
||||
instance->dialogs,
|
||||
instance->device->load_path,
|
||||
instance->device->load_path,
|
||||
&browser_options);
|
||||
|
||||
SubBruteFileResult load_result = SubBruteFileResultUnknown;
|
||||
bool res =
|
||||
dialog_file_browser_show(instance->dialogs, load_path, app_folder, &browser_options);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"load_path: %s, app_folder: %s",
|
||||
string_get_cstr(load_path),
|
||||
string_get_cstr(app_folder));
|
||||
#endif
|
||||
if(res) {
|
||||
SubBruteFileResult load_result = subbrute_device_load_protocol_from_file(instance->device);
|
||||
load_result = subbrute_device_load_from_file(instance->device, load_path);
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile);
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
// Ready to run!
|
||||
instance->device->state = SubBruteDeviceStateReady;
|
||||
FURI_LOG_I(TAG, "Ready to run");
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Returned error: %d", load_result);
|
||||
|
||||
string_t dialog_msg;
|
||||
string_init(dialog_msg);
|
||||
string_cat_printf(
|
||||
dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||
dialog_message_show_storage_error(instance->dialogs, string_get_cstr(dialog_msg));
|
||||
string_clear(dialog_msg);
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(file_path);
|
||||
|
||||
if(!res) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneLoadFile);
|
||||
instance->scene_manager, SubBruteSceneStart);
|
||||
}
|
||||
|
||||
string_clear(app_folder);
|
||||
string_clear(load_path);
|
||||
}
|
||||
|
||||
void subbrute_scene_load_file_on_exit(void* context) {
|
||||
|
|
|
@ -82,4 +82,6 @@ void subbrute_scene_save_name_on_exit(void* context) {
|
|||
validator_is_file_free(validator_context);
|
||||
|
||||
text_input_reset(instance->text_input);
|
||||
|
||||
string_reset(instance->device->load_path);
|
||||
}
|
||||
|
|
|
@ -27,12 +27,7 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
|||
instance->device->key_index,
|
||||
false);
|
||||
|
||||
// Run worker anyway
|
||||
subbrute_attack_view_start_worker(
|
||||
view,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name));
|
||||
subbrute_attack_view_stop_worker(view);
|
||||
|
||||
instance->current_view = SubBruteViewAttack;
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance);
|
||||
|
@ -41,6 +36,9 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
|||
|
||||
void subbrute_scene_setup_attack_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit");
|
||||
#endif
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
@ -54,10 +52,27 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
|||
if(event.event == SubBruteCustomEventTypeTransmitStarted) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
||||
subbrute_attack_view_stop_worker(view);
|
||||
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
|
||||
} else if(event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
subbrute_attack_view_stop_worker(view);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "SubBruteCustomEventTypeBackPressed");
|
||||
#endif
|
||||
instance->device->key_index = 0x00;
|
||||
subbrute_attack_view_stop_worker(view);
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
|
||||
// +1
|
||||
|
@ -86,6 +101,13 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
|||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_green_100);
|
||||
|
||||
if(!subbrute_attack_view_is_worker_running(view)) {
|
||||
subbrute_attack_view_start_worker(
|
||||
view,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
string_get_cstr(instance->device->protocol_name));
|
||||
}
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index);
|
||||
subbrute_attack_view_transmit(view, instance->device->payload);
|
||||
|
|
|
@ -24,10 +24,8 @@ void subbrute_scene_start_on_enter(void* context) {
|
|||
|
||||
instance->current_view = SubBruteViewMain;
|
||||
subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance);
|
||||
subbrute_main_view_set_index(view, (uint8_t)instance->device->attack);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "view_dispatcher_switch_to_view");
|
||||
#endif
|
||||
subbrute_main_view_set_index(view, instance->device->attack);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
}
|
||||
|
||||
|
@ -49,7 +47,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||
if(event.event == SubBruteCustomEventTypeMenuSelected) {
|
||||
SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main);
|
||||
|
||||
subbrute_device_attack_set(instance->device, attack, NULL);
|
||||
subbrute_device_attack_set(instance->device, attack);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
|
||||
consumed = true;
|
||||
|
|
|
@ -51,7 +51,6 @@ SubBruteDevice* subbrute_device_alloc() {
|
|||
|
||||
instance->state = SubBruteDeviceStateIDLE;
|
||||
instance->key_index = 0;
|
||||
instance->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
string_init(instance->load_path);
|
||||
string_init(instance->preset_name);
|
||||
|
@ -61,7 +60,7 @@ SubBruteDevice* subbrute_device_alloc() {
|
|||
instance->receiver = NULL;
|
||||
instance->environment = NULL;
|
||||
|
||||
subbrute_device_attack_set_default_values(instance);
|
||||
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
@ -71,7 +70,6 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
|||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_free");
|
||||
#endif
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
|
||||
// I don't know how to free this
|
||||
instance->decoder_result = NULL;
|
||||
|
@ -103,47 +101,6 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
|||
free(instance);
|
||||
}
|
||||
|
||||
SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_load_protocol_from_file");
|
||||
#endif
|
||||
// Input events and views are managed by file_browser
|
||||
string_t app_directory;
|
||||
string_init_set_str(app_directory, SUBBRUTE_PATH);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px);
|
||||
|
||||
SubBruteFileResult load_result = SubBruteFileResultUnknown;
|
||||
bool res = dialog_file_browser_show(
|
||||
instance->dialogs, instance->load_path, app_directory, &browser_options);
|
||||
|
||||
string_clear(app_directory);
|
||||
if(res) {
|
||||
load_result = subbrute_device_attack_set(
|
||||
instance, SubBruteAttackLoadFile, string_get_cstr(instance->load_path));
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
// Ready to run!
|
||||
instance->state = SubBruteDeviceStateReady;
|
||||
FURI_LOG_I(TAG, "Ready to run");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Returned error: %sd", load_result);
|
||||
// res = false;
|
||||
//
|
||||
// char file_info_message[128];
|
||||
// snprintf(
|
||||
// file_info_message,
|
||||
// sizeof(file_info_message),
|
||||
// "Can not load file\n%s",
|
||||
// (char*)subbrute_device_error_get_desc(set_result));
|
||||
// dialog_message_show_storage_error(instance->dialogs, file_info_message);
|
||||
}
|
||||
|
||||
return load_result;
|
||||
}
|
||||
|
||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
|
||||
furi_assert(instance);
|
||||
|
||||
|
@ -249,7 +206,7 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste
|
|||
}
|
||||
char subbrute_payload_byte[4];
|
||||
string_set_str(candidate, instance->file_key);
|
||||
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)instance->file_key[step]);
|
||||
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step);
|
||||
string_replace_at(candidate, step, 3, subbrute_payload_byte);
|
||||
//snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]);
|
||||
} else {
|
||||
|
@ -303,26 +260,21 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste
|
|||
return true;
|
||||
}
|
||||
|
||||
SubBruteFileResult subbrute_device_attack_set(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteAttacks type,
|
||||
const char* file_path) {
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set: %d", type);
|
||||
#endif
|
||||
subbrute_device_attack_set_default_values(instance);
|
||||
uint8_t file_result;
|
||||
|
||||
instance->attack = type;
|
||||
|
||||
subbrute_device_attack_set_default_values(instance, type);
|
||||
switch(type) {
|
||||
case SubBruteAttackLoadFile:
|
||||
file_result = subbrute_device_load_from_file(instance, file_path);
|
||||
if(file_result != SubBruteFileResultOk) {
|
||||
// Failed load file so failed to set attack type
|
||||
return file_result; // RETURN
|
||||
}
|
||||
// In this case values must be already set
|
||||
// file_result =
|
||||
// subbrute_device_load_from_file(instance, string_get_cstr(instance->load_path));
|
||||
// if(file_result != SubBruteFileResultOk) {
|
||||
// // Failed load file so failed to set attack type
|
||||
// return file_result; // RETURN
|
||||
// }
|
||||
break;
|
||||
case SubBruteAttackCAME12bit307:
|
||||
case SubBruteAttackCAME12bit433:
|
||||
|
@ -460,10 +412,10 @@ SubBruteFileResult subbrute_device_attack_set(
|
|||
return SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) {
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_path) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", file_path);
|
||||
FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", string_get_cstr(file_path));
|
||||
#endif
|
||||
SubBruteFileResult result = SubBruteFileResultUnknown;
|
||||
|
||||
|
@ -480,8 +432,8 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
|
|||
furi_hal_subghz_reset();
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||
if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_path))) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", string_get_cstr(file_path));
|
||||
result = SubBruteFileResultErrorOpenFile;
|
||||
break;
|
||||
}
|
||||
|
@ -504,21 +456,24 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
|
|||
break;
|
||||
}
|
||||
// Preset
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", instance->preset_name)) {
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Preset FAIL");
|
||||
result = SubBruteFileResultPresetInvalid;
|
||||
} else {
|
||||
string_init_set_str(instance->preset_name, string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
// Protocol
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", instance->protocol_name)) {
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
result = SubBruteFileResultMissingProtocol;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
string_init_set_str(instance->protocol_name, string_get_cstr(temp_str));
|
||||
#ifdef FURI_DEBUG
|
||||
else {
|
||||
FURI_LOG_D(TAG, "Protocol: %s", string_get_cstr(instance->protocol_name));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||
instance->receiver, string_get_cstr(instance->protocol_name));
|
||||
|
@ -615,25 +570,29 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
|
|||
return result;
|
||||
}
|
||||
|
||||
void subbrute_device_attack_set_default_values(SubBruteDevice* instance) {
|
||||
void subbrute_device_attack_set_default_values(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteAttacks default_attack) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values");
|
||||
#endif
|
||||
instance->attack = SubBruteAttackCAME12bit307;
|
||||
instance->max_value = 0;
|
||||
instance->attack = default_attack;
|
||||
instance->key_index = 0x00;
|
||||
|
||||
memset(instance->file_template, 0, sizeof(instance->file_template));
|
||||
memset(instance->current_key, 0, sizeof(instance->current_key));
|
||||
memset(instance->file_key, 0, sizeof(instance->file_key));
|
||||
memset(instance->text_store, 0, sizeof(instance->text_store));
|
||||
memset(instance->payload, 0, sizeof(instance->payload));
|
||||
|
||||
if(default_attack != SubBruteAttackLoadFile) {
|
||||
memset(instance->file_key, 0, sizeof(instance->file_key));
|
||||
|
||||
instance->max_value = (uint64_t)0x00;
|
||||
|
||||
string_clear(instance->protocol_name);
|
||||
string_clear(instance->preset_name);
|
||||
string_clear(instance->load_path);
|
||||
|
||||
string_clear(instance->load_path);
|
||||
string_init(instance->load_path);
|
||||
|
||||
string_init_set_str(instance->protocol_name, protocol_raw);
|
||||
|
@ -643,7 +602,7 @@ void subbrute_device_attack_set_default_values(SubBruteDevice* instance) {
|
|||
instance->repeat = 5;
|
||||
instance->te = 0;
|
||||
instance->has_tail = false;
|
||||
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG, "subbrute_device_attack_set_default_values done. has_tail: %d", instance->has_tail);
|
||||
|
|
|
@ -55,7 +55,6 @@ typedef enum {
|
|||
} SubBruteDeviceState;
|
||||
|
||||
typedef struct {
|
||||
DialogsApp* dialogs;
|
||||
SubBruteDeviceState state;
|
||||
|
||||
// Current step
|
||||
|
@ -89,14 +88,10 @@ typedef struct {
|
|||
|
||||
SubBruteDevice* subbrute_device_alloc();
|
||||
void subbrute_device_free(SubBruteDevice* instance);
|
||||
SubBruteFileResult subbrute_device_load_protocol_from_file(SubBruteDevice* instance);
|
||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name);
|
||||
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id);
|
||||
bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint64_t step);
|
||||
SubBruteFileResult subbrute_device_attack_set(
|
||||
SubBruteDevice* context,
|
||||
SubBruteAttacks type,
|
||||
const char* file_path);
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type);
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, string_t file_path);
|
||||
FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset);
|
||||
void subbrute_device_attack_set_default_values(SubBruteDevice* context);
|
||||
void subbrute_device_attack_set_default_values(SubBruteDevice* context, SubBruteAttacks default_attack);
|
|
@ -306,12 +306,17 @@ void subbrute_attack_view_exit(void* context) {
|
|||
SubBruteAttackView* instance = context;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_attack_view_exit");
|
||||
furi_delay_ms(150);
|
||||
#endif
|
||||
with_view_model(
|
||||
instance->view, (SubBruteAttackViewModel * model) {
|
||||
icon_animation_stop(model->icon);
|
||||
return false;
|
||||
});
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_worker_stop");
|
||||
furi_delay_ms(150);
|
||||
#endif
|
||||
|
||||
// Just stop, make free in free method
|
||||
subbrute_worker_stop(instance->worker);
|
||||
|
|
|
@ -216,7 +216,7 @@ View* subbrute_main_view_get_view(SubBruteMainView* instance) {
|
|||
|
||||
void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) {
|
||||
furi_assert(instance);
|
||||
furi_assert(idx < SubBruteAttackTotalCount - 1);
|
||||
furi_assert(idx < SubBruteAttackTotalCount);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Set index: %d", idx);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue