mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 15:08:36 -07:00
Returned to Worker model
This commit is contained in:
362
applications/plugins/subbrute/helpers/subbrute_worker.c
Normal file
362
applications/plugins/subbrute/helpers/subbrute_worker.c
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
#include "subbrute_worker_private.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <toolbox/stream/stream.h>
|
||||||
|
#include <flipper_format.h>
|
||||||
|
#include <flipper_format_i.h>
|
||||||
|
|
||||||
|
#define TAG "SubBruteWorker"
|
||||||
|
#define SUBBRUTE_TX_TIMEOUT 5
|
||||||
|
#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
|
||||||
|
|
||||||
|
SubBruteWorker* subbrute_worker_alloc() {
|
||||||
|
SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
|
||||||
|
|
||||||
|
instance->state = SubBruteWorkerStateIDLE;
|
||||||
|
instance->key_index = 0;
|
||||||
|
instance->worker_running = false;
|
||||||
|
instance->initiated = false;
|
||||||
|
instance->last_time_tx_data = 0;
|
||||||
|
instance->load_index = 0;
|
||||||
|
|
||||||
|
instance->thread = furi_thread_alloc();
|
||||||
|
furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
|
||||||
|
furi_thread_set_stack_size(instance->thread, 2048);
|
||||||
|
furi_thread_set_context(instance->thread, instance);
|
||||||
|
furi_thread_set_callback(instance->thread, subbrute_worker_thread);
|
||||||
|
|
||||||
|
instance->context = NULL;
|
||||||
|
instance->callback = NULL;
|
||||||
|
|
||||||
|
instance->decoder_result = NULL;
|
||||||
|
instance->transmitter = NULL;
|
||||||
|
instance->environment = subghz_environment_alloc();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_worker_free(SubBruteWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
// I don't know how to free this
|
||||||
|
instance->decoder_result = NULL;
|
||||||
|
|
||||||
|
if(instance->transmitter != NULL) {
|
||||||
|
subghz_transmitter_free(instance->transmitter);
|
||||||
|
instance->transmitter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
subghz_environment_free(instance->environment);
|
||||||
|
instance->environment = NULL;
|
||||||
|
|
||||||
|
furi_thread_free(instance->thread);
|
||||||
|
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t subbrute_worker_get_step(SubBruteWorker* instance) {
|
||||||
|
return instance->key_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(!subbrute_worker_can_manual_transmit(instance)) {
|
||||||
|
FURI_LOG_W(TAG, "Cannot set step during running mode");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->key_index = step;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_init_default_attack(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
SubBruteAttacks attack_type,
|
||||||
|
uint64_t step,
|
||||||
|
const SubBruteProtocol* protocol) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(instance->worker_running) {
|
||||||
|
FURI_LOG_W(TAG, "Init Worker when it's running");
|
||||||
|
subbrute_worker_stop(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->attack = attack_type;
|
||||||
|
instance->frequency = protocol->frequency;
|
||||||
|
instance->preset = protocol->preset;
|
||||||
|
instance->file = protocol->file;
|
||||||
|
instance->key_index = step;
|
||||||
|
instance->bits = protocol->bits;
|
||||||
|
instance->te = protocol->te;
|
||||||
|
instance->load_index = 0;
|
||||||
|
instance->file_key = NULL;
|
||||||
|
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_init_file_attack(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t load_index,
|
||||||
|
const char* file_key,
|
||||||
|
SubBruteProtocol* protocol) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(instance->worker_running) {
|
||||||
|
FURI_LOG_W(TAG, "Init Worker when it's running");
|
||||||
|
subbrute_worker_stop(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->attack = SubBruteAttackLoadFile;
|
||||||
|
instance->frequency = protocol->frequency;
|
||||||
|
instance->preset = protocol->preset;
|
||||||
|
instance->file = protocol->file;
|
||||||
|
instance->key_index = step;
|
||||||
|
instance->bits = protocol->bits;
|
||||||
|
instance->te = protocol->te;
|
||||||
|
instance->load_index = load_index;
|
||||||
|
instance->file_key = file_key;
|
||||||
|
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_start(SubBruteWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(!instance->initiated) {
|
||||||
|
FURI_LOG_W(TAG, "Worker not init!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instance->worker_running) {
|
||||||
|
FURI_LOG_W(TAG, "Worker is already running!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(instance->state != SubBruteWorkerStateReady &&
|
||||||
|
instance->state != SubBruteWorkerStateFinished) {
|
||||||
|
FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->worker_running = true;
|
||||||
|
furi_thread_start(instance->thread);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_worker_stop(SubBruteWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
instance->worker_running = false;
|
||||||
|
|
||||||
|
furi_thread_join(instance->thread);
|
||||||
|
|
||||||
|
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||||
|
furi_hal_subghz_sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(!instance->initiated) {
|
||||||
|
FURI_LOG_W(TAG, "Worker not init!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(instance->worker_running) {
|
||||||
|
FURI_LOG_W(TAG, "Worker in running state!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(instance->state != SubBruteWorkerStateReady &&
|
||||||
|
instance->state != SubBruteWorkerStateFinished) {
|
||||||
|
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ticks = furi_get_tick();
|
||||||
|
if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
|
||||||
|
#if FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->last_time_tx_data = ticks;
|
||||||
|
instance->key_index = step;
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||||
|
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||||
|
|
||||||
|
FuriString* payload = furi_string_alloc();
|
||||||
|
stream_clean(stream);
|
||||||
|
|
||||||
|
if(instance->attack == SubBruteAttackLoadFile) {
|
||||||
|
payload = subbrute_protocol_file_payload(
|
||||||
|
step,
|
||||||
|
instance->bits,
|
||||||
|
instance->te,
|
||||||
|
instance->repeat,
|
||||||
|
instance->load_index,
|
||||||
|
instance->file_key);
|
||||||
|
} else {
|
||||||
|
payload = subbrute_protocol_default_payload(
|
||||||
|
step, instance->bits, instance->te, instance->repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t written = stream_write_string(stream, payload);
|
||||||
|
if(written <= 0) {
|
||||||
|
FURI_LOG_W(TAG, "Error creating packet! EXIT");
|
||||||
|
result = false;
|
||||||
|
} else {
|
||||||
|
subbrute_worker_subghz_transmit(instance, flipper_format);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
#if FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "Manual transmit done");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
flipper_format_free(flipper_format);
|
||||||
|
furi_string_free(payload);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_is_running(SubBruteWorker* instance) {
|
||||||
|
return instance->worker_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(!instance->initiated) {
|
||||||
|
FURI_LOG_W(TAG, "Worker not init!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !instance->worker_running && instance->state != SubBruteWorkerStateIDLE &&
|
||||||
|
instance->state != SubBruteWorkerStateTx &&
|
||||||
|
((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_worker_set_callback(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
SubBruteWorkerCallback callback,
|
||||||
|
void* context) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
instance->callback = callback;
|
||||||
|
instance->context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format) {
|
||||||
|
instance->transmitter = subghz_transmitter_alloc_init(
|
||||||
|
instance->environment, subbrute_protocol_name(instance->attack));
|
||||||
|
subghz_transmitter_deserialize(instance->transmitter, flipper_format);
|
||||||
|
furi_hal_subghz_reset();
|
||||||
|
furi_hal_subghz_load_preset(instance->preset);
|
||||||
|
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||||
|
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
|
||||||
|
|
||||||
|
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||||
|
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||||
|
}
|
||||||
|
furi_hal_subghz_stop_async_tx();
|
||||||
|
|
||||||
|
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||||
|
furi_hal_subghz_sleep();
|
||||||
|
subghz_transmitter_free(instance->transmitter);
|
||||||
|
instance->transmitter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_worker_send_callback(SubBruteWorker* instance) {
|
||||||
|
if(instance->callback != NULL) {
|
||||||
|
instance->callback(instance->context, instance->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entrypoint for worker
|
||||||
|
*
|
||||||
|
* @param context SubBruteWorker*
|
||||||
|
* @return 0 if ok
|
||||||
|
*/
|
||||||
|
int32_t subbrute_worker_thread(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubBruteWorker* instance = (SubBruteWorker*)context;
|
||||||
|
|
||||||
|
if(!instance->worker_running) {
|
||||||
|
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(instance->state != SubBruteWorkerStateReady &&
|
||||||
|
instance->state != SubBruteWorkerStateFinished) {
|
||||||
|
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_I(TAG, "Worker start");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SubBruteWorkerState local_state = instance->state = SubBruteWorkerStateTx;
|
||||||
|
subbrute_worker_send_callback(instance);
|
||||||
|
|
||||||
|
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||||
|
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||||
|
|
||||||
|
while(instance->worker_running) {
|
||||||
|
FuriString* payload = furi_string_alloc();
|
||||||
|
stream_clean(stream);
|
||||||
|
|
||||||
|
if(instance->attack == SubBruteAttackLoadFile) {
|
||||||
|
payload = subbrute_protocol_file_payload(
|
||||||
|
instance->key_index,
|
||||||
|
instance->bits,
|
||||||
|
instance->te,
|
||||||
|
instance->repeat,
|
||||||
|
instance->load_index,
|
||||||
|
instance->file_key);
|
||||||
|
} else {
|
||||||
|
payload = subbrute_protocol_default_payload(
|
||||||
|
instance->key_index, instance->bits, instance->te, instance->repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t written = stream_write_string(stream, payload);
|
||||||
|
if(written <= 0) {
|
||||||
|
FURI_LOG_W(TAG, "Error creating packet! BREAK");
|
||||||
|
instance->worker_running = false;
|
||||||
|
local_state = SubBruteWorkerStateIDLE;
|
||||||
|
furi_string_free(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
subbrute_worker_subghz_transmit(instance, flipper_format);
|
||||||
|
|
||||||
|
if(instance->key_index + 1 > instance->max_value) {
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_I(TAG, "Worker finished to end");
|
||||||
|
#endif
|
||||||
|
local_state = SubBruteWorkerStateFinished;
|
||||||
|
furi_string_free(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
instance->key_index++;
|
||||||
|
|
||||||
|
furi_string_free(payload);
|
||||||
|
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
flipper_format_free(flipper_format);
|
||||||
|
|
||||||
|
instance->worker_running = false; // Because we have error states
|
||||||
|
instance->state = local_state == SubBruteWorkerStateTx ? SubBruteWorkerStateReady :
|
||||||
|
local_state;
|
||||||
|
subbrute_worker_send_callback(instance);
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_I(TAG, "Worker stop");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
39
applications/plugins/subbrute/helpers/subbrute_worker.h
Normal file
39
applications/plugins/subbrute/helpers/subbrute_worker.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../subbrute_protocols.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubBruteWorkerStateIDLE,
|
||||||
|
SubBruteWorkerStateReady,
|
||||||
|
SubBruteWorkerStateTx,
|
||||||
|
SubBruteWorkerStateFinished
|
||||||
|
} SubBruteWorkerState;
|
||||||
|
|
||||||
|
typedef void (*SubBruteWorkerCallback)(void* context, SubBruteWorkerState state);
|
||||||
|
|
||||||
|
typedef struct SubBruteWorker SubBruteWorker;
|
||||||
|
|
||||||
|
SubBruteWorker* subbrute_worker_alloc();
|
||||||
|
void subbrute_worker_free(SubBruteWorker* instance);
|
||||||
|
uint64_t subbrute_worker_get_step(SubBruteWorker* instance);
|
||||||
|
bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step);
|
||||||
|
bool subbrute_worker_is_running(SubBruteWorker* instance);
|
||||||
|
bool subbrute_worker_init_default_attack(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
SubBruteAttacks attack_type,
|
||||||
|
uint64_t step,
|
||||||
|
const SubBruteProtocol* protocol);
|
||||||
|
bool subbrute_worker_init_file_attack(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t load_index,
|
||||||
|
const char* file_key,
|
||||||
|
SubBruteProtocol* protocol);
|
||||||
|
bool subbrute_worker_start(SubBruteWorker* instance);
|
||||||
|
void subbrute_worker_stop(SubBruteWorker* instance);
|
||||||
|
bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step);
|
||||||
|
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance);
|
||||||
|
void subbrute_worker_set_callback(
|
||||||
|
SubBruteWorker* instance,
|
||||||
|
SubBruteWorkerCallback callback,
|
||||||
|
void* context);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "subbrute_worker.h"
|
||||||
|
#include <lib/subghz/protocols/base.h>
|
||||||
|
#include <lib/subghz/transmitter.h>
|
||||||
|
#include <lib/subghz/receiver.h>
|
||||||
|
#include <lib/subghz/environment.h>
|
||||||
|
|
||||||
|
struct SubBruteWorker {
|
||||||
|
SubBruteWorkerState state;
|
||||||
|
volatile bool worker_running;
|
||||||
|
volatile bool initiated;
|
||||||
|
|
||||||
|
// Current step
|
||||||
|
uint64_t key_index;
|
||||||
|
|
||||||
|
// SubGhz
|
||||||
|
FuriThread* thread;
|
||||||
|
SubGhzProtocolDecoderBase* decoder_result;
|
||||||
|
SubGhzEnvironment* environment;
|
||||||
|
SubGhzTransmitter* transmitter;
|
||||||
|
|
||||||
|
// Initiated values
|
||||||
|
SubBruteAttacks attack; // Attack state
|
||||||
|
uint32_t frequency;
|
||||||
|
FuriHalSubGhzPreset preset;
|
||||||
|
SubBruteFileProtocol file;
|
||||||
|
uint8_t bits;
|
||||||
|
uint8_t te;
|
||||||
|
uint8_t repeat;
|
||||||
|
uint8_t load_index; // Index of group to bruteforce in loaded file
|
||||||
|
const char* file_key;
|
||||||
|
uint64_t max_value; // Max step
|
||||||
|
|
||||||
|
// Manual transmit
|
||||||
|
uint32_t last_time_tx_data;
|
||||||
|
|
||||||
|
// Callback for changed states
|
||||||
|
SubBruteWorkerCallback callback;
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t subbrute_worker_thread(void* context);
|
||||||
|
void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format);
|
||||||
|
void subbrute_worker_send_callback(SubBruteWorker* instance);
|
||||||
@@ -39,6 +39,14 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
|||||||
if(load_result == SubBruteFileResultOk) {
|
if(load_result == SubBruteFileResultOk) {
|
||||||
load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile);
|
load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile);
|
||||||
if(load_result == SubBruteFileResultOk) {
|
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->file_protocol_info)) {
|
||||||
|
furi_crash("Invalid attack set!");
|
||||||
|
}
|
||||||
// Ready to run!
|
// Ready to run!
|
||||||
FURI_LOG_I(TAG, "Ready to run");
|
FURI_LOG_I(TAG, "Ready to run");
|
||||||
res = true;
|
res = true;
|
||||||
@@ -52,7 +60,8 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
|||||||
|
|
||||||
FuriString* dialog_msg;
|
FuriString* dialog_msg;
|
||||||
dialog_msg = furi_string_alloc();
|
dialog_msg = furi_string_alloc();
|
||||||
furi_string_cat_printf(dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
furi_string_cat_printf(
|
||||||
|
dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||||
dialog_message_show_storage_error(instance->dialogs, furi_string_get_cstr(dialog_msg));
|
dialog_message_show_storage_error(instance->dialogs, furi_string_get_cstr(dialog_msg));
|
||||||
furi_string_free(dialog_msg);
|
furi_string_free(dialog_msg);
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void subbrute_scene_load_select_on_enter(void* context) {
|
|||||||
|
|
||||||
instance->current_view = SubBruteViewMain;
|
instance->current_view = SubBruteViewMain;
|
||||||
subbrute_main_view_set_callback(view, subbrute_scene_load_select_callback, instance);
|
subbrute_main_view_set_callback(view, subbrute_scene_load_select_callback, instance);
|
||||||
subbrute_main_view_set_index(view, 7, true, subbrute_device_get_file_key(instance->device));
|
subbrute_main_view_set_index(view, 7, true, instance->device->file_key);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||||
}
|
}
|
||||||
@@ -38,8 +38,15 @@ bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event)
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubBruteCustomEventTypeIndexSelected) {
|
if(event.event == SubBruteCustomEventTypeIndexSelected) {
|
||||||
subbrute_device_set_load_index(
|
instance->device->load_index = subbrute_main_view_get_index(instance->view_main);
|
||||||
instance->device, subbrute_main_view_get_index(instance->view_main));
|
if(!subbrute_worker_init_file_attack(
|
||||||
|
instance->worker,
|
||||||
|
instance->device->key_index,
|
||||||
|
instance->device->load_index,
|
||||||
|
instance->device->file_key,
|
||||||
|
instance->device->file_protocol_info)) {
|
||||||
|
furi_crash("Invalid attack set!");
|
||||||
|
}
|
||||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void*
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
subbrute_scene_run_attack_device_state_changed(void* context, SubBruteDeviceState state) {
|
subbrute_scene_run_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
SubBruteState* instance = (SubBruteState*)context;
|
SubBruteState* instance = (SubBruteState*)context;
|
||||||
|
|
||||||
if(state == SubBruteDeviceStateIDLE) {
|
if(state == SubBruteWorkerStateIDLE) {
|
||||||
// Can't be IDLE on this step!
|
// Can't be IDLE on this step!
|
||||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||||
} else if(state == SubBruteDeviceStateFinished) {
|
} else if(state == SubBruteWorkerStateFinished) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ void subbrute_scene_run_attack_on_exit(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubBruteState* instance = (SubBruteState*)context;
|
SubBruteState* instance = (SubBruteState*)context;
|
||||||
|
|
||||||
subbrute_worker_stop(instance->device);
|
subbrute_worker_stop(instance->worker);
|
||||||
|
|
||||||
notification_message(instance->notifications, &sequence_blink_stop);
|
notification_message(instance->notifications, &sequence_blink_stop);
|
||||||
}
|
}
|
||||||
@@ -42,11 +42,11 @@ void subbrute_scene_run_attack_on_enter(void* context) {
|
|||||||
subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance);
|
subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance);
|
||||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||||
|
|
||||||
subbrute_device_set_callback(
|
subbrute_worker_set_callback(
|
||||||
instance->device, subbrute_scene_run_attack_device_state_changed, instance);
|
instance->worker, subbrute_scene_run_attack_device_state_changed, instance);
|
||||||
|
|
||||||
if(!subbrute_device_is_worker_running(instance->device)) {
|
if(!subbrute_worker_is_running(instance->worker)) {
|
||||||
subbrute_worker_start(instance->device);
|
subbrute_worker_start(instance->worker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
subbrute_attack_view_set_current_step(view, subbrute_get_step(instance));
|
subbrute_attack_view_set_current_step(view, subbrute_worker_get_step(instance->worker));
|
||||||
|
|
||||||
if(event.event == SubBruteCustomEventTypeTransmitFinished) {
|
if(event.event == SubBruteCustomEventTypeTransmitFinished) {
|
||||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||||
@@ -77,7 +77,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
|
|||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.type == SceneManagerEventTypeTick) {
|
} else if(event.type == SceneManagerEventTypeTick) {
|
||||||
subbrute_attack_view_set_current_step(view, subbrute_get_step(instance));
|
subbrute_attack_view_set_current_step(view, subbrute_worker_get_step(instance->worker));
|
||||||
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteDeviceState state) {
|
subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
SubBruteState* instance = (SubBruteState*)context;
|
SubBruteState* instance = (SubBruteState*)context;
|
||||||
|
|
||||||
if(state == SubBruteDeviceStateIDLE) {
|
if(state == SubBruteWorkerStateIDLE) {
|
||||||
// Can't be IDLE on this step!
|
// Can't be IDLE on this step!
|
||||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||||
}
|
}
|
||||||
@@ -28,16 +28,24 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
|||||||
SubBruteAttackView* view = instance->view_attack;
|
SubBruteAttackView* view = instance->view_attack;
|
||||||
|
|
||||||
#ifdef FURI_DEBUG
|
#ifdef FURI_DEBUG
|
||||||
FURI_LOG_D(TAG, "Enter Attack: %d", subbrute_device_get_attack(instance->device));
|
FURI_LOG_D(TAG, "Enter Attack: %d", instance->device->attack);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
subbrute_device_set_callback(
|
subbrute_worker_set_callback(
|
||||||
instance->device, subbrute_scene_setup_attack_device_state_changed, context);
|
instance->worker, subbrute_scene_setup_attack_device_state_changed, context);
|
||||||
|
|
||||||
if(subbrute_device_is_worker_running(instance->device)) {
|
if(subbrute_worker_is_running(instance->worker)) {
|
||||||
subbrute_worker_stop(instance->device);
|
instance->device->key_index = subbrute_worker_get_step(instance->worker);
|
||||||
|
subbrute_worker_stop(instance->worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subbrute_attack_view_init_values(
|
||||||
|
view,
|
||||||
|
instance->device->attack,
|
||||||
|
instance->device->max_value,
|
||||||
|
instance->device->key_index,
|
||||||
|
false);
|
||||||
|
|
||||||
instance->current_view = SubBruteViewAttack;
|
instance->current_view = SubBruteViewAttack;
|
||||||
subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance);
|
subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance);
|
||||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||||
@@ -49,7 +57,7 @@ void subbrute_scene_setup_attack_on_exit(void* context) {
|
|||||||
FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit");
|
FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit");
|
||||||
#endif
|
#endif
|
||||||
SubBruteState* instance = (SubBruteState*)context;
|
SubBruteState* instance = (SubBruteState*)context;
|
||||||
subbrute_worker_stop(instance->device);
|
subbrute_worker_stop(instance->worker);
|
||||||
notification_message(instance->notifications, &sequence_blink_stop);
|
notification_message(instance->notifications, &sequence_blink_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,53 +73,60 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
|||||||
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
||||||
subbrute_attack_view_init_values(
|
subbrute_attack_view_init_values(
|
||||||
view,
|
view,
|
||||||
subbrute_device_get_attack(instance->device),
|
instance->device->attack,
|
||||||
subbrute_device_get_max_value(instance->device),
|
instance->device->max_value,
|
||||||
subbrute_device_get_step(instance->device),
|
instance->device->key_index,
|
||||||
false);
|
false);
|
||||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
|
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
|
||||||
} else if(event.event == SubBruteCustomEventTypeBackPressed) {
|
} else if(event.event == SubBruteCustomEventTypeBackPressed) {
|
||||||
subbrute_device_reset_step(instance->device);
|
|
||||||
subbrute_attack_view_init_values(
|
subbrute_attack_view_init_values(
|
||||||
view,
|
view,
|
||||||
subbrute_device_get_attack(instance->device),
|
instance->device->attack,
|
||||||
subbrute_device_get_max_value(instance->device),
|
instance->device->max_value,
|
||||||
subbrute_device_get_step(instance->device),
|
instance->device->key_index,
|
||||||
false);
|
false);
|
||||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
||||||
} else if(event.event == SubBruteCustomEventTypeError) {
|
} else if(event.event == SubBruteCustomEventTypeError) {
|
||||||
notification_message(instance->notifications, &sequence_error);
|
notification_message(instance->notifications, &sequence_error);
|
||||||
} else if(event.event == SubBruteCustomEventTypeTransmitCustom) {
|
} else if(event.event == SubBruteCustomEventTypeTransmitCustom) {
|
||||||
// We can transmit only in not working states
|
// We can transmit only in not working states
|
||||||
if(subbrute_device_can_manual_transmit(instance->device)) {
|
if(subbrute_worker_can_manual_transmit(instance->worker)) {
|
||||||
// MANUAL Transmit!
|
// MANUAL Transmit!
|
||||||
// Blink
|
// Blink
|
||||||
notification_message(instance->notifications, &sequence_blink_green_100);
|
notification_message(instance->notifications, &sequence_blink_green_100);
|
||||||
subbrute_device_transmit_current_key(instance->device);
|
subbrute_worker_transmit_current_key(
|
||||||
|
instance->worker, instance->device->key_index);
|
||||||
// Stop
|
// Stop
|
||||||
notification_message(instance->notifications, &sequence_blink_stop);
|
notification_message(instance->notifications, &sequence_blink_stop);
|
||||||
}
|
}
|
||||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
|
} else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
|
||||||
// +1
|
// +1
|
||||||
uint64_t step = subbrute_device_add_step(instance->device, 1);
|
uint64_t step = subbrute_device_add_step(instance->device, 1);
|
||||||
|
subbrute_worker_set_step(instance->worker, step);
|
||||||
subbrute_attack_view_set_current_step(view, step);
|
subbrute_attack_view_set_current_step(view, step);
|
||||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) {
|
} else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) {
|
||||||
// +50
|
// +50
|
||||||
uint64_t step = subbrute_device_add_step(instance->device, 50);
|
uint64_t step = subbrute_device_add_step(instance->device, 50);
|
||||||
|
subbrute_worker_set_step(instance->worker, step);
|
||||||
subbrute_attack_view_set_current_step(view, step);
|
subbrute_attack_view_set_current_step(view, step);
|
||||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDown) {
|
} else if(event.event == SubBruteCustomEventTypeChangeStepDown) {
|
||||||
// -1
|
// -1
|
||||||
uint64_t step = subbrute_device_add_step(instance->device, -1);
|
uint64_t step = subbrute_device_add_step(instance->device, -1);
|
||||||
|
subbrute_worker_set_step(instance->worker, step);
|
||||||
subbrute_attack_view_set_current_step(view, step);
|
subbrute_attack_view_set_current_step(view, step);
|
||||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) {
|
} else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) {
|
||||||
// -50
|
// -50
|
||||||
uint64_t step = subbrute_device_add_step(instance->device, -50);
|
uint64_t step = subbrute_device_add_step(instance->device, -50);
|
||||||
|
subbrute_worker_set_step(instance->worker, step);
|
||||||
subbrute_attack_view_set_current_step(view, step);
|
subbrute_attack_view_set_current_step(view, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.type == SceneManagerEventTypeTick) {
|
} else if(event.type == SceneManagerEventTypeTick) {
|
||||||
subbrute_attack_view_set_current_step(view, subbrute_device_get_step(instance->device));
|
if(subbrute_worker_is_running(instance->worker)) {
|
||||||
|
instance->device->key_index = subbrute_worker_get_step(instance->worker);
|
||||||
|
}
|
||||||
|
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void subbrute_scene_start_on_enter(void* context) {
|
|||||||
|
|
||||||
instance->current_view = SubBruteViewMain;
|
instance->current_view = SubBruteViewMain;
|
||||||
subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance);
|
subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance);
|
||||||
subbrute_main_view_set_index(view, subbrute_device_get_attack(instance->device), false, NULL);
|
subbrute_main_view_set_index(view, instance->device->attack, false, NULL);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,14 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
if(event.event == SubBruteCustomEventTypeMenuSelected) {
|
if(event.event == SubBruteCustomEventTypeMenuSelected) {
|
||||||
SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main);
|
SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main);
|
||||||
|
|
||||||
subbrute_device_attack_set(instance->device, attack);
|
if(subbrute_device_attack_set(instance->device, attack) != SubBruteFileResultOk ||
|
||||||
|
!subbrute_worker_init_default_attack(
|
||||||
|
instance->worker,
|
||||||
|
attack,
|
||||||
|
instance->device->key_index,
|
||||||
|
instance->device->protocol_info)) {
|
||||||
|
furi_crash("Invalid attack set!");
|
||||||
|
}
|
||||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||||
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ SubBruteState* subbrute_alloc() {
|
|||||||
// Devices
|
// Devices
|
||||||
instance->device = subbrute_device_alloc();
|
instance->device = subbrute_device_alloc();
|
||||||
|
|
||||||
|
// SubBruteWorker
|
||||||
|
instance->worker = subbrute_worker_alloc();
|
||||||
|
|
||||||
// TextInput
|
// TextInput
|
||||||
instance->text_input = text_input_alloc();
|
instance->text_input = text_input_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@@ -96,8 +99,11 @@ SubBruteState* subbrute_alloc() {
|
|||||||
void subbrute_free(SubBruteState* instance) {
|
void subbrute_free(SubBruteState* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
|
// SubBruteWorker
|
||||||
|
subbrute_worker_stop(instance->worker);
|
||||||
|
subbrute_worker_free(instance->worker);
|
||||||
|
|
||||||
// SubBruteDevice
|
// SubBruteDevice
|
||||||
subbrute_worker_stop(instance->device);
|
|
||||||
subbrute_device_free(instance->device);
|
subbrute_device_free(instance->device);
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
@@ -163,13 +169,6 @@ void subbrute_popup_closed_callback(void* context) {
|
|||||||
instance->view_dispatcher, SubBruteCustomEventTypePopupClosed);
|
instance->view_dispatcher, SubBruteCustomEventTypePopupClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t subbrute_get_step(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
SubBruteState* instance = context;
|
|
||||||
|
|
||||||
return subbrute_device_get_step(instance->device);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ENTRYPOINT
|
// ENTRYPOINT
|
||||||
int32_t subbrute_app(void* p) {
|
int32_t subbrute_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|||||||
@@ -8,40 +8,14 @@
|
|||||||
|
|
||||||
#define TAG "SubBruteDevice"
|
#define TAG "SubBruteDevice"
|
||||||
|
|
||||||
#define SUBBRUTE_TX_TIMEOUT 5
|
|
||||||
#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Values to not use less memory for packet parse operations
|
|
||||||
*/
|
|
||||||
static const char* subbrute_key_file_start =
|
|
||||||
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d";
|
|
||||||
static const char* subbrute_key_file_key = "%s\nKey: %s\nRepeat: %d\n";
|
|
||||||
static const char* subbrute_key_file_key_with_tail = "%s\nKey: %s\nTE: %d\nRepeat: %d\n";
|
|
||||||
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\nRepeat: %d\nRepeat: %d\n";
|
|
||||||
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
|
||||||
|
|
||||||
SubBruteDevice* subbrute_device_alloc() {
|
SubBruteDevice* subbrute_device_alloc() {
|
||||||
SubBruteDevice* instance = malloc(sizeof(SubBruteDevice));
|
SubBruteDevice* instance = malloc(sizeof(SubBruteDevice));
|
||||||
|
|
||||||
instance->state = SubBruteDeviceStateIDLE;
|
|
||||||
instance->key_index = 0;
|
instance->key_index = 0;
|
||||||
instance->worker_running = false;
|
|
||||||
instance->last_time_tx_data = 0;
|
|
||||||
|
|
||||||
instance->thread = furi_thread_alloc();
|
|
||||||
furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
|
|
||||||
furi_thread_set_stack_size(instance->thread, 2048);
|
|
||||||
furi_thread_set_context(instance->thread, instance);
|
|
||||||
furi_thread_set_callback(instance->thread, subbrute_worker_thread);
|
|
||||||
|
|
||||||
instance->context = NULL;
|
|
||||||
instance->callback = NULL;
|
|
||||||
|
|
||||||
instance->protocol_info = NULL;
|
instance->protocol_info = NULL;
|
||||||
instance->file_protocol_info = NULL;
|
instance->file_protocol_info = NULL;
|
||||||
instance->decoder_result = NULL;
|
instance->decoder_result = NULL;
|
||||||
instance->transmitter = NULL;
|
|
||||||
instance->receiver = NULL;
|
instance->receiver = NULL;
|
||||||
instance->environment = subghz_environment_alloc();
|
instance->environment = subghz_environment_alloc();
|
||||||
|
|
||||||
@@ -61,137 +35,15 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
|||||||
instance->receiver = NULL;
|
instance->receiver = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(instance->transmitter != NULL) {
|
|
||||||
subghz_transmitter_free(instance->transmitter);
|
|
||||||
instance->transmitter = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
subghz_environment_free(instance->environment);
|
subghz_environment_free(instance->environment);
|
||||||
instance->environment = NULL;
|
instance->environment = NULL;
|
||||||
|
|
||||||
furi_thread_free(instance->thread);
|
|
||||||
subbrute_device_free_protocol_info(instance);
|
subbrute_device_free_protocol_info(instance);
|
||||||
|
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Entrypoint for worker
|
|
||||||
*
|
|
||||||
* @param context SubBruteWorker*
|
|
||||||
* @return 0 if ok
|
|
||||||
*/
|
|
||||||
int32_t subbrute_worker_thread(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
SubBruteDevice* instance = (SubBruteDevice*)context;
|
|
||||||
|
|
||||||
if(!instance->worker_running) {
|
|
||||||
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(instance->state != SubBruteDeviceStateReady &&
|
|
||||||
instance->state != SubBruteDeviceStateFinished) {
|
|
||||||
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_I(TAG, "Worker start");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SubBruteDeviceState local_state = instance->state = SubBruteDeviceStateTx;
|
|
||||||
subbrute_device_send_callback(instance);
|
|
||||||
|
|
||||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
|
||||||
|
|
||||||
while(instance->worker_running) {
|
|
||||||
if(!subbrute_device_create_packet_parsed(
|
|
||||||
instance, flipper_format, instance->key_index, true)) {
|
|
||||||
FURI_LOG_W(TAG, "Error creating packet! BREAK");
|
|
||||||
instance->worker_running = false;
|
|
||||||
local_state = SubBruteDeviceStateIDLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
subbrute_device_subghz_transmit(instance, flipper_format);
|
|
||||||
|
|
||||||
if(instance->key_index + 1 > instance->max_value) {
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_I(TAG, "Worker finished to end");
|
|
||||||
#endif
|
|
||||||
local_state = SubBruteDeviceStateFinished;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
instance->key_index++;
|
|
||||||
|
|
||||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
flipper_format_free(flipper_format);
|
|
||||||
|
|
||||||
instance->worker_running = false; // Because we have error states
|
|
||||||
instance->state = local_state == SubBruteDeviceStateTx ? SubBruteDeviceStateReady :
|
|
||||||
local_state;
|
|
||||||
subbrute_device_send_callback(instance);
|
|
||||||
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_I(TAG, "Worker stop");
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool subbrute_worker_start(SubBruteDevice* instance) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
if(instance->worker_running) {
|
|
||||||
FURI_LOG_W(TAG, "Worker is already running!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(instance->state != SubBruteDeviceStateReady &&
|
|
||||||
instance->state != SubBruteDeviceStateFinished) {
|
|
||||||
FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if((instance->protocol_info == NULL && instance->attack != SubBruteAttackLoadFile) ||
|
|
||||||
(instance->attack == SubBruteAttackLoadFile && instance->file_protocol_info == NULL)) {
|
|
||||||
FURI_LOG_W(TAG, "Worker cannot start, protocol_info is NULL!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->worker_running = true;
|
|
||||||
furi_thread_start(instance->thread);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void subbrute_worker_stop(SubBruteDevice* instance) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
instance->worker_running = false;
|
|
||||||
|
|
||||||
furi_thread_join(instance->thread);
|
|
||||||
|
|
||||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
|
||||||
furi_hal_subghz_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
SubBruteAttacks subbrute_device_get_attack(SubBruteDevice* instance) {
|
|
||||||
return instance->attack;
|
|
||||||
}
|
|
||||||
bool subbrute_device_is_worker_running(SubBruteDevice* instance) {
|
|
||||||
return instance->worker_running;
|
|
||||||
}
|
|
||||||
uint64_t subbrute_device_get_max_value(SubBruteDevice* instance) {
|
|
||||||
return instance->max_value;
|
|
||||||
}
|
|
||||||
uint64_t subbrute_device_get_step(SubBruteDevice* instance) {
|
|
||||||
return instance->key_index;
|
|
||||||
}
|
|
||||||
const char* subbrute_device_get_file_key(SubBruteDevice* instance) {
|
|
||||||
return instance->file_key;
|
|
||||||
}
|
|
||||||
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
|
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
|
||||||
if(!subbrute_device_can_manual_transmit(instance)) {
|
|
||||||
return instance->key_index;
|
|
||||||
}
|
|
||||||
if(step > 0) {
|
if(step > 0) {
|
||||||
if((instance->key_index + step) - instance->max_value == 1) {
|
if((instance->key_index + step) - instance->max_value == 1) {
|
||||||
instance->key_index = 0x00;
|
instance->key_index = 0x00;
|
||||||
@@ -220,122 +72,17 @@ uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
|
|||||||
|
|
||||||
return instance->key_index;
|
return instance->key_index;
|
||||||
}
|
}
|
||||||
void subbrute_device_set_load_index(SubBruteDevice* instance, uint64_t load_index) {
|
|
||||||
instance->load_index = load_index;
|
|
||||||
}
|
|
||||||
void subbrute_device_reset_step(SubBruteDevice* instance) {
|
|
||||||
instance->key_index = 0x00;
|
|
||||||
}
|
|
||||||
void subbrute_device_subghz_transmit(SubBruteDevice* instance, FlipperFormat* flipper_format) {
|
|
||||||
instance->transmitter = subghz_transmitter_alloc_init(
|
|
||||||
instance->environment, subbrute_protocol_name(instance->attack));
|
|
||||||
subghz_transmitter_deserialize(instance->transmitter, flipper_format);
|
|
||||||
furi_hal_subghz_reset();
|
|
||||||
if(instance->attack == SubBruteAttackLoadFile) {
|
|
||||||
furi_hal_subghz_load_preset(instance->file_protocol_info->preset);
|
|
||||||
furi_hal_subghz_set_frequency_and_path(instance->file_protocol_info->preset);
|
|
||||||
} else {
|
|
||||||
furi_hal_subghz_load_preset(instance->protocol_info->preset);
|
|
||||||
furi_hal_subghz_set_frequency_and_path(instance->protocol_info->preset);
|
|
||||||
}
|
|
||||||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
|
|
||||||
|
|
||||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
|
||||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
|
||||||
}
|
|
||||||
furi_hal_subghz_stop_async_tx();
|
|
||||||
|
|
||||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
|
||||||
furi_hal_subghz_sleep();
|
|
||||||
subghz_transmitter_free(instance->transmitter);
|
|
||||||
instance->transmitter = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool subbrute_device_transmit_current_key(SubBruteDevice* instance) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
if(instance->worker_running) {
|
|
||||||
FURI_LOG_W(TAG, "Worker in running state!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(instance->state != SubBruteDeviceStateReady &&
|
|
||||||
instance->state != SubBruteDeviceStateFinished) {
|
|
||||||
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ticks = furi_get_tick();
|
|
||||||
if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
|
|
||||||
#if FURI_DEBUG
|
|
||||||
FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->last_time_tx_data = ticks;
|
|
||||||
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
if(instance->attack == SubBruteAttackLoadFile) {
|
|
||||||
FURI_LOG_D(
|
|
||||||
TAG,
|
|
||||||
"Protocol: %d, Frequency: %ld",
|
|
||||||
instance->file_protocol_info->file,
|
|
||||||
instance->file_protocol_info->frequency);
|
|
||||||
} else {
|
|
||||||
FURI_LOG_D(
|
|
||||||
TAG,
|
|
||||||
"Protocol: %d, Frequency: %ld",
|
|
||||||
instance->protocol_info->file,
|
|
||||||
instance->protocol_info->frequency);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
|
||||||
|
|
||||||
if(!subbrute_device_create_packet_parsed(instance, flipper_format, instance->key_index, true)) {
|
|
||||||
FURI_LOG_W(TAG, "Error creating packet! EXIT");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
subbrute_device_subghz_transmit(instance, flipper_format);
|
|
||||||
|
|
||||||
flipper_format_free(flipper_format);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void subbrute_device_set_callback(
|
|
||||||
SubBruteDevice* instance,
|
|
||||||
SubBruteDeviceWorkerCallback callback,
|
|
||||||
void* context) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
instance->callback = callback;
|
|
||||||
instance->context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool subbrute_device_can_manual_transmit(SubBruteDevice* instance) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
return !instance->worker_running && instance->state != SubBruteDeviceStateIDLE &&
|
|
||||||
instance->state != SubBruteDeviceStateTx &&
|
|
||||||
((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
|
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
if(instance->state != SubBruteDeviceStateReady &&
|
|
||||||
instance->state != SubBruteDeviceStateFinished) {
|
|
||||||
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef FURI_DEBUG
|
#ifdef FURI_DEBUG
|
||||||
FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name);
|
FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||||
|
FuriString* file_content = furi_string_alloc();
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
do {
|
do {
|
||||||
@@ -343,7 +90,32 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!subbrute_device_create_packet_parsed(instance, file, instance->key_index, false)) {
|
if(instance->attack == SubBruteAttackLoadFile) {
|
||||||
|
file_content = subbrute_protocol_file_generate_file(
|
||||||
|
instance->file_protocol_info->frequency,
|
||||||
|
instance->file_protocol_info->preset,
|
||||||
|
instance->file_protocol_info->file,
|
||||||
|
instance->key_index,
|
||||||
|
instance->file_protocol_info->bits,
|
||||||
|
instance->file_protocol_info->te,
|
||||||
|
instance->file_protocol_info->repeat,
|
||||||
|
instance->load_index,
|
||||||
|
instance->file_key);
|
||||||
|
} else {
|
||||||
|
file_content = subbrute_protocol_default_generate_file(
|
||||||
|
instance->protocol_info->frequency,
|
||||||
|
instance->protocol_info->preset,
|
||||||
|
instance->protocol_info->file,
|
||||||
|
instance->key_index,
|
||||||
|
instance->protocol_info->bits,
|
||||||
|
instance->protocol_info->te,
|
||||||
|
instance->protocol_info->repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream* stream = flipper_format_get_raw_stream(file);
|
||||||
|
stream_clean(stream);
|
||||||
|
size_t written = stream_write_string(stream, file_content);
|
||||||
|
if(written <= 0) {
|
||||||
FURI_LOG_E(TAG, "create_packet_parsed failed!");
|
FURI_LOG_E(TAG, "create_packet_parsed failed!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -352,140 +124,17 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
|
|||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!result) {
|
if(!result) {
|
||||||
FURI_LOG_E(TAG, "flipper_format_file_open_always failed!");
|
FURI_LOG_E(TAG, "subbrute_device_save_file failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flipper_format_file_close(file);
|
||||||
flipper_format_free(file);
|
flipper_format_free(file);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
furi_string_free(file_content);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subbrute_device_create_packet_parsed(
|
|
||||||
SubBruteDevice* instance,
|
|
||||||
FlipperFormat* flipper_format,
|
|
||||||
uint64_t step,
|
|
||||||
bool small) {
|
|
||||||
furi_assert(instance);
|
|
||||||
|
|
||||||
FuriString* candidate = furi_string_alloc();
|
|
||||||
|
|
||||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
|
||||||
stream_clean(stream);
|
|
||||||
|
|
||||||
if(instance->attack == SubBruteAttackLoadFile) {
|
|
||||||
if(step >= sizeof(instance->file_key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char subbrute_payload_byte[4];
|
|
||||||
furi_string_set_str(candidate, instance->file_key);
|
|
||||||
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step);
|
|
||||||
furi_string_replace_at(candidate, instance->load_index * 3, 3, subbrute_payload_byte);
|
|
||||||
//snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]);
|
|
||||||
|
|
||||||
if(small) {
|
|
||||||
if(instance->file_protocol_info->te) {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_small_with_tail,
|
|
||||||
instance->file_protocol_info->bits,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->file_protocol_info->te,
|
|
||||||
instance->file_protocol_info->repeat);
|
|
||||||
} else {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_small_no_tail,
|
|
||||||
instance->file_protocol_info->bits,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->file_protocol_info->repeat);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(instance->file_protocol_info->te) {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_file_key_with_tail,
|
|
||||||
instance->file_template,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->file_protocol_info->te,
|
|
||||||
instance->file_protocol_info->repeat);
|
|
||||||
} else {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_file_key,
|
|
||||||
instance->file_template,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->file_protocol_info->repeat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//snprintf(step_payload, sizeof(step_payload), "%16X", step);
|
|
||||||
//snprintf(step_payload, sizeof(step_payload), "%016llX", step);
|
|
||||||
FuriString* buffer = furi_string_alloc();
|
|
||||||
furi_string_printf(buffer, "%16llX", step);
|
|
||||||
int j = 0;
|
|
||||||
furi_string_set_str(candidate, " ");
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(small) {
|
|
||||||
if(instance->protocol_info->te) {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_small_with_tail,
|
|
||||||
instance->protocol_info->bits,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->protocol_info->te,
|
|
||||||
instance->protocol_info->repeat);
|
|
||||||
} else {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_small_no_tail,
|
|
||||||
instance->protocol_info->bits,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->protocol_info->repeat);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(instance->protocol_info->te) {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_file_key_with_tail,
|
|
||||||
instance->file_template,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->protocol_info->te,
|
|
||||||
instance->protocol_info->repeat);
|
|
||||||
} else {
|
|
||||||
stream_write_format(
|
|
||||||
stream,
|
|
||||||
subbrute_key_file_key,
|
|
||||||
instance->file_template,
|
|
||||||
furi_string_get_cstr(candidate),
|
|
||||||
instance->protocol_info->repeat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_D(TAG, "candidate: %s", furi_string_get_cstr(candidate));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_free(candidate);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
#ifdef FURI_DEBUG
|
#ifdef FURI_DEBUG
|
||||||
@@ -513,10 +162,18 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
|||||||
FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set");
|
FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set");
|
||||||
} else {
|
} else {
|
||||||
protocol_check_result = SubBruteFileResultOk;
|
protocol_check_result = SubBruteFileResultOk;
|
||||||
|
|
||||||
|
// Calc max value
|
||||||
|
instance->max_value =
|
||||||
|
subbrute_protocol_calc_max_value(instance->attack, instance->protocol_info->bits);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// And here we need to set preset enum
|
// And here we need to set preset enum
|
||||||
protocol_check_result = SubBruteFileResultOk;
|
protocol_check_result = SubBruteFileResultOk;
|
||||||
|
|
||||||
|
// Calc max value
|
||||||
|
instance->max_value =
|
||||||
|
subbrute_protocol_calc_max_value(instance->attack, instance->file_protocol_info->bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
subghz_receiver_free(instance->receiver);
|
subghz_receiver_free(instance->receiver);
|
||||||
@@ -526,56 +183,6 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
|||||||
return SubBruteFileResultProtocolNotFound;
|
return SubBruteFileResultProtocolNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calc max value
|
|
||||||
if(instance->attack == SubBruteAttackLoadFile) {
|
|
||||||
instance->max_value = 0x3F;
|
|
||||||
|
|
||||||
// Now we are ready to set file template for using in the future with snprintf
|
|
||||||
// for sending attack payload ONLY for files!
|
|
||||||
snprintf(
|
|
||||||
instance->file_template,
|
|
||||||
sizeof(instance->file_template),
|
|
||||||
subbrute_key_file_start,
|
|
||||||
instance->file_protocol_info->frequency,
|
|
||||||
subbrute_protocol_preset(instance->file_protocol_info->preset),
|
|
||||||
subbrute_protocol_file(instance->file_protocol_info->file),
|
|
||||||
instance->file_protocol_info->bits);
|
|
||||||
} else {
|
|
||||||
FuriString* max_value_s;
|
|
||||||
max_value_s = furi_string_alloc();
|
|
||||||
for(uint8_t i = 0; i < instance->protocol_info->bits; i++) {
|
|
||||||
furi_string_cat_printf(max_value_s, "1");
|
|
||||||
}
|
|
||||||
instance->max_value = (uint64_t)strtol(furi_string_get_cstr(max_value_s), NULL, 2);
|
|
||||||
furi_string_free(max_value_s);
|
|
||||||
|
|
||||||
// Now we are ready to set file template for using in the future with snprintf
|
|
||||||
// for sending attack payload
|
|
||||||
snprintf(
|
|
||||||
instance->file_template,
|
|
||||||
sizeof(instance->file_template),
|
|
||||||
subbrute_key_file_start,
|
|
||||||
instance->protocol_info->frequency,
|
|
||||||
subbrute_protocol_preset(instance->protocol_info->preset),
|
|
||||||
subbrute_protocol_file(instance->protocol_info->file),
|
|
||||||
instance->protocol_info->bits);
|
|
||||||
#ifdef FURI_DEBUG
|
|
||||||
FURI_LOG_D(
|
|
||||||
TAG,
|
|
||||||
"tail: %d, file_template: %s",
|
|
||||||
instance->protocol_info->te,
|
|
||||||
instance->file_template);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init payload
|
|
||||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
|
||||||
if(subbrute_device_create_packet_parsed(instance, flipper_format, instance->key_index, false)) {
|
|
||||||
instance->state = SubBruteDeviceStateReady;
|
|
||||||
subbrute_device_send_callback(instance);
|
|
||||||
}
|
|
||||||
flipper_format_free(flipper_format);
|
|
||||||
|
|
||||||
return SubBruteFileResultOk;
|
return SubBruteFileResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,7 +358,6 @@ void subbrute_device_attack_set_default_values(
|
|||||||
instance->attack = default_attack;
|
instance->attack = default_attack;
|
||||||
instance->key_index = 0x00;
|
instance->key_index = 0x00;
|
||||||
instance->load_index = 0x00;
|
instance->load_index = 0x00;
|
||||||
memset(instance->file_template, 0, sizeof(instance->file_template));
|
|
||||||
memset(instance->current_key, 0, sizeof(instance->current_key));
|
memset(instance->current_key, 0, sizeof(instance->current_key));
|
||||||
|
|
||||||
if(default_attack != SubBruteAttackLoadFile) {
|
if(default_attack != SubBruteAttackLoadFile) {
|
||||||
@@ -761,12 +367,6 @@ void subbrute_device_attack_set_default_values(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void subbrute_device_send_callback(SubBruteDevice* instance) {
|
|
||||||
if(instance->callback != NULL) {
|
|
||||||
instance->callback(instance->context, instance->state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||||
const char* result;
|
const char* result;
|
||||||
switch(error_id) {
|
switch(error_id) {
|
||||||
|
|||||||
@@ -31,19 +31,9 @@ typedef enum {
|
|||||||
SubBruteFileResultMissingOrIncorrectTe,
|
SubBruteFileResultMissingOrIncorrectTe,
|
||||||
} SubBruteFileResult;
|
} SubBruteFileResult;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubBruteDeviceStateIDLE,
|
|
||||||
SubBruteDeviceStateReady,
|
|
||||||
SubBruteDeviceStateTx,
|
|
||||||
SubBruteDeviceStateFinished
|
|
||||||
} SubBruteDeviceState;
|
|
||||||
|
|
||||||
typedef void (*SubBruteDeviceWorkerCallback)(void* context, SubBruteDeviceState state);
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SubBruteDeviceState state;
|
|
||||||
const SubBruteProtocol* protocol_info;
|
const SubBruteProtocol* protocol_info;
|
||||||
SubBruteProtocol* file_protocol_info;
|
SubBruteProtocol* file_protocol_info;
|
||||||
volatile bool worker_running;
|
|
||||||
|
|
||||||
// Current step
|
// Current step
|
||||||
uint64_t key_index;
|
uint64_t key_index;
|
||||||
@@ -51,28 +41,17 @@ typedef struct {
|
|||||||
uint8_t load_index;
|
uint8_t load_index;
|
||||||
|
|
||||||
// SubGhz
|
// SubGhz
|
||||||
FuriThread* thread;
|
|
||||||
SubGhzReceiver* receiver;
|
SubGhzReceiver* receiver;
|
||||||
SubGhzProtocolDecoderBase* decoder_result;
|
SubGhzProtocolDecoderBase* decoder_result;
|
||||||
SubGhzEnvironment* environment;
|
SubGhzEnvironment* environment;
|
||||||
SubGhzTransmitter* transmitter;
|
|
||||||
|
|
||||||
// Attack state
|
// Attack state
|
||||||
SubBruteAttacks attack;
|
SubBruteAttacks attack;
|
||||||
char file_template[SUBBRUTE_TEXT_STORE_SIZE];
|
|
||||||
|
|
||||||
uint64_t max_value;
|
uint64_t max_value;
|
||||||
|
|
||||||
// Loaded info for attack type
|
// Loaded info for attack type
|
||||||
char current_key[SUBBRUTE_PAYLOAD_SIZE];
|
char current_key[SUBBRUTE_PAYLOAD_SIZE];
|
||||||
char file_key[SUBBRUTE_MAX_LEN_NAME];
|
char file_key[SUBBRUTE_MAX_LEN_NAME];
|
||||||
|
|
||||||
// Manual transmit
|
|
||||||
uint32_t last_time_tx_data;
|
|
||||||
|
|
||||||
// Callback for changed states
|
|
||||||
SubBruteDeviceWorkerCallback callback;
|
|
||||||
void* context;
|
|
||||||
} SubBruteDevice;
|
} SubBruteDevice;
|
||||||
|
|
||||||
SubBruteDevice* subbrute_device_alloc();
|
SubBruteDevice* subbrute_device_alloc();
|
||||||
@@ -83,33 +62,9 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id);
|
|||||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type);
|
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type);
|
||||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
|
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
|
||||||
|
|
||||||
bool subbrute_device_is_worker_running(SubBruteDevice* instance);
|
|
||||||
SubBruteAttacks subbrute_device_get_attack(SubBruteDevice* instance);
|
|
||||||
uint64_t subbrute_device_get_max_value(SubBruteDevice* instance);
|
|
||||||
uint64_t subbrute_device_get_step(SubBruteDevice* instance);
|
|
||||||
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step);
|
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step);
|
||||||
void subbrute_device_set_load_index(SubBruteDevice* instance, uint64_t load_index);
|
|
||||||
void subbrute_device_reset_step(SubBruteDevice* instance);
|
|
||||||
const char* subbrute_device_get_file_key(SubBruteDevice* instance);
|
|
||||||
|
|
||||||
bool subbrute_worker_start(SubBruteDevice* instance);
|
|
||||||
void subbrute_worker_stop(SubBruteDevice* instance);
|
|
||||||
bool subbrute_device_transmit_current_key(SubBruteDevice* instance);
|
|
||||||
bool subbrute_device_can_manual_transmit(SubBruteDevice* instance);
|
|
||||||
void subbrute_device_set_callback(
|
|
||||||
SubBruteDevice* instance,
|
|
||||||
SubBruteDeviceWorkerCallback callback,
|
|
||||||
void* context);
|
|
||||||
|
|
||||||
void subbrute_device_free_protocol_info(SubBruteDevice* instance);
|
void subbrute_device_free_protocol_info(SubBruteDevice* instance);
|
||||||
int32_t subbrute_worker_thread(void* context);
|
|
||||||
void subbrute_device_attack_set_default_values(
|
void subbrute_device_attack_set_default_values(
|
||||||
SubBruteDevice* context,
|
SubBruteDevice* context,
|
||||||
SubBruteAttacks default_attack);
|
SubBruteAttacks default_attack);
|
||||||
bool subbrute_device_create_packet_parsed(
|
|
||||||
SubBruteDevice* instance,
|
|
||||||
FlipperFormat* flipper_format,
|
|
||||||
uint64_t step,
|
|
||||||
bool small);
|
|
||||||
void subbrute_device_send_callback(SubBruteDevice* instance);
|
|
||||||
void subbrute_device_subghz_transmit(SubBruteDevice* instance, FlipperFormat* flipper_format);
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "subbrute.h"
|
#include "subbrute.h"
|
||||||
#include "subbrute_device.h"
|
#include "subbrute_device.h"
|
||||||
|
#include "helpers/subbrute_worker.h"
|
||||||
#include "views/subbrute_attack_view.h"
|
#include "views/subbrute_attack_view.h"
|
||||||
#include "views/subbrute_main_view.h"
|
#include "views/subbrute_main_view.h"
|
||||||
|
|
||||||
@@ -62,9 +63,10 @@ struct SubBruteState {
|
|||||||
|
|
||||||
// SubBruteDevice
|
// SubBruteDevice
|
||||||
SubBruteDevice* device;
|
SubBruteDevice* device;
|
||||||
|
// SubBruteWorker
|
||||||
|
SubBruteWorker* worker;
|
||||||
};
|
};
|
||||||
|
|
||||||
void subbrute_show_loading_popup(void* context, bool show);
|
void subbrute_show_loading_popup(void* context, bool show);
|
||||||
void subbrute_text_input_callback(void* context);
|
void subbrute_text_input_callback(void* context);
|
||||||
void subbrute_popup_closed_callback(void* context);
|
void subbrute_popup_closed_callback(void* context);
|
||||||
uint64_t subbrute_get_step(void* context);
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "subbrute_protocols.h"
|
#include "subbrute_protocols.h"
|
||||||
|
|
||||||
|
#define TAG "SubBruteProtocols"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CAME 12bit 303MHz
|
* CAME 12bit 303MHz
|
||||||
*/
|
*/
|
||||||
@@ -201,6 +203,16 @@ static const char* subbrute_protocol_file_types[] = {
|
|||||||
[PrincetonFileProtocol] = "Princeton",
|
[PrincetonFileProtocol] = "Princeton",
|
||||||
[RAWFileProtocol] = "RAW"};
|
[RAWFileProtocol] = "RAW"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Values to not use less memory for packet parse operations
|
||||||
|
*/
|
||||||
|
static const char* subbrute_key_file_start_no_tail =
|
||||||
|
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\nKey: %s\nRepeat: %d\n";
|
||||||
|
static const char* subbrute_key_file_start_with_tail =
|
||||||
|
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||||
|
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\nRepeat: %d\nRepeat: %d\n";
|
||||||
|
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||||
|
|
||||||
const char* subbrute_protocol_name(SubBruteAttacks index) {
|
const char* subbrute_protocol_name(SubBruteAttacks index) {
|
||||||
return subbrute_protocol_names[index];
|
return subbrute_protocol_names[index];
|
||||||
}
|
}
|
||||||
@@ -236,3 +248,209 @@ SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) {
|
|||||||
|
|
||||||
return RAWFileProtocol;
|
return RAWFileProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuriString*
|
||||||
|
subbrute_protocol_default_payload(uint64_t step, 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);
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||||
|
#endif
|
||||||
|
FuriString* result;
|
||||||
|
|
||||||
|
if(te) {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_small_with_tail, bits, furi_string_get_cstr(candidate), te, repeat);
|
||||||
|
} else {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||||
|
}
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
furi_string_free(candidate);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuriString* subbrute_protocol_file_payload(
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t bits,
|
||||||
|
uint8_t te,
|
||||||
|
uint8_t repeat,
|
||||||
|
uint8_t load_index,
|
||||||
|
const char* file_key) {
|
||||||
|
FuriString* candidate = furi_string_alloc();
|
||||||
|
if(step >= sizeof(file_key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||||
|
#endif
|
||||||
|
FuriString* result;
|
||||||
|
|
||||||
|
if(te) {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_small_with_tail, bits, furi_string_get_cstr(candidate), te, repeat);
|
||||||
|
} else {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
furi_string_free(candidate);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuriString* subbrute_protocol_default_generate_file(
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset,
|
||||||
|
SubBruteFileProtocol file,
|
||||||
|
uint64_t step,
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||||
|
#endif
|
||||||
|
FuriString* result;
|
||||||
|
|
||||||
|
if(te) {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_file_start_with_tail,
|
||||||
|
frequency,
|
||||||
|
preset,
|
||||||
|
file,
|
||||||
|
bits,
|
||||||
|
furi_string_get_cstr(candidate),
|
||||||
|
te,
|
||||||
|
repeat);
|
||||||
|
} else {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_file_start_no_tail,
|
||||||
|
frequency,
|
||||||
|
preset,
|
||||||
|
file,
|
||||||
|
bits,
|
||||||
|
furi_string_get_cstr(candidate),
|
||||||
|
repeat);
|
||||||
|
}
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
furi_string_free(candidate);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuriString* subbrute_protocol_file_generate_file(
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset,
|
||||||
|
SubBruteFileProtocol file,
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t bits,
|
||||||
|
uint8_t te,
|
||||||
|
uint8_t repeat,
|
||||||
|
uint8_t load_index,
|
||||||
|
const char* file_key) {
|
||||||
|
FuriString* candidate = furi_string_alloc();
|
||||||
|
if(step >= sizeof(file_key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||||
|
#endif
|
||||||
|
FuriString* result;
|
||||||
|
|
||||||
|
if(te) {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_file_start_with_tail,
|
||||||
|
frequency,
|
||||||
|
preset,
|
||||||
|
file,
|
||||||
|
bits,
|
||||||
|
furi_string_get_cstr(candidate),
|
||||||
|
te,
|
||||||
|
repeat);
|
||||||
|
} else {
|
||||||
|
result = furi_string_alloc_printf(
|
||||||
|
subbrute_key_file_start_no_tail,
|
||||||
|
frequency,
|
||||||
|
preset,
|
||||||
|
file,
|
||||||
|
bits,
|
||||||
|
furi_string_get_cstr(candidate),
|
||||||
|
repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FURI_DEBUG
|
||||||
|
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
furi_string_free(candidate);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) {
|
||||||
|
uint64_t max_value;
|
||||||
|
if(attack_type == SubBruteAttackLoadFile) {
|
||||||
|
max_value = 0x3F;
|
||||||
|
} else {
|
||||||
|
FuriString* max_value_s;
|
||||||
|
max_value_s = furi_string_alloc();
|
||||||
|
for(uint8_t i = 0; i < bits; i++) {
|
||||||
|
furi_string_cat_printf(max_value_s, "1");
|
||||||
|
}
|
||||||
|
max_value = (uint64_t)strtol(furi_string_get_cstr(max_value_s), NULL, 2);
|
||||||
|
furi_string_free(max_value_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_value;
|
||||||
|
}
|
||||||
@@ -55,3 +55,32 @@ const char* subbrute_protocol_file(SubBruteFileProtocol protocol);
|
|||||||
FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name);
|
FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name);
|
||||||
SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name);
|
SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name);
|
||||||
const char* subbrute_protocol_name(SubBruteAttacks index);
|
const char* subbrute_protocol_name(SubBruteAttacks index);
|
||||||
|
|
||||||
|
FuriString*
|
||||||
|
subbrute_protocol_default_payload(uint64_t step, uint8_t bits, uint8_t te, uint8_t repeat);
|
||||||
|
FuriString* subbrute_protocol_file_payload(
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t bits,
|
||||||
|
uint8_t te,
|
||||||
|
uint8_t repeat,
|
||||||
|
uint8_t load_index,
|
||||||
|
const char* file_key);
|
||||||
|
FuriString* subbrute_protocol_default_generate_file(
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset,
|
||||||
|
SubBruteFileProtocol file,
|
||||||
|
uint64_t step,
|
||||||
|
uint8_t bits,
|
||||||
|
uint8_t te,
|
||||||
|
uint8_t repeat);
|
||||||
|
FuriString* subbrute_protocol_file_generate_file(
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset,
|
||||||
|
SubBruteFileProtocol file,
|
||||||
|
uint64_t step,
|
||||||
|
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);
|
||||||
@@ -227,10 +227,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
#ifdef FURI_DEBUG
|
#ifdef FURI_DEBUG
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubBruteMainViewModel * model) {
|
instance->view, SubBruteMainViewModel * model, { index = model->index; }, false);
|
||||||
index = model->index;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
FURI_LOG_I(TAG, "Index: %d", index);
|
FURI_LOG_I(TAG, "Index: %d", index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -265,10 +262,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
#ifdef FURI_DEBUG
|
#ifdef FURI_DEBUG
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view, (SubBruteMainViewModel * model) {
|
instance->view, SubBruteMainViewModel * model, { index = model->index; }, false);
|
||||||
index = model->index;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
FURI_LOG_I(TAG, "Index: %d", index);
|
FURI_LOG_I(TAG, "Index: %d", index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user