diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.c b/applications/plugins/subbrute/helpers/subbrute_worker.c index 01df8c4ba..596240ded 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.c +++ b/applications/plugins/subbrute/helpers/subbrute_worker.c @@ -1,126 +1,185 @@ -#include "subbrute_worker.h" - -#include -#include +#include "subbrute_worker_private.h" +#include +#include +#include #include -#include #define TAG "SubBruteWorker" - -struct SubBruteWorker { - SubGhzTxRxWorker* subghz_txrx; - volatile bool worker_running; - volatile bool worker_manual_mode; - bool is_manual_init; - bool is_continuous_worker; - - SubGhzEnvironment* environment; - SubGhzTransmitter* transmitter; - FlipperFormat* flipper_format; - - uint32_t last_time_tx_data; - - // Preset and frequency needed - FuriHalSubGhzPreset preset; - uint32_t frequency; - FuriString* protocol_name; - - //SubBruteWorkerCallback callback; - //void* context; -}; - -/** Taken from subghz_tx_rx_worker.c */ -#define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048 -#define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60 -#define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40 #define SUBBRUTE_TX_TIMEOUT 5 -#define SUBBRUTE_SEND_DELAY 20 +#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400 SubBruteWorker* subbrute_worker_alloc() { SubBruteWorker* instance = malloc(sizeof(SubBruteWorker)); - //instance->status = SubBruteWorkerStatusIDLE; + instance->state = SubBruteWorkerStateIDLE; + instance->step = 0; instance->worker_running = false; - instance->worker_manual_mode = false; + instance->initiated = false; + instance->last_time_tx_data = 0; + instance->load_index = 0; - //instance->environment = subghz_environment_alloc(); + 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(); - instance->flipper_format = flipper_format_string_alloc(); - instance->protocol_name = furi_string_alloc(); - - // SubGhzTxRxWorker - instance->subghz_txrx = subghz_tx_rx_worker_alloc(); + instance->transmit_mode = false; return instance; } void subbrute_worker_free(SubBruteWorker* instance) { furi_assert(instance); - furi_assert(!instance->worker_running); + + // I don't know how to free this + instance->decoder_result = NULL; if(instance->transmitter != NULL) { subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; } - /*if(instance->environment != NULL) { - subghz_environment_free(instance->environment); - instance->environment = NULL; - }*/ + subghz_environment_free(instance->environment); + instance->environment = NULL; - flipper_format_free(instance->flipper_format); - - furi_string_free(instance->protocol_name); - - // SubGhzTxRxWorker - subghz_tx_rx_worker_free(instance->subghz_txrx); + furi_thread_free(instance->thread); free(instance); } -bool subbrute_worker_start( - SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name) { - furi_assert(instance); +uint64_t subbrute_worker_get_step(SubBruteWorker* instance) { + return instance->step; +} - if(instance->worker_manual_mode) { - FURI_LOG_W(TAG, "Invalid mode for starting worker!"); +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->frequency = frequency; - instance->preset = preset; + instance->step = step; - furi_string_free(instance->protocol_name); - instance->protocol_name = furi_string_alloc_printf("%s", protocol_name); + return true; +} - bool res = false; +bool subbrute_worker_init_default_attack( + SubBruteWorker* instance, + SubBruteAttacks attack_type, + uint64_t step, + const SubBruteProtocol* protocol) { + furi_assert(instance); - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_preset(instance->preset); - - furi_hal_subghz_set_frequency_and_path(instance->frequency); - furi_hal_subghz_flush_rx(); - - //if(furi_hal_subghz_is_tx_allowed(frequency)) { - instance->frequency = frequency; - res = true; - //} - instance->worker_running = res; - -#ifdef FURI_DEBUG - FURI_LOG_I(TAG, "Frequency: %ld", frequency); -#endif - instance->preset = preset; - if(res) { - instance->worker_running = res = - subghz_tx_rx_worker_start(instance->subghz_txrx, frequency); + if(instance->worker_running) { + FURI_LOG_W(TAG, "Init Worker when it's running"); + subbrute_worker_stop(instance); } - return res; + + instance->attack = attack_type; + instance->frequency = protocol->frequency; + instance->preset = protocol->preset; + instance->file = protocol->file; + instance->step = step; + instance->bits = protocol->bits; + instance->te = protocol->te; + instance->repeat = protocol->repeat; + instance->load_index = 0; + instance->file_key = NULL; + instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits); + + instance->initiated = true; + instance->state = SubBruteWorkerStateReady; + subbrute_worker_send_callback(instance); +#ifdef FURI_DEBUG + FURI_LOG_I( + TAG, + "subbrute_worker_init_default_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld", + subbrute_protocol_name(instance->attack), + instance->bits, + subbrute_protocol_preset(instance->preset), + subbrute_protocol_file(instance->file), + instance->te, + instance->repeat, + instance->max_value); +#endif + + 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->step = step; + instance->bits = protocol->bits; + instance->te = protocol->te; + instance->load_index = load_index; + instance->repeat = protocol->repeat; + instance->file_key = file_key; + instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits); + + instance->initiated = true; + instance->state = SubBruteWorkerStateReady; + subbrute_worker_send_callback(instance); +#ifdef FURI_DEBUG + FURI_LOG_I( + TAG, + "subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld", + subbrute_protocol_name(instance->attack), + instance->bits, + subbrute_protocol_preset(instance->preset), + subbrute_protocol_file(instance->file), + instance->te, + instance->repeat, + instance->max_value); +#endif + + 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) { @@ -128,204 +187,122 @@ void subbrute_worker_stop(SubBruteWorker* instance) { instance->worker_running = false; - if(subghz_tx_rx_worker_is_running(instance->subghz_txrx)) { - subghz_tx_rx_worker_stop(instance->subghz_txrx); - } -} - -void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker) { - furi_assert(instance); - - instance->is_continuous_worker = is_continuous_worker; -} - -bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance) { - furi_assert(instance); - - return instance->is_continuous_worker; -} - -bool subbrute_worker_is_running(SubBruteWorker* instance) { - furi_assert(instance); - - return instance->worker_running; -} - -bool subbrute_worker_can_transmit(SubBruteWorker* instance) { - furi_assert(instance); - - return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY; -} - -bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed) { - furi_assert(instance); - - if(is_button_pressed) { - // It's human pressed, trying to reset twice pressing - return !instance->worker_manual_mode && - (furi_get_tick() - instance->last_time_tx_data) > 500; - } else { - return !instance->worker_manual_mode; - } -} - -bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) { - furi_assert(instance); - furi_assert(instance->worker_running); - - if(!subbrute_worker_can_transmit(instance)) { - FURI_LOG_E(TAG, "Too early to transmit"); - - return false; - } - instance->last_time_tx_data = furi_get_tick(); - -#ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "payload: %s", payload); -#endif - - while(!subghz_tx_rx_worker_write(instance->subghz_txrx, (uint8_t*)payload, strlen(payload))) { - furi_delay_ms(10); - } - - furi_hal_subghz_flush_tx(); - // Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); - // stream_clean(stream); - // stream_write_cstring(stream, payload); - // subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); - - return true; -} - -// Init MANUAL -bool subbrute_worker_init_manual_transmit( - SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name) { -#ifdef FURI_DEBUG - FURI_LOG_D( - TAG, - "subbrute_worker_init_manual_transmit. frequency: %ld, protocol: %s", - frequency, - protocol_name); -#endif - if(instance->worker_manual_mode || !subbrute_worker_can_manual_transmit(instance, false) || - instance->worker_running) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "cannot transmit"); -#endif - return false; - } - if(instance->worker_running) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_worker_stop"); -#endif - subbrute_worker_stop(instance); - } - - // Not transmit at this period - instance->worker_manual_mode = true; - - if(instance->is_manual_init) { - FURI_LOG_E(TAG, "Trying to setup without normally shutdown prev transmit session!"); - subbrute_worker_manual_transmit_stop(instance); - } - - instance->preset = preset; - instance->frequency = frequency; - - furi_string_free(instance->protocol_name); - instance->protocol_name = furi_string_alloc_printf("%s", protocol_name); - - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_preset(instance->preset); - - furi_hal_subghz_set_frequency_and_path(instance->frequency); - furi_hal_subghz_flush_rx(); - - /*if(!furi_hal_subghz_is_tx_allowed(frequency)) { - FURI_LOG_E(TAG, "Frequency: %d invalid!", frequency); - - instance->frequency = frequency; - instance->worker_manual_mode = false; - return false; - }*/ - -#ifdef FURI_DEBUG - FURI_LOG_I(TAG, "Frequency: %ld", frequency); -#endif - - instance->transmitter = subghz_transmitter_alloc_init( - instance->environment, furi_string_get_cstr(instance->protocol_name)); - - furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(instance->preset); - instance->frequency = furi_hal_subghz_set_frequency_and_path(frequency); + furi_thread_join(instance->thread); furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); furi_hal_subghz_sleep(); - subghz_transmitter_free(instance->transmitter); - instance->transmitter = NULL; - - instance->worker_manual_mode = false; - instance->is_manual_init = true; - - return true; } -void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_worker_manual_transmit_stop"); -#endif - if(!instance->is_manual_init) { - return; +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; } - furi_hal_subghz_idle(); - furi_hal_subghz_sleep(); + 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->step = step; + + bool result; + instance->protocol_name = subbrute_protocol_file(instance->file); + FlipperFormat* flipper_format = flipper_format_string_alloc(); + Stream* stream = flipper_format_get_raw_stream(flipper_format); + + stream_clean(stream); + + if(instance->attack == SubBruteAttackLoadFile) { + subbrute_protocol_file_payload( + stream, + step, + instance->bits, + instance->te, + instance->repeat, + instance->load_index, + instance->file_key); + } else { + subbrute_protocol_default_payload( + stream, 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) { + while(instance->transmit_mode) { + furi_delay_ms(SUBBRUTE_TX_TIMEOUT); + } + instance->transmit_mode = true; if(instance->transmitter != NULL) { subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; } - - instance->is_manual_init = false; -} - -bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload) { - furi_assert(instance); - - if(instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "cannot transmit"); -#endif - return false; - } - if(instance->worker_running) { - FURI_LOG_W(TAG, "Worker was working for manual mode. Shutdown thread"); - subbrute_worker_stop(instance); - } - if(!instance->is_manual_init) { - FURI_LOG_E(TAG, "Manually transmit doesn't set!"); - return false; - } - - instance->last_time_tx_data = furi_get_tick(); - instance->worker_manual_mode = true; - - Stream* stream = flipper_format_get_raw_stream(instance->flipper_format); - stream_clean(stream); - stream_write_cstring(stream, payload); - - instance->transmitter = subghz_transmitter_alloc_init( - instance->environment, furi_string_get_cstr(instance->protocol_name)); - subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format); + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, instance->protocol_name); + subghz_transmitter_deserialize(instance->transmitter, flipper_format); furi_hal_subghz_reset(); furi_hal_subghz_load_preset(instance->preset); - instance->frequency = furi_hal_subghz_set_frequency_and_path(instance->frequency); - + 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()) { @@ -338,9 +315,100 @@ bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* paylo subghz_transmitter_free(instance->transmitter); instance->transmitter = NULL; - stream_clean(stream); + instance->transmit_mode = false; +} - instance->worker_manual_mode = false; +void subbrute_worker_send_callback(SubBruteWorker* instance) { + if(instance->callback != NULL) { + instance->callback(instance->context, instance->state); + } +} - return true; -} \ No newline at end of file +/** + * 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); + + instance->protocol_name = subbrute_protocol_file(instance->file); + + FlipperFormat* flipper_format = flipper_format_string_alloc(); + Stream* stream = flipper_format_get_raw_stream(flipper_format); + + while(instance->worker_running) { + stream_clean(stream); + if(instance->attack == SubBruteAttackLoadFile) { + subbrute_protocol_file_payload( + stream, + instance->step, + instance->bits, + instance->te, + instance->repeat, + instance->load_index, + instance->file_key); + } else { + subbrute_protocol_default_payload( + stream, instance->step, instance->bits, instance->te, instance->repeat); + } +#ifdef FURI_DEBUG + //FURI_LOG_I(TAG, "Payload: %s", furi_string_get_cstr(payload)); + //furi_delay_ms(SUBBRUTE_MANUAL_TRANSMIT_INTERVAL / 4); +#endif + + // size_t written = stream_write_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->step + 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->step++; + + // 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; +} diff --git a/applications/plugins/subbrute/helpers/subbrute_worker.h b/applications/plugins/subbrute/helpers/subbrute_worker.h index d96fbdde2..3a514272b 100644 --- a/applications/plugins/subbrute/helpers/subbrute_worker.h +++ b/applications/plugins/subbrute/helpers/subbrute_worker.h @@ -1,39 +1,39 @@ #pragma once -#include - -typedef struct SubBruteWorker SubBruteWorker; -/** - * Same like SubGhzTxRxWorkerStatus in subghz_tx_rx_worker.h - * using just to not include that file +#include "../subbrute_protocols.h" typedef enum { - SubBruteWorkerStatusIDLE, - SubBruteWorkerStatusTx, - // SubBruteWorkerStatusRx, -} SubBruteWorkerStatus; + SubBruteWorkerStateIDLE, + SubBruteWorkerStateReady, + SubBruteWorkerStateTx, + SubBruteWorkerStateFinished +} SubBruteWorkerState; + +typedef void (*SubBruteWorkerCallback)(void* context, SubBruteWorkerState state); + +typedef struct SubBruteWorker SubBruteWorker; -//typedef void (*SubBruteWorkerCallback)(SubBruteWorkerStatus event, void* context); -*/ SubBruteWorker* subbrute_worker_alloc(); void subbrute_worker_free(SubBruteWorker* instance); -bool subbrute_worker_start( - SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name); -void subbrute_worker_stop(SubBruteWorker* instance); -bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance); -void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker); -//bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size); +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_can_transmit(SubBruteWorker* instance); -bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed); -bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload); -bool subbrute_worker_init_manual_transmit( +bool subbrute_worker_init_default_attack( SubBruteWorker* instance, - uint32_t frequency, - FuriHalSubGhzPreset preset, - const char* protocol_name); -bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload); -void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance); \ No newline at end of file + 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); \ No newline at end of file diff --git a/applications/plugins/subbrute/helpers/subbrute_worker_private.h b/applications/plugins/subbrute/helpers/subbrute_worker_private.h new file mode 100644 index 000000000..cebda8585 --- /dev/null +++ b/applications/plugins/subbrute/helpers/subbrute_worker_private.h @@ -0,0 +1,47 @@ +#pragma once + +#include "subbrute_worker.h" +#include +#include +#include +#include + +struct SubBruteWorker { + SubBruteWorkerState state; + volatile bool worker_running; + volatile bool initiated; + volatile bool transmit_mode; + + // Current step + uint64_t step; + + // SubGhz + FuriThread* thread; + SubGhzProtocolDecoderBase* decoder_result; + SubGhzEnvironment* environment; + SubGhzTransmitter* transmitter; + const char* protocol_name; + + // 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); \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c index d7d64bc46..84df3e4e5 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c @@ -1,6 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" -#include +#include "subbrute_scene.h" #define TAG "SubBruteSceneLoadFile" @@ -35,12 +34,20 @@ void subbrute_scene_load_file_on_enter(void* context) { furi_string_get_cstr(app_folder)); #endif if(res) { - load_result = subbrute_device_load_from_file(instance->device, load_path); + load_result = + subbrute_device_load_from_file(instance->device, furi_string_get_cstr(load_path)); if(load_result == SubBruteFileResultOk) { load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile); 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! - instance->device->state = SubBruteDeviceStateReady; FURI_LOG_I(TAG, "Ready to run"); res = true; } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c index e3774e407..77db3f64b 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c @@ -1,6 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" -#include "../views/subbrute_main_view.h" +#include "subbrute_scene.h" #define TAG "SubBruteSceneStart" @@ -8,9 +7,6 @@ void subbrute_scene_load_select_callback(SubBruteCustomEvent event, void* contex furi_assert(context); SubBruteState* instance = (SubBruteState*)context; -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_scene_load_select_callback"); -#endif view_dispatcher_send_custom_event(instance->view_dispatcher, event); } @@ -43,9 +39,14 @@ bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeIndexSelected) { instance->device->load_index = subbrute_main_view_get_index(instance->view_main); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "load_index: %d", instance->device->load_index); -#endif + 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); consumed = true; } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c index 3521b30e8..e632b0cf2 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_run_attack.c @@ -1,7 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" -#include "../views/subbrute_attack_view.h" -#include "../helpers/subbrute_worker.h" +#include "subbrute_scene.h" #define TAG "SubBruteSceneRunAttack" @@ -12,56 +10,25 @@ static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void* view_dispatcher_send_custom_event(instance->view_dispatcher, event); } -//static void subbrute_scene_run_attack_worker_callback(void* context) { -// SubBruteState* instance = (SubBruteState*)context; -// -// if(instance->locked || instance->device->key_index + 1 > instance->device->max_value) { -// return; -// } -// instance->locked = true; -// -// if(subbrute_worker_can_manual_transmit(instance->worker)) { -// // Blink -// notification_message(instance->notifications, &sequence_blink_yellow_100); -// subbrute_device_create_packet_parsed(instance->device, instance->device->key_index, true); -// -//#ifdef FURI_DEBUG -// FURI_LOG_I(TAG, "subbrute_worker_manual_transmit"); -//#endif -// if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) { -//#ifdef FURI_DEBUG -// FURI_LOG_I(TAG, "transmit ok"); -//#endif -// // Make payload for new iteration or exit -// if(instance->device->key_index + 1 <= instance->device->max_value) { -// instance->device->key_index++; -// } else { -// view_dispatcher_send_custom_event( -// instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished); -// } -// } -// -// // Stop -// notification_message(instance->notifications, &sequence_blink_stop); -// } -// -// instance->locked = false; -// subbrute_attack_view_set_current_step(instance->view_attack, instance->device->key_index); -//} +static void + subbrute_scene_run_attack_device_state_changed(void* context, SubBruteWorkerState state) { + furi_assert(context); + SubBruteState* instance = (SubBruteState*)context; + + if(state == SubBruteWorkerStateIDLE) { + // Can't be IDLE on this step! + view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError); + } else if(state == SubBruteWorkerStateFinished) { + view_dispatcher_send_custom_event( + instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished); + } +} void subbrute_scene_run_attack_on_exit(void* context) { furi_assert(context); SubBruteState* instance = (SubBruteState*)context; - // SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state( - // instance->scene_manager, SubBruteSceneRunAttack); - // furi_assert(state); - // - // furi_timer_free(state->timer); - // free(state); - if(subbrute_worker_get_continuous_worker(instance->worker)) { - subbrute_worker_stop(instance->worker); - } + subbrute_worker_stop(instance->worker); notification_message(instance->notifications, &sequence_blink_stop); } @@ -70,124 +37,67 @@ void subbrute_scene_run_attack_on_enter(void* context) { furi_assert(context); SubBruteState* instance = (SubBruteState*)context; SubBruteAttackView* view = instance->view_attack; - // - // SubBruteAttackState* state = malloc(sizeof(SubBruteAttackState)); - // scene_manager_set_scene_state( - // instance->scene_manager, SubBruteSceneRunAttack, (uint32_t)state); instance->current_view = SubBruteViewAttack; subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); - subbrute_attack_view_init_values( - view, - (uint8_t)instance->device->attack, - instance->device->max_value, - instance->device->key_index, - true); + subbrute_worker_set_callback( + instance->worker, subbrute_scene_run_attack_device_state_changed, instance); - if(subbrute_worker_get_continuous_worker(instance->worker)) { - // Init Continuous worker with values! - if(!subbrute_worker_start( - instance->worker, - instance->device->frequency, - instance->device->preset, - furi_string_get_cstr(instance->device->protocol_name))) { - FURI_LOG_W(TAG, "Worker Continuous init failed!"); + if(!subbrute_worker_is_running(instance->worker)) { + subbrute_worker_set_step(instance->worker, instance->device->key_index); + if(!subbrute_worker_start(instance->worker)) { + view_dispatcher_send_custom_event( + instance->view_dispatcher, SubBruteCustomEventTypeError); + } else { + notification_message(instance->notifications, &sequence_single_vibro); + notification_message(instance->notifications, &sequence_blink_start_yellow); } - } else { - // Init worker with values - if(!subbrute_worker_init_manual_transmit( - instance->worker, - instance->device->frequency, - instance->device->preset, - furi_string_get_cstr(instance->device->protocol_name))) { - FURI_LOG_W(TAG, "Worker init failed!"); - } - - // state->timer = furi_timer_alloc( - // subbrute_scene_run_attack_worker_callback, FuriTimerTypePeriodic, instance); - // furi_timer_start(state->timer, pdMS_TO_TICKS(100)); // 20 ms } } bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) { SubBruteState* instance = (SubBruteState*)context; - // SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state( - // instance->scene_manager, SubBruteSceneRunAttack); - // furi_assert(state); + SubBruteAttackView* view = instance->view_attack; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - SubBruteAttackView* view = instance->view_attack; + uint64_t step = subbrute_worker_get_step(instance->worker); + instance->device->key_index = step; + subbrute_attack_view_set_current_step(view, step); - if(event.event == SubBruteCustomEventTypeTransmitNotStarted || - event.event == SubBruteCustomEventTypeTransmitFinished || - event.event == SubBruteCustomEventTypeBackPressed) { - // furi_timer_stop(state->timer); - // Stop transmit + if(event.event == SubBruteCustomEventTypeTransmitFinished) { notification_message(instance->notifications, &sequence_display_backlight_on); - notification_message(instance->notifications, &sequence_single_vibro); - subbrute_attack_view_set_current_step(view, instance->device->key_index); + notification_message(instance->notifications, &sequence_double_vibro); + + + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + } else if( + event.event == SubBruteCustomEventTypeTransmitNotStarted || + event.event == SubBruteCustomEventTypeBackPressed) { + if (subbrute_worker_is_running(instance->worker)) { + // Notify + notification_message(instance->notifications, &sequence_single_vibro); + } + // Stop transmit + scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneSetupAttack); + } else if(event.event == SubBruteCustomEventTypeError) { + notification_message(instance->notifications, &sequence_error); + + // Stop transmit scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, SubBruteSceneSetupAttack); - consumed = true; } else if(event.event == SubBruteCustomEventTypeUpdateView) { - subbrute_attack_view_set_current_step(view, instance->device->key_index); + //subbrute_attack_view_set_current_step(view, instance->device->key_index); } + consumed = true; } else if(event.type == SceneManagerEventTypeTick) { - if(subbrute_worker_get_continuous_worker(instance->worker)) { - if(subbrute_worker_can_transmit(instance->worker)) { - // Blink - notification_message(instance->notifications, &sequence_blink_yellow_100); - - subbrute_device_create_packet_parsed( - instance->device, instance->device->key_index, true); - - if(subbrute_worker_transmit(instance->worker, instance->device->payload)) { - // Make payload for new iteration or exit - if(instance->device->key_index + 1 > instance->device->max_value) { - // End of list - view_dispatcher_send_custom_event( - instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished); - } else { - instance->device->key_index++; - view_dispatcher_send_custom_event( - instance->view_dispatcher, SubBruteCustomEventTypeUpdateView); - //subbrute_attack_view_set_current_step(view, instance->device->key_index); - } - } - - // Stop - notification_message(instance->notifications, &sequence_blink_stop); - } - } else { - if(subbrute_worker_can_manual_transmit(instance->worker, false)) { - // Blink - notification_message(instance->notifications, &sequence_blink_yellow_100); - - subbrute_device_create_packet_parsed( - instance->device, instance->device->key_index, true); - - if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) { - // Make payload for new iteration or exit - if(instance->device->key_index + 1 > instance->device->max_value) { - // End of list - view_dispatcher_send_custom_event( - instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished); - } else { - instance->device->key_index++; - view_dispatcher_send_custom_event( - instance->view_dispatcher, SubBruteCustomEventTypeUpdateView); - //subbrute_attack_view_set_current_step(view, instance->device->key_index); - } - } - - // Stop - notification_message(instance->notifications, &sequence_blink_stop); - } - } + uint64_t step = subbrute_worker_get_step(instance->worker); + instance->device->key_index = step; + subbrute_attack_view_set_current_step(view, step); consumed = true; } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c index 44b790c3d..b5919ae5a 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_name.c @@ -1,34 +1,30 @@ -#include -#include -#include -#include - #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" +#include "subbrute_scene.h" +#include #define TAG "SubBruteSceneSaveFile" void subbrute_scene_save_name_on_enter(void* context) { SubBruteState* instance = (SubBruteState*)context; - SubBruteDevice* device = instance->device; // Setup view TextInput* text_input = instance->text_input; - set_random_name(device->text_store, sizeof(device->text_store)); + set_random_name(instance->text_store, sizeof(instance->text_store)); text_input_set_header_text(text_input, "Name of file"); text_input_set_result_callback( text_input, subbrute_text_input_callback, instance, - device->text_store, + instance->text_store, SUBBRUTE_MAX_LEN_NAME, true); - furi_string_set(device->load_path, SUBBRUTE_PATH); + furi_string_reset(instance->file_path); + furi_string_set_str(instance->file_path, SUBBRUTE_PATH); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - furi_string_get_cstr(device->load_path), SUBBRUTE_FILE_EXT, ""); + furi_string_get_cstr(instance->file_path), SUBBRUTE_FILE_EXT, ""); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewTextInput); @@ -45,18 +41,15 @@ bool subbrute_scene_save_name_on_event(void* context, SceneManagerEvent event) { event.type == SceneManagerEventTypeCustom && event.event == SubBruteCustomEventTypeTextEditDone) { #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Saving: %s", instance->device->text_store); + FURI_LOG_D(TAG, "Saving: %s", instance->text_store); #endif bool success = false; - if(strcmp(instance->device->text_store, "")) { + if(strcmp(instance->text_store, "")) { + furi_string_reset(instance->file_path); furi_string_cat_printf( - instance->device->load_path, - "/%s%s", - instance->device->text_store, - SUBBRUTE_FILE_EXT); + instance->file_path, "%s/%s%s", SUBBRUTE_PATH, instance->text_store, SUBBRUTE_FILE_EXT); - if(subbrute_device_save_file( - instance->device, furi_string_get_cstr(instance->device->load_path))) { + if(subbrute_device_save_file(instance->device, furi_string_get_cstr(instance->file_path))) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveSuccess); success = true; consumed = true; @@ -82,5 +75,5 @@ void subbrute_scene_save_name_on_exit(void* context) { text_input_reset(instance->text_input); - furi_string_reset(instance->device->load_path); + furi_string_reset(instance->file_path); } diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c index f83c0c0fe..20b1a0de4 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_save_success.c @@ -1,5 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" +#include "subbrute_scene.h" void subbrute_scene_save_success_on_enter(void* context) { furi_assert(context); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c index c41954e7d..4984b4931 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_setup_attack.c @@ -1,6 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" -#include "../views/subbrute_attack_view.h" +#include "subbrute_scene.h" #define TAG "SubBruteSceneSetupAttack" @@ -11,6 +10,18 @@ static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void view_dispatcher_send_custom_event(instance->view_dispatcher, event); } +static void + subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteWorkerState state) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; + + if(state == SubBruteWorkerStateIDLE) { + // Can't be IDLE on this step! + view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError); + } +} + void subbrute_scene_setup_attack_on_enter(void* context) { furi_assert(context); SubBruteState* instance = (SubBruteState*)context; @@ -20,6 +31,14 @@ void subbrute_scene_setup_attack_on_enter(void* context) { FURI_LOG_D(TAG, "Enter Attack: %d", instance->device->attack); #endif + subbrute_worker_set_callback( + instance->worker, subbrute_scene_setup_attack_device_state_changed, context); + + if(subbrute_worker_is_running(instance->worker)) { + instance->device->key_index = subbrute_worker_get_step(instance->worker); + subbrute_worker_stop(instance->worker); + } + subbrute_attack_view_init_values( view, instance->device->attack, @@ -27,14 +46,6 @@ void subbrute_scene_setup_attack_on_enter(void* context) { instance->device->key_index, false); - if(!subbrute_worker_init_manual_transmit( - instance->worker, - instance->device->frequency, - instance->device->preset, - furi_string_get_cstr(instance->device->protocol_name))) { - FURI_LOG_W(TAG, "Worker init failed!"); - } - instance->current_view = SubBruteViewAttack; subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); @@ -46,7 +57,7 @@ void subbrute_scene_setup_attack_on_exit(void* context) { FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit"); #endif SubBruteState* instance = (SubBruteState*)context; - subbrute_worker_manual_transmit_stop(instance->worker); + subbrute_worker_stop(instance->worker); notification_message(instance->notifications, &sequence_blink_stop); } @@ -57,17 +68,9 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubBruteCustomEventTypeTransmitStarted) { - subbrute_worker_set_continuous_worker(instance->worker, false); subbrute_attack_view_set_worker_type(view, false); scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); - } else if(event.event == SubBruteCustomEventTypeTransmitContinuousStarted) { - // Setting different type of worker - subbrute_worker_set_continuous_worker(instance->worker, true); - subbrute_attack_view_set_worker_type(view, true); - scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack); } else if(event.event == SubBruteCustomEventTypeSaveFile) { - subbrute_worker_manual_transmit_stop(instance->worker); - subbrute_attack_view_init_values( view, instance->device->attack, @@ -76,11 +79,6 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event false); scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName); } else if(event.event == SubBruteCustomEventTypeBackPressed) { -#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, @@ -88,98 +86,49 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event instance->device->key_index, false); scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); - } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { - // +1 - if((instance->device->key_index + 1) - instance->device->max_value == 1) { - instance->device->key_index = 0x00; - } else { - uint64_t value = instance->device->key_index + 1; - if(value == instance->device->max_value) { - instance->device->key_index = value; - } else { - instance->device->key_index = value % instance->device->max_value; - } - } - subbrute_attack_view_set_current_step(view, instance->device->key_index); - } else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) { - // +50 - uint64_t value = instance->device->key_index + 50; - if(value == instance->device->max_value) { - instance->device->key_index += value; - } else { - instance->device->key_index = value % instance->device->max_value; - } - subbrute_attack_view_set_current_step(view, instance->device->key_index); - } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { - // -1 - if(instance->device->key_index - 1 == 0) { - instance->device->key_index = 0x00; - } else if(instance->device->key_index == 0) { - instance->device->key_index = instance->device->max_value; - } else { - uint64_t value = ((instance->device->key_index - 1) + instance->device->max_value); - if(value == instance->device->max_value) { - instance->device->key_index = value; - } else { - instance->device->key_index = value % instance->device->max_value; - } - } - subbrute_attack_view_set_current_step(view, instance->device->key_index); - } else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) { - // -50 - uint64_t value = ((instance->device->key_index - 50) + instance->device->max_value); - if(value == instance->device->max_value) { - instance->device->key_index = value; - } else { - instance->device->key_index = value % instance->device->max_value; - } - subbrute_attack_view_set_current_step(view, instance->device->key_index); + } else if(event.event == SubBruteCustomEventTypeError) { + notification_message(instance->notifications, &sequence_error); } else if(event.event == SubBruteCustomEventTypeTransmitCustom) { - if(subbrute_worker_can_manual_transmit(instance->worker, true)) { + // We can transmit only in not working states + if(subbrute_worker_can_manual_transmit(instance->worker)) { + // MANUAL Transmit! // 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, - // furi_string_get_cstr(instance->device->protocol_name)); - // } - subbrute_device_create_packet_parsed( - instance->device, instance->device->key_index, false); - subbrute_worker_manual_transmit(instance->worker, instance->device->payload); - + subbrute_worker_transmit_current_key( + instance->worker, instance->device->key_index); // Stop notification_message(instance->notifications, &sequence_blink_stop); } + } else if(event.event == SubBruteCustomEventTypeChangeStepUp) { + // +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); + } else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) { + // +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); + } else if(event.event == SubBruteCustomEventTypeChangeStepDown) { + // -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); + } else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) { + // -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); } + consumed = true; + } else if(event.type == SceneManagerEventTypeTick) { + 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; } - // if(event.type == SceneManagerEventTypeCustom) { - // switch(event.event) { - // case SubBruteCustomEventTypeMenuSelected: - // with_view_model( - // view, (SubBruteMainViewModel * model) { - // instance->menu_index = model->index; - // return false; - // }); - // scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); - // consumed = true; - // break; - // case SubBruteCustomEventTypeLoadFile: - // with_view_model( - // view, (SubBruteMainViewModel * model) { - // instance->menu_index = model->index; - // return false; - // }); - // scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); - // consumed = true; - // break; - // } - // } - return consumed; -} \ No newline at end of file +} diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index 9c572db3c..677b1ef20 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -1,6 +1,5 @@ #include "../subbrute_i.h" -#include "../subbrute_custom_event.h" -#include "../views/subbrute_main_view.h" +#include "subbrute_scene.h" #define TAG "SubBruteSceneStart" @@ -42,12 +41,24 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Event: %ld", event.event); + FURI_LOG_D( + TAG, + "Event: %ld, SubBruteCustomEventTypeMenuSelected: %s, SubBruteCustomEventTypeLoadFile: %s", + event.event, + event.event == SubBruteCustomEventTypeMenuSelected ? "true" : "false", + event.event == SubBruteCustomEventTypeLoadFile ? "true" : "false"); #endif if(event.event == SubBruteCustomEventTypeMenuSelected) { 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); consumed = true; diff --git a/applications/plugins/subbrute/subbrute.c b/applications/plugins/subbrute/subbrute.c index f969ee13d..aaab3aeb1 100644 --- a/applications/plugins/subbrute/subbrute.c +++ b/applications/plugins/subbrute/subbrute.c @@ -1,56 +1,9 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "subbrute.h" #include "subbrute_i.h" #include "subbrute_custom_event.h" +#include "scenes/subbrute_scene.h" #define TAG "SubBruteApp" -static const char* subbrute_menu_names[] = { - [SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz", - [SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz", - [SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz", - [SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz", - [SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz", - [SubBruteAttackNICE12bit868] = "NICE 12bit 868MHz", - [SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz", - [SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz", - [SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz", - [SubBruteAttackLinear10bit300] = "Linear 10bit 300MHz", - [SubBruteAttackLinear10bit310] = "Linear 10bit 310MHz", - [SubBruteAttackLoadFile] = "BF existing dump", - [SubBruteAttackTotalCount] = "Total Count", -}; - -static const char* subbrute_menu_names_small[] = { - [SubBruteAttackCAME12bit303] = "CAME 303MHz", - [SubBruteAttackCAME12bit307] = "CAME 307MHz", - [SubBruteAttackCAME12bit433] = "CAME 433MHz", - [SubBruteAttackCAME12bit868] = "CAME 868MHz", - [SubBruteAttackNICE12bit433] = "NICE 433MHz", - [SubBruteAttackNICE12bit868] = "NICE 868MHz", - [SubBruteAttackChamberlain9bit300] = "Cham 300MHz", - [SubBruteAttackChamberlain9bit315] = "Cham 315MHz", - [SubBruteAttackChamberlain9bit390] = "Cham 390MHz", - [SubBruteAttackLinear10bit300] = "Linear 300MHz", - [SubBruteAttackLinear10bit310] = "Linear 310MHz", - [SubBruteAttackLoadFile] = "Existing", - [SubBruteAttackTotalCount] = "Total Count", -}; - static bool subbrute_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubBruteState* instance = context; @@ -72,6 +25,9 @@ static void subbrute_tick_event_callback(void* context) { SubBruteState* subbrute_alloc() { SubBruteState* instance = malloc(sizeof(SubBruteState)); + memset(instance->text_store, 0, sizeof(instance->text_store)); + instance->file_path = furi_string_alloc(); + instance->scene_manager = scene_manager_alloc(&subbrute_scene_handlers, instance); instance->view_dispatcher = view_dispatcher_alloc(); @@ -84,7 +40,7 @@ SubBruteState* subbrute_alloc() { view_dispatcher_set_navigation_event_callback( instance->view_dispatcher, subbrute_back_event_callback); view_dispatcher_set_tick_event_callback( - instance->view_dispatcher, subbrute_tick_event_callback, 10); + instance->view_dispatcher, subbrute_tick_event_callback, 100); //Dialog instance->dialogs = furi_record_open(RECORD_DIALOGS); @@ -95,7 +51,7 @@ SubBruteState* subbrute_alloc() { // Devices instance->device = subbrute_device_alloc(); - // Worker + // SubBruteWorker instance->worker = subbrute_worker_alloc(); // TextInput @@ -134,8 +90,6 @@ SubBruteState* subbrute_alloc() { SubBruteViewAttack, subbrute_attack_view_get_view(instance->view_attack)); - // Loading - instance->loading = loading_alloc(); //instance->flipper_format = flipper_format_string_alloc(); //instance->environment = subghz_environment_alloc(); @@ -146,124 +100,61 @@ void subbrute_free(SubBruteState* instance) { furi_assert(instance); // SubBruteWorker -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteDevice"); -#endif subbrute_worker_stop(instance->worker); subbrute_worker_free(instance->worker); // SubBruteDevice -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteDevice"); -#endif subbrute_device_free(instance->device); // Notifications -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free Notifications"); -#endif notification_message(instance->notifications, &sequence_blink_stop); furi_record_close(RECORD_NOTIFICATION); instance->notifications = NULL; - // Loading -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free loading"); -#endif - loading_free(instance->loading); - // View Main -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewMain"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewMain); subbrute_main_view_free(instance->view_main); // View Attack -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewAttack"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewAttack); subbrute_attack_view_free(instance->view_attack); // TextInput -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewTextInput"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewTextInput); text_input_free(instance->text_input); // Custom Widget -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewWidget"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewWidget); widget_free(instance->widget); // Popup -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewPopup"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewPopup); popup_free(instance->popup); // ViewStack -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free SubBruteViewStack"); -#endif view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewStack); view_stack_free(instance->view_stack); //Dialog -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free RECORD_DIALOGS"); -#endif furi_record_close(RECORD_DIALOGS); instance->dialogs = NULL; // Scene manager -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free scene_manager"); -#endif scene_manager_free(instance->scene_manager); // View Dispatcher -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free view_dispatcher"); -#endif view_dispatcher_free(instance->view_dispatcher); // GUI -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free RECORD_GUI"); -#endif furi_record_close(RECORD_GUI); instance->gui = NULL; + furi_string_free(instance->file_path); + // The rest -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "free instance"); -#endif free(instance); } -void subbrute_show_loading_popup(void* context, bool show) { - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - SubBruteState* instance = context; - ViewStack* view_stack = instance->view_stack; - Loading* loading = instance->loading; - - if(show) { - // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); - view_stack_add_view(view_stack, loading_get_view(loading)); - } else { - view_stack_remove_view(view_stack, loading_get_view(loading)); - // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); - } -} - void subbrute_text_input_callback(void* context) { furi_assert(context); SubBruteState* instance = context; @@ -278,18 +169,6 @@ void subbrute_popup_closed_callback(void* context) { instance->view_dispatcher, SubBruteCustomEventTypePopupClosed); } -const char* subbrute_get_menu_name(SubBruteAttacks index) { - furi_assert(index < SubBruteAttackTotalCount); - - return subbrute_menu_names[index]; -} - -const char* subbrute_get_small_menu_name(SubBruteAttacks index) { - furi_assert(index < SubBruteAttackTotalCount); - - return subbrute_menu_names_small[index]; -} - // ENTRYPOINT int32_t subbrute_app(void* p) { UNUSED(p); diff --git a/applications/plugins/subbrute/subbrute_custom_event.h b/applications/plugins/subbrute/subbrute_custom_event.h index 800d8f5e0..2864f8934 100644 --- a/applications/plugins/subbrute/subbrute_custom_event.h +++ b/applications/plugins/subbrute/subbrute_custom_event.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - typedef enum { // Reserve first 100 events for button types and indexes, starting from 0 SubBruteCustomEventTypeReserved = 100, @@ -10,7 +7,7 @@ typedef enum { SubBruteCustomEventTypeBackPressed, SubBruteCustomEventTypeIndexSelected, SubBruteCustomEventTypeTransmitStarted, - SubBruteCustomEventTypeTransmitContinuousStarted, + SubBruteCustomEventTypeError, SubBruteCustomEventTypeTransmitFinished, SubBruteCustomEventTypeTransmitNotStarted, SubBruteCustomEventTypeTransmitCustom, diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 10d7a798d..bf85e3a66 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -1,85 +1,39 @@ #include "subbrute_device.h" -#include "subbrute_i.h" - -#include -#include -#include #include -#include - -#include -#include - #include -#include -#include -#include -#include +#include +#include #include #define TAG "SubBruteDevice" -/** - * List of protocols - */ -static const char* protocol_came = "CAME"; -static const char* protocol_cham_code = "Cham_Code"; -static const char* protocol_linear = "Linear"; -static const char* protocol_nice_flo = "Nice FLO"; -static const char* protocol_princeton = "Princeton"; -static const char* protocol_raw = "RAW"; - -/** - * Values to not use less memory for packet parse operations - */ -static const char* subbrute_key_file_start = - "Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d"; -static const char* subbrute_key_file_key = "%s\nKey: %s\n"; -static const char* subbrute_key_file_princeton_end = "%s\nKey: %s\nTE: %d\n"; -static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\n"; -static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\n"; - -// Why nobody set in as const in all codebase? -static const char* preset_ook270_async = "FuriHalSubGhzPresetOok270Async"; -static const char* preset_ook650_async = "FuriHalSubGhzPresetOok650Async"; -static const char* preset_2fsk_dev238_async = "FuriHalSubGhzPreset2FSKDev238Async"; -static const char* preset_2fsk_dev476_async = "FuriHalSubGhzPreset2FSKDev476Async"; -static const char* preset_msk99_97_kb_async = "FuriHalSubGhzPresetMSK99_97KbAsync"; -static const char* preset_gfs99_97_kb_async = "FuriHalSubGhzPresetGFS99_97KbAsync"; - SubBruteDevice* subbrute_device_alloc() { SubBruteDevice* instance = malloc(sizeof(SubBruteDevice)); - instance->state = SubBruteDeviceStateIDLE; instance->key_index = 0; - instance->load_path = furi_string_alloc(); - instance->preset_name = furi_string_alloc(); - instance->protocol_name = furi_string_alloc(); - + instance->protocol_info = NULL; + instance->file_protocol_info = NULL; instance->decoder_result = NULL; instance->receiver = NULL; instance->environment = subghz_environment_alloc(); - subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307); - +#ifdef FURI_DEBUG + subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); +#else + subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); +#endif return instance; } void subbrute_device_free(SubBruteDevice* instance) { furi_assert(instance); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_device_free"); -#endif // I don't know how to free this instance->decoder_result = NULL; if(instance->receiver != NULL) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subghz_receiver_free"); -#endif subghz_receiver_free(instance->receiver); instance->receiver = NULL; } @@ -87,57 +41,361 @@ void subbrute_device_free(SubBruteDevice* instance) { subghz_environment_free(instance->environment); instance->environment = NULL; -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "before free"); -#endif - - furi_string_free(instance->load_path); - furi_string_free(instance->preset_name); - furi_string_free(instance->protocol_name); + subbrute_device_free_protocol_info(instance); free(instance); } +uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) { + if(step > 0) { + if((instance->key_index + step) - instance->max_value == 1) { + instance->key_index = 0x00; + } else { + uint64_t value = instance->key_index + step; + if(value == instance->max_value) { + instance->key_index = value; + } else { + instance->key_index = value % instance->max_value; + } + } + } else { + if(instance->key_index + step == 0) { + instance->key_index = 0x00; + } else if(instance->key_index == 0) { + instance->key_index = instance->max_value; + } else { + uint64_t value = ((instance->key_index + step) + instance->max_value); + if(value == instance->max_value) { + instance->key_index = value; + } else { + instance->key_index = value % instance->max_value; + } + } + } + + return instance->key_index; +} + bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) { furi_assert(instance); #ifdef FURI_DEBUG FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name); #endif - bool result = subbrute_device_create_packet_parsed(instance, instance->key_index, false); - - if(!result) { - FURI_LOG_E(TAG, "subbrute_device_create_packet_parsed failed!"); - //subbrute_device_notification_message(instance, &sequence_error); - return false; - } Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* stream = buffered_file_stream_alloc(storage); - - result = false; + FlipperFormat* file = flipper_format_file_alloc(storage); + bool result = false; do { - if(!buffered_file_stream_open(stream, dev_file_name, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { - buffered_file_stream_close(stream); + if(!flipper_format_file_open_always(file, dev_file_name)) { + FURI_LOG_E(TAG, "Failed to open file: %s", dev_file_name); break; } - stream_write_cstring(stream, instance->payload); + Stream* stream = flipper_format_get_raw_stream(file); + if(instance->attack == SubBruteAttackLoadFile) { + subbrute_protocol_file_generate_file( + stream, + 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 { + subbrute_protocol_default_generate_file( + stream, + 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); + } result = true; } while(false); - buffered_file_stream_close(stream); - stream_free(stream); if(!result) { - FURI_LOG_E(TAG, "stream_write_string failed!"); - //subbrute_device_notification_message(instance, &sequence_error); + FURI_LOG_E(TAG, "subbrute_device_save_file failed!"); } + flipper_format_file_close(file); + flipper_format_free(file); furi_record_close(RECORD_STORAGE); return result; } +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, type); + + if(type != SubBruteAttackLoadFile) { + subbrute_device_free_protocol_info(instance); + instance->protocol_info = subbrute_protocol(type); + } + + // For non-file types we didn't set SubGhzProtocolDecoderBase + instance->receiver = subghz_receiver_alloc_init(instance->environment); + subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); + furi_hal_subghz_reset(); + + uint8_t protocol_check_result = SubBruteFileResultProtocolNotFound; +#ifdef FURI_DEBUG + uint8_t bits; + uint8_t te; + uint8_t repeat; + FuriHalSubGhzPreset preset; + SubBruteFileProtocol file; +#endif + if(type != SubBruteAttackLoadFile) { + instance->decoder_result = subghz_receiver_search_decoder_base_by_name( + instance->receiver, subbrute_protocol_file(instance->protocol_info->file)); + + if(!instance->decoder_result || + instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set"); + } else { + protocol_check_result = SubBruteFileResultOk; + + // Calc max value + instance->max_value = + subbrute_protocol_calc_max_value(instance->attack, instance->protocol_info->bits); + } +#ifdef FURI_DEBUG + bits = instance->protocol_info->bits; + te = instance->protocol_info->te; + repeat = instance->protocol_info->repeat; + preset = instance->protocol_info->preset; + file = instance->protocol_info->file; +#endif + } else { + // And here we need to set preset enum + protocol_check_result = SubBruteFileResultOk; + + // Calc max value + instance->max_value = + subbrute_protocol_calc_max_value(instance->attack, instance->file_protocol_info->bits); +#ifdef FURI_DEBUG + bits = instance->file_protocol_info->bits; + te = instance->file_protocol_info->te; + repeat = instance->file_protocol_info->repeat; + preset = instance->file_protocol_info->preset; + file = instance->file_protocol_info->file; +#endif + } + + subghz_receiver_free(instance->receiver); + instance->receiver = NULL; + + if(protocol_check_result != SubBruteFileResultOk) { + return SubBruteFileResultProtocolNotFound; + } + +#ifdef FURI_DEBUG + FURI_LOG_I( + TAG, + "subbrute_device_attack_set: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld", + subbrute_protocol_name(instance->attack), + bits, + subbrute_protocol_preset(preset), + subbrute_protocol_file(file), + te, + repeat, + instance->max_value); +#endif + + return SubBruteFileResultOk; +} + +uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) { + furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", file_path); +#endif + SubBruteFileResult result = SubBruteFileResultUnknown; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + + subbrute_device_free_protocol_info(instance); + instance->file_protocol_info = malloc(sizeof(SubBruteProtocol)); + + FuriString* temp_str; + temp_str = furi_string_alloc(); + uint32_t temp_data32; + + instance->receiver = subghz_receiver_alloc_init(instance->environment); + subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); + 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); + result = SubBruteFileResultErrorOpenFile; + break; + } + if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + result = SubBruteFileResultMissingOrIncorrectHeader; + break; + } + + // Frequency + if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { + instance->file_protocol_info->frequency = temp_data32; + if(!furi_hal_subghz_is_tx_allowed(instance->file_protocol_info->frequency)) { + result = SubBruteFileResultFrequencyNotAllowed; + break; + } + } else { + FURI_LOG_E(TAG, "Missing or incorrect Frequency"); + result = SubBruteFileResultMissingOrIncorrectFrequency; + break; + } + + // Preset + if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { + FURI_LOG_E(TAG, "Preset FAIL"); + result = SubBruteFileResultPresetInvalid; + } else { + instance->file_protocol_info->preset = subbrute_protocol_convert_preset(temp_str); + } + + const char* protocol_file = NULL; + // Protocol + if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + result = SubBruteFileResultMissingProtocol; + break; + } else { + instance->file_protocol_info->file = subbrute_protocol_file_protocol_name(temp_str); + protocol_file = subbrute_protocol_file(instance->file_protocol_info->file); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Protocol: %s", protocol_file); +#endif + } + + instance->decoder_result = + subghz_receiver_search_decoder_base_by_name(instance->receiver, protocol_file); + + if(!instance->decoder_result || strcmp(protocol_file, "RAW") == 0) { + FURI_LOG_E(TAG, "RAW unsupported"); + result = SubBruteFileResultProtocolNotSupported; + break; + } + + if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + FURI_LOG_E(TAG, "Protocol is dynamic - not supported"); + result = SubBruteFileResultDynamicProtocolNotValid; + break; + } +#ifdef FURI_DEBUG + else { + FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name); + } +#endif + + // Bit + if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) { + FURI_LOG_E(TAG, "Missing or incorrect Bit"); + result = SubBruteFileResultMissingOrIncorrectBit; + break; + } else { + instance->file_protocol_info->bits = temp_data32; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Bit: %d", instance->file_protocol_info->bits); +#endif + } + + // Key + if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { + FURI_LOG_E(TAG, "Missing or incorrect Key"); + result = SubBruteFileResultMissingOrIncorrectKey; + break; + } else { + snprintf( + instance->file_key, + sizeof(instance->file_key), + "%s", + furi_string_get_cstr(temp_str)); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Key: %s", instance->file_key); +#endif + } + + // TE + if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { + FURI_LOG_E(TAG, "Missing or incorrect TE"); + //result = SubBruteFileResultMissingOrIncorrectTe; + //break; + } else { + instance->file_protocol_info->te = temp_data32 != 0 ? temp_data32 : 0; + } + + // Repeat + if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Repeat: %ld", temp_data32); +#endif + instance->file_protocol_info->repeat = (uint8_t)temp_data32; + } else { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Repeat: 3 (default)"); +#endif + instance->file_protocol_info->repeat = 3; + } + + result = SubBruteFileResultOk; + } while(0); + + furi_string_free(temp_str); + flipper_format_file_close(fff_data_file); + flipper_format_free(fff_data_file); + furi_record_close(RECORD_STORAGE); + + subghz_receiver_free(instance->receiver); + + instance->decoder_result = NULL; + instance->receiver = NULL; + + if(result == SubBruteFileResultOk) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Loaded successfully"); +#endif + } else { + subbrute_device_free_protocol_info(instance); + } + + return result; +} + +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 = default_attack; + instance->key_index = 0x00; + instance->load_index = 0x00; + memset(instance->current_key, 0, sizeof(instance->current_key)); + + if(default_attack != SubBruteAttackLoadFile) { + memset(instance->file_key, 0, sizeof(instance->file_key)); + + instance->max_value = (uint64_t)0x00; + } +} + const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) { const char* result; switch(error_id) { @@ -174,9 +432,6 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) { case(SubBruteFileResultMissingOrIncorrectBit): result = "Missing or incorrect Bit"; break; - case(SubBruteFileResultBigBitSize): - result = "Has more than 24 Bits"; - break; case(SubBruteFileResultMissingOrIncorrectKey): result = "Missing or incorrect Key"; break; @@ -191,478 +446,11 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) { return result; } -bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t step, bool small) { +void subbrute_device_free_protocol_info(SubBruteDevice* instance) { furi_assert(instance); - - //char step_payload[32]; - //memset(step_payload, '0', sizeof(step_payload)); - memset(instance->payload, 0, sizeof(instance->payload)); - FuriString* candidate = furi_string_alloc(); - - 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]); - } 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); + instance->protocol_info = NULL; + if(instance->file_protocol_info) { + free(instance->file_protocol_info); } - -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step); -#endif - - if(small) { - if(instance->has_tail) { - snprintf( - instance->payload, - sizeof(instance->payload), - subbrute_key_small_with_tail, - instance->bit, - furi_string_get_cstr(candidate), - instance->te); - } else { - snprintf( - instance->payload, - sizeof(instance->payload), - subbrute_key_small_no_tail, - instance->bit, - furi_string_get_cstr(candidate)); - } - } else { - if(instance->has_tail) { - snprintf( - instance->payload, - sizeof(instance->payload), - subbrute_key_file_princeton_end, - instance->file_template, - furi_string_get_cstr(candidate), - instance->te); - } else { - snprintf( - instance->payload, - sizeof(instance->payload), - subbrute_key_file_key, - instance->file_template, - furi_string_get_cstr(candidate)); - } - } - -#ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "payload: %s", instance->payload); -#endif - - furi_string_free(candidate); - - return true; -} - -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, type); - switch(type) { - case SubBruteAttackLoadFile: - // In this case values must be already set - // file_result = - // subbrute_device_load_from_file(instance, furi_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 SubBruteAttackCAME12bit303: - case SubBruteAttackCAME12bit307: - case SubBruteAttackCAME12bit433: - case SubBruteAttackCAME12bit868: - if(type == SubBruteAttackCAME12bit303) { - instance->frequency = 303875000; - } else if(type == SubBruteAttackCAME12bit307) { - instance->frequency = 307800000; - } else if(type == SubBruteAttackCAME12bit433) { - instance->frequency = 433920000; - } else /* ALWAYS TRUE if(type == SubBruteAttackCAME12bit868) */ { - instance->frequency = 868350000; - } - instance->bit = 12; - furi_string_set_str(instance->protocol_name, protocol_came); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - case SubBruteAttackChamberlain9bit300: - case SubBruteAttackChamberlain9bit315: - case SubBruteAttackChamberlain9bit390: - if(type == SubBruteAttackChamberlain9bit300) { - instance->frequency = 300000000; - } else if(type == SubBruteAttackChamberlain9bit315) { - instance->frequency = 315000000; - } else /* ALWAYS TRUE if(type == SubBruteAttackChamberlain9bit390) */ { - instance->frequency = 390000000; - } - instance->bit = 9; - furi_string_set_str(instance->protocol_name, protocol_cham_code); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - case SubBruteAttackLinear10bit300: - instance->frequency = 300000000; - instance->bit = 10; - furi_string_set_str(instance->protocol_name, protocol_linear); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - case SubBruteAttackLinear10bit310: - instance->frequency = 310000000; - instance->bit = 10; - furi_string_set_str(instance->protocol_name, protocol_linear); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - case SubBruteAttackNICE12bit433: - instance->frequency = 433920000; - instance->bit = 12; - furi_string_set_str(instance->protocol_name, protocol_nice_flo); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - case SubBruteAttackNICE12bit868: - instance->frequency = 868350000; - instance->bit = 12; - furi_string_set_str(instance->protocol_name, protocol_nice_flo); - furi_string_set_str(instance->preset_name, preset_ook650_async); - break; - default: - FURI_LOG_E(TAG, "Unknown attack type: %d", type); - return SubBruteFileResultProtocolNotFound; // RETURN - } - - /*if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) { - FURI_LOG_E(TAG, "Frequency invalid: %d", instance->frequency); - return SubBruteFileResultMissingOrIncorrectFrequency; // RETURN - }*/ - - // For non-file types we didn't set SubGhzProtocolDecoderBase - instance->receiver = subghz_receiver_alloc_init(instance->environment); - subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); - furi_hal_subghz_reset(); - - uint8_t protocol_check_result = SubBruteFileResultProtocolNotFound; - if(type != SubBruteAttackLoadFile) { - instance->decoder_result = subghz_receiver_search_decoder_base_by_name( - instance->receiver, furi_string_get_cstr(instance->protocol_name)); - - if(!instance->decoder_result || - instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { - FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set"); - } else { - protocol_check_result = SubBruteFileResultOk; - } - } else { - // And here we need to set preset enum - instance->preset = - subbrute_device_convert_preset(furi_string_get_cstr(instance->preset_name)); - protocol_check_result = SubBruteFileResultOk; - } - - subghz_receiver_free(instance->receiver); - instance->receiver = NULL; - - if(protocol_check_result != SubBruteFileResultOk) { - return SubBruteFileResultProtocolNotFound; - } - - instance->has_tail = - (strcmp(furi_string_get_cstr(instance->protocol_name), protocol_princeton) == 0); - - // Calc max value - if(instance->attack == SubBruteAttackLoadFile) { - instance->max_value = 0x3F; - } else { - FuriString* max_value_s; - max_value_s = furi_string_alloc(); - for(uint8_t i = 0; i < instance->bit; 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->frequency, - furi_string_get_cstr(instance->preset_name), - furi_string_get_cstr(instance->protocol_name), - instance->bit); -// strncat(instance->file_template, "\n", sizeof(instance->file_template)); -// strncat(instance->file_template, subbrute_key_file_key, sizeof(instance->file_template)); -// if(instance->has_tail) { -// strncat( -// instance->file_template, -// subbrute_key_file_princeton_end, -// sizeof(instance->file_template)); -// } -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "tail: %d, file_template: %s", instance->has_tail, instance->file_template); -#endif - - // Init payload - subbrute_device_create_packet_parsed(instance, instance->key_index, false); - - return SubBruteFileResultOk; -} - -uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, FuriString* file_path) { - furi_assert(instance); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", furi_string_get_cstr(file_path)); -#endif - SubBruteFileResult result = SubBruteFileResultUnknown; - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - - FuriString* temp_str; - temp_str = furi_string_alloc(); - uint32_t temp_data32; - - instance->receiver = subghz_receiver_alloc_init(instance->environment); - subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable); - furi_hal_subghz_reset(); - - do { - if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_path))) { - FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(file_path)); - result = SubBruteFileResultErrorOpenFile; - break; - } - if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - result = SubBruteFileResultMissingOrIncorrectHeader; - break; - } - - // Frequency - if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - instance->frequency = temp_data32; - if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) { - result = SubBruteFileResultFrequencyNotAllowed; - break; - } - } else { - FURI_LOG_E(TAG, "Missing or incorrect Frequency"); - result = SubBruteFileResultMissingOrIncorrectFrequency; - break; - } - // Preset - if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { - FURI_LOG_E(TAG, "Preset FAIL"); - result = SubBruteFileResultPresetInvalid; - } else { - instance->preset_name = furi_string_alloc_set(furi_string_get_cstr(temp_str)); - } - - // Protocol - if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - result = SubBruteFileResultMissingProtocol; - break; - } else { - instance->protocol_name = furi_string_alloc_set(furi_string_get_cstr(temp_str)); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Protocol: %s", furi_string_get_cstr(instance->protocol_name)); -#endif - } - - instance->decoder_result = subghz_receiver_search_decoder_base_by_name( - instance->receiver, furi_string_get_cstr(instance->protocol_name)); - - if(!instance->decoder_result || - strcmp(furi_string_get_cstr(instance->protocol_name), "RAW") == 0) { - FURI_LOG_E(TAG, "RAW unsupported"); - result = SubBruteFileResultProtocolNotSupported; - break; - } - - if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { - FURI_LOG_E(TAG, "Protocol is dynamic - not supported"); - result = SubBruteFileResultDynamicProtocolNotValid; - break; - } -#ifdef FURI_DEBUG - else { - FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name); - } -#endif - - // instance->decoder_result = subghz_receiver_search_decoder_base_by_name( - // instance->receiver, furi_string_get_cstr(instance->protocol_name)); - // - // if(!instance->decoder_result) { - // FURI_LOG_E(TAG, "Protocol not found"); - // result = SubBruteFileResultProtocolNotFound; - // break; - // } - - // Bit - if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) { - FURI_LOG_E(TAG, "Missing or incorrect Bit"); - result = SubBruteFileResultMissingOrIncorrectBit; - break; - } else { - if(temp_data32 > 24) { - FURI_LOG_E(TAG, "Incorrect Bits, 24 is maximum"); - result = SubBruteFileResultBigBitSize; - break; - } - instance->bit = temp_data32; -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Bit: %ld", instance->bit); -#endif - } - - // Key - if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { - FURI_LOG_E(TAG, "Missing or incorrect Key"); - result = SubBruteFileResultMissingOrIncorrectKey; - break; - } else { - snprintf( - instance->file_key, - sizeof(instance->file_key), - "%s", - furi_string_get_cstr(temp_str)); -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Key: %s", instance->file_key); -#endif - } - - // TE - if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { - FURI_LOG_E(TAG, "Missing or incorrect TE"); - //result = SubBruteFileResultMissingOrIncorrectTe; - //break; - } else { - instance->te = temp_data32; - instance->has_tail = true; - } - - // Repeat - if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Repeat: %ld", temp_data32); -#endif - instance->repeat = temp_data32; - } else { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Repeat: 3 (default)"); -#endif - instance->repeat = 3; - } - - result = SubBruteFileResultOk; - } while(0); - - furi_string_free(temp_str); - flipper_format_file_close(fff_data_file); - flipper_format_free(fff_data_file); - furi_record_close(RECORD_STORAGE); - - subghz_receiver_free(instance->receiver); - - instance->decoder_result = NULL; - instance->receiver = NULL; - - if(result == SubBruteFileResultOk) { -#ifdef FURI_DEBUG - FURI_LOG_D(TAG, "Loaded successfully"); -#endif - } - - return result; -} - -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 = default_attack; - instance->key_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->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; - - furi_string_free(instance->protocol_name); - furi_string_free(instance->preset_name); - - furi_string_free(instance->load_path); - instance->load_path = furi_string_alloc(); - - instance->protocol_name = furi_string_alloc_set(protocol_raw); - instance->preset_name = furi_string_alloc_set(preset_ook650_async); - instance->preset = FuriHalSubGhzPresetOok650Async; - - instance->repeat = 5; - instance->te = 0; - instance->has_tail = false; - } -#ifdef FURI_DEBUG - FURI_LOG_D( - TAG, "subbrute_device_attack_set_default_values done. has_tail: %d", instance->has_tail); - //furi_delay_ms(250); -#endif -} - -FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset_name) { - FuriString* preset; - preset = furi_string_alloc_set(preset_name); - FuriHalSubGhzPreset preset_value; - if(furi_string_cmp_str(preset, preset_ook270_async) == 0) { - preset_value = FuriHalSubGhzPresetOok270Async; - } else if(furi_string_cmp_str(preset, preset_ook650_async) == 0) { - preset_value = FuriHalSubGhzPresetOok650Async; - } else if(furi_string_cmp_str(preset, preset_2fsk_dev238_async) == 0) { - preset_value = FuriHalSubGhzPreset2FSKDev238Async; - } else if(furi_string_cmp_str(preset, preset_2fsk_dev476_async) == 0) { - preset_value = FuriHalSubGhzPreset2FSKDev476Async; - } else if(furi_string_cmp_str(preset, preset_msk99_97_kb_async) == 0) { - preset_value = FuriHalSubGhzPresetMSK99_97KbAsync; - } else if(furi_string_cmp_str(preset, preset_gfs99_97_kb_async) == 0) { - preset_value = FuriHalSubGhzPresetMSK99_97KbAsync; - } else { - preset_value = FuriHalSubGhzPresetCustom; - } - - furi_string_free(preset); - return preset_value; -} + instance->file_protocol_info = NULL; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index 7b8963731..b0f136ad2 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -1,8 +1,6 @@ #pragma once -#include -#include -#include +#include "subbrute_protocols.h" #include #include #include @@ -16,22 +14,6 @@ #define SUBBRUTE_PAYLOAD_SIZE 16 -typedef enum { - SubBruteAttackCAME12bit303, - SubBruteAttackCAME12bit307, - SubBruteAttackCAME12bit433, - SubBruteAttackCAME12bit868, - SubBruteAttackNICE12bit433, - SubBruteAttackNICE12bit868, - SubBruteAttackChamberlain9bit300, - SubBruteAttackChamberlain9bit315, - SubBruteAttackChamberlain9bit390, - SubBruteAttackLinear10bit300, - SubBruteAttackLinear10bit310, - SubBruteAttackLoadFile, - SubBruteAttackTotalCount, -} SubBruteAttacks; - typedef enum { SubBruteFileResultUnknown, SubBruteFileResultOk, @@ -47,58 +29,42 @@ typedef enum { SubBruteFileResultMissingOrIncorrectBit, SubBruteFileResultMissingOrIncorrectKey, SubBruteFileResultMissingOrIncorrectTe, - SubBruteFileResultBigBitSize, } SubBruteFileResult; -typedef enum { - SubBruteDeviceStateIDLE, - SubBruteDeviceStateReady, - SubBruteDeviceStateTx, - SubBruteDeviceStateFinished, -} SubBruteDeviceState; - typedef struct { - SubBruteDeviceState state; + const SubBruteProtocol* protocol_info; + SubBruteProtocol* file_protocol_info; // Current step uint64_t key_index; - FuriString* load_path; // Index of group to bruteforce in loaded file uint8_t load_index; + // SubGhz SubGhzReceiver* receiver; SubGhzProtocolDecoderBase* decoder_result; SubGhzEnvironment* environment; // Attack state SubBruteAttacks attack; - char file_template[SUBBRUTE_TEXT_STORE_SIZE]; - bool has_tail; - char payload[SUBBRUTE_TEXT_STORE_SIZE * 2]; uint64_t max_value; // Loaded info for attack type - FuriHalSubGhzPreset preset; - FuriString* preset_name; - FuriString* protocol_name; - uint32_t frequency; - uint32_t repeat; - uint32_t bit; char current_key[SUBBRUTE_PAYLOAD_SIZE]; - uint32_t te; - char file_key[SUBBRUTE_MAX_LEN_NAME]; - char text_store[SUBBRUTE_PAYLOAD_SIZE]; } SubBruteDevice; SubBruteDevice* subbrute_device_alloc(); void subbrute_device_free(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, bool small); SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type); -uint8_t subbrute_device_load_from_file(SubBruteDevice* context, FuriString* file_path); -FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset); +uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path); + +uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step); + +void subbrute_device_free_protocol_info(SubBruteDevice* instance); void subbrute_device_attack_set_default_values( SubBruteDevice* context, SubBruteAttacks default_attack); \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_i.h b/applications/plugins/subbrute/subbrute_i.h index 348a180c1..edd87eb0f 100644 --- a/applications/plugins/subbrute/subbrute_i.h +++ b/applications/plugins/subbrute/subbrute_i.h @@ -4,12 +4,9 @@ #include #include -#include "lib/toolbox/path.h" #include #include -#include - #include #include #include @@ -21,17 +18,12 @@ #include -#include -#include -#include -#include #include #include +#include "subbrute.h" #include "subbrute_device.h" #include "helpers/subbrute_worker.h" -#include "subbrute.h" -#include "scenes/subbrute_scene.h" #include "views/subbrute_attack_view.h" #include "views/subbrute_main_view.h" @@ -56,7 +48,10 @@ struct SubBruteState { Popup* popup; Widget* widget; DialogsApp* dialogs; - Loading* loading; + + // Text store + char text_store[SUBBRUTE_MAX_LEN_NAME]; + FuriString* file_path; // Views SubBruteMainView* view_main; @@ -66,16 +61,12 @@ struct SubBruteState { // Scene SceneManager* scene_manager; + // SubBruteDevice SubBruteDevice* device; + // SubBruteWorker SubBruteWorker* worker; - - //Menu stuff - // TODO: Do we need it? - uint8_t menu_index; }; void subbrute_show_loading_popup(void* context, bool show); void subbrute_text_input_callback(void* context); -void subbrute_popup_closed_callback(void* context); -const char* subbrute_get_menu_name(uint8_t index); -const char* subbrute_get_small_menu_name(uint8_t index); \ No newline at end of file +void subbrute_popup_closed_callback(void* context); \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_protocols.c b/applications/plugins/subbrute/subbrute_protocols.c new file mode 100644 index 000000000..77a0bf791 --- /dev/null +++ b/applications/plugins/subbrute/subbrute_protocols.c @@ -0,0 +1,422 @@ +#include "subbrute_protocols.h" +#include + +#define TAG "SubBruteProtocols" + +/** + * CAME 12bit 303MHz + */ +const SubBruteProtocol subbrute_protocol_came_12bit_303 = { + .frequency = 303875000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = CAMEFileProtocol}; + +/** + * CAME 12bit 307MHz + */ +const SubBruteProtocol subbrute_protocol_came_12bit_307 = { + .frequency = 307800000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = CAMEFileProtocol}; + +/** + * CAME 12bit 433MHz + */ +const SubBruteProtocol subbrute_protocol_came_12bit_433 = { + .frequency = 433920000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = CAMEFileProtocol}; + +/** + * CAME 12bit 868MHz + */ +const SubBruteProtocol subbrute_protocol_came_12bit_868 = { + .frequency = 868350000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = CAMEFileProtocol}; + +/** + * NICE 12bit 433MHz + */ +const SubBruteProtocol subbrute_protocol_nice_12bit_433 = { + .frequency = 433920000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = NICEFileProtocol}; + +/** + * NICE 12bit 868MHz + */ +const SubBruteProtocol subbrute_protocol_nice_12bit_868 = { + .frequency = 868350000, + .bits = 12, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = NICEFileProtocol}; + +/** + * Chamberlain 9bit 300MHz + */ +const SubBruteProtocol subbrute_protocol_chamberlain_9bit_300 = { + .frequency = 300000000, + .bits = 9, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = ChamberlainFileProtocol}; + +/** + * Chamberlain 9bit 315MHz + */ +const SubBruteProtocol subbrute_protocol_chamberlain_9bit_315 = { + .frequency = 315000000, + .bits = 9, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = ChamberlainFileProtocol}; + +/** + * Chamberlain 9bit 390MHz + */ +const SubBruteProtocol subbrute_protocol_chamberlain_9bit_390 = { + .frequency = 390000000, + .bits = 9, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = ChamberlainFileProtocol}; + +/** + * Linear 10bit 300MHz + */ +const SubBruteProtocol subbrute_protocol_linear_10bit_300 = { + .frequency = 300000000, + .bits = 10, + .te = 0, + .repeat = 5, + .preset = FuriHalSubGhzPresetOok650Async, + .file = LinearFileProtocol}; + +/** + * Linear 10bit 310MHz + */ +const SubBruteProtocol subbrute_protocol_linear_10bit_310 = { + .frequency = 310000000, + .bits = 10, + .te = 0, + .repeat = 5, + .preset = FuriHalSubGhzPresetOok650Async, + .file = LinearFileProtocol}; + +/** + * BF existing dump + */ +const SubBruteProtocol subbrute_protocol_load_file = + {0, 0, 0, 3, FuriHalSubGhzPresetOok650Async, RAWFileProtocol}; + +static const char* subbrute_protocol_names[] = { + [SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz", + [SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz", + [SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz", + [SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz", + [SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz", + [SubBruteAttackNICE12bit868] = "NICE 12bit 868MHz", + [SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz", + [SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz", + [SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz", + [SubBruteAttackLinear10bit300] = "Linear 10bit 300MHz", + [SubBruteAttackLinear10bit310] = "Linear 10bit 310MHz", + [SubBruteAttackLoadFile] = "BF existing dump", + [SubBruteAttackTotalCount] = "Total Count", +}; + +static const char* subbrute_protocol_presets[] = { + [FuriHalSubGhzPresetIDLE] = "FuriHalSubGhzPresetIDLE", + [FuriHalSubGhzPresetOok270Async] = "FuriHalSubGhzPresetOok270Async", + [FuriHalSubGhzPresetOok650Async] = "FuriHalSubGhzPresetOok650Async", + [FuriHalSubGhzPreset2FSKDev238Async] = "FuriHalSubGhzPreset2FSKDev238Async", + [FuriHalSubGhzPreset2FSKDev476Async] = "FuriHalSubGhzPreset2FSKDev476Async", + [FuriHalSubGhzPresetMSK99_97KbAsync] = "FuriHalSubGhzPresetMSK99_97KbAsync", + [FuriHalSubGhzPresetGFSK9_99KbAsync] = "FuriHalSubGhzPresetGFSK9_99KbAsync", +}; + +const SubBruteProtocol* subbrute_protocol_registry[] = { + [SubBruteAttackCAME12bit303] = &subbrute_protocol_came_12bit_303, + [SubBruteAttackCAME12bit307] = &subbrute_protocol_came_12bit_307, + [SubBruteAttackCAME12bit433] = &subbrute_protocol_came_12bit_433, + [SubBruteAttackCAME12bit868] = &subbrute_protocol_came_12bit_868, + [SubBruteAttackNICE12bit433] = &subbrute_protocol_nice_12bit_433, + [SubBruteAttackNICE12bit868] = &subbrute_protocol_nice_12bit_868, + [SubBruteAttackChamberlain9bit300] = &subbrute_protocol_chamberlain_9bit_300, + [SubBruteAttackChamberlain9bit315] = &subbrute_protocol_chamberlain_9bit_315, + [SubBruteAttackChamberlain9bit390] = &subbrute_protocol_chamberlain_9bit_390, + [SubBruteAttackLinear10bit300] = &subbrute_protocol_linear_10bit_300, + [SubBruteAttackLinear10bit310] = &subbrute_protocol_linear_10bit_310, + [SubBruteAttackLoadFile] = &subbrute_protocol_load_file}; + +static const char* subbrute_protocol_file_types[] = { + [CAMEFileProtocol] = "CAME", + [NICEFileProtocol] = "Nice FLO", + [ChamberlainFileProtocol] = "Cham_Code", + [LinearFileProtocol] = "Linear", + [PrincetonFileProtocol] = "Princeton", + [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\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) { + return subbrute_protocol_names[index]; +} + +const SubBruteProtocol* subbrute_protocol(SubBruteAttacks index) { + return subbrute_protocol_registry[index]; +} + +const char* subbrute_protocol_preset(FuriHalSubGhzPreset preset) { + return subbrute_protocol_presets[preset]; +} + +const char* subbrute_protocol_file(SubBruteFileProtocol protocol) { + return subbrute_protocol_file_types[protocol]; +} + +FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name) { + for(size_t i = FuriHalSubGhzPresetIDLE; i < FuriHalSubGhzPresetCustom; i++) { + if(furi_string_cmp_str(preset_name, subbrute_protocol_presets[i]) == 0) { + return i; + } + } + + return FuriHalSubGhzPresetIDLE; +} + +SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) { + for(size_t i = CAMEFileProtocol; i < TotalFileProtocol - 1; i++) { + if(furi_string_cmp_str(name, subbrute_protocol_file_types[i]) == 0) { + return i; + } + } + + return RAWFileProtocol; +} + +void subbrute_protocol_default_payload( + Stream* stream, + 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 + stream_clean(stream); + if(te) { + stream_write_format( + stream, + subbrute_key_small_with_tail, + bits, + furi_string_get_cstr(candidate), + te, + repeat); + } else { + stream_write_format( + stream, subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat); + } + + furi_string_free(candidate); +} + +void subbrute_protocol_file_payload( + Stream* stream, + 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(); + 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 + stream_clean(stream); + + if(te) { + stream_write_format( + stream, + subbrute_key_small_with_tail, + bits, + furi_string_get_cstr(candidate), + te, + repeat); + } else { + stream_write_format( + stream, subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat); + } + + furi_string_free(candidate); +} + +void subbrute_protocol_default_generate_file( + Stream* stream, + 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 + stream_clean(stream); + + if(te) { + stream_write_format( + stream, + subbrute_key_file_start_with_tail, + frequency, + subbrute_protocol_preset(preset), + subbrute_protocol_file(file), + bits, + furi_string_get_cstr(candidate), + te, + repeat); + } else { + stream_write_format( + stream, + subbrute_key_file_start_no_tail, + frequency, + subbrute_protocol_preset(preset), + subbrute_protocol_file(file), + bits, + furi_string_get_cstr(candidate), + repeat); + } + + furi_string_free(candidate); +} + +void subbrute_protocol_file_generate_file( + Stream* stream, + 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(); + 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 + stream_clean(stream); + if(te) { + stream_write_format( + stream, + subbrute_key_file_start_with_tail, + frequency, + subbrute_protocol_preset(preset), + subbrute_protocol_file(file), + bits, + furi_string_get_cstr(candidate), + te, + repeat); + } else { + stream_write_format( + stream, + subbrute_key_file_start_no_tail, + frequency, + subbrute_protocol_preset(preset), + subbrute_protocol_file(file), + bits, + furi_string_get_cstr(candidate), + repeat); + } + + furi_string_free(candidate); +} + +uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) { + uint64_t max_value; + if(attack_type == SubBruteAttackLoadFile) { + max_value = 0xFF; + } 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; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/subbrute_protocols.h b/applications/plugins/subbrute/subbrute_protocols.h new file mode 100644 index 000000000..e0a97eef2 --- /dev/null +++ b/applications/plugins/subbrute/subbrute_protocols.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include +#include +//typedef enum { +// FrequencyProtocolField, +// BitsProtocolField, +// HasTeProtocolField, +// RepeatProtocolField, +// PresetProtocolField, +// FileProtocolField, +// TotalProtocolFields +//} ProtocolFields; + +typedef enum { + CAMEFileProtocol, + NICEFileProtocol, + ChamberlainFileProtocol, + LinearFileProtocol, + PrincetonFileProtocol, + RAWFileProtocol, + TotalFileProtocol, +} SubBruteFileProtocol; + +typedef enum { + SubBruteAttackCAME12bit303, + SubBruteAttackCAME12bit307, + SubBruteAttackCAME12bit433, + SubBruteAttackCAME12bit868, + SubBruteAttackNICE12bit433, + SubBruteAttackNICE12bit868, + SubBruteAttackChamberlain9bit300, + SubBruteAttackChamberlain9bit315, + SubBruteAttackChamberlain9bit390, + SubBruteAttackLinear10bit300, + SubBruteAttackLinear10bit310, + SubBruteAttackLoadFile, + SubBruteAttackTotalCount, +} SubBruteAttacks; + +typedef struct { + uint32_t frequency; + uint8_t bits; + uint8_t te; + uint8_t repeat; + FuriHalSubGhzPreset preset; + SubBruteFileProtocol file; +} SubBruteProtocol; + +const SubBruteProtocol* subbrute_protocol(SubBruteAttacks index); +const char* subbrute_protocol_preset(FuriHalSubGhzPreset preset); +const char* subbrute_protocol_file(SubBruteFileProtocol protocol); +FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name); +SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name); +const char* subbrute_protocol_name(SubBruteAttacks index); + +void subbrute_protocol_default_payload( + Stream* stream, + uint64_t step, + uint8_t bits, + uint8_t te, + uint8_t repeat); +void subbrute_protocol_file_payload( + Stream* stream, + uint64_t step, + uint8_t bits, + uint8_t te, + uint8_t repeat, + uint8_t load_index, + const char* file_key); +void subbrute_protocol_default_generate_file( + Stream* stream, + uint32_t frequency, + FuriHalSubGhzPreset preset, + SubBruteFileProtocol file, + uint64_t step, + uint8_t bits, + uint8_t te, + uint8_t repeat); +void subbrute_protocol_file_generate_file( + Stream* stream, + 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); \ No newline at end of file diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.c b/applications/plugins/subbrute/views/subbrute_attack_view.c index c117fb680..c3412de71 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.c +++ b/applications/plugins/subbrute/views/subbrute_attack_view.c @@ -1,11 +1,12 @@ #include "subbrute_attack_view.h" #include "../subbrute_i.h" +#include "../subbrute_protocols.h" -#include "assets_icons.h" #include #include -#include -#include +#include +#include +#include #define TAG "SubBruteAttackView" @@ -292,69 +293,67 @@ void subbrute_attack_view_exit(void* context) { false); } +/** + * Thanks to the author of metronome + * @param canvas + * @param str + */ void elements_button_top_left(Canvas* canvas, const char* str) { const Icon* icon = &I_ButtonUp_7x4; const uint8_t button_height = 12; - const uint8_t vertical_offset = 9; // + const uint8_t vertical_offset = 3; const uint8_t horizontal_offset = 3; const uint8_t string_width = canvas_string_width(canvas, str); const uint8_t icon_h_offset = 3; - const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height; // - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1; + const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset; + const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; const uint8_t x = 0; - const uint8_t y = 0; + const uint8_t y = 0 + button_height; - canvas_draw_box(canvas, x, y, button_width, button_height); -#ifdef FURI_DEBUG - FURI_LOG_D( - TAG, "lbox, x: %d, y: %d, width: %d, height: %d", x, y, button_width, button_height); -#endif - // canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y + button_height - 0); // - // canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y + button_height - 1); - // canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y + button_height - 2); + canvas_draw_box(canvas, x, y - button_height, button_width, button_height); + canvas_draw_line(canvas, x + button_width + 0, y - button_height, x + button_width + 0, y - 1); + canvas_draw_line(canvas, x + button_width + 1, y - button_height, x + button_width + 1, y - 2); + canvas_draw_line(canvas, x + button_width + 2, y - button_height, x + button_width + 2, y - 3); canvas_invert_color(canvas); - canvas_draw_icon(canvas, x + horizontal_offset, y + icon_v_offset, icon); + canvas_draw_icon(canvas, x + horizontal_offset, y - icon_v_offset, icon); canvas_draw_str( - canvas, x + horizontal_offset + icon_width_with_offset, y + vertical_offset, str); + canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); canvas_invert_color(canvas); } +/** + * Thanks to the author of metronome + * @param canvas + * @param str + */ void elements_button_top_right(Canvas* canvas, const char* str) { const Icon* icon = &I_ButtonDown_7x4; const uint8_t button_height = 12; - const uint8_t vertical_offset = 9; + const uint8_t vertical_offset = 3; const uint8_t horizontal_offset = 3; const uint8_t string_width = canvas_string_width(canvas, str); const uint8_t icon_h_offset = 3; - const uint8_t icon_width_with_offset = icon->width + icon_h_offset; - const uint8_t icon_v_offset = icon->height; // + vertical_offset; - const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1; + const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset; + const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset + 1; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; const uint8_t x = canvas_width(canvas); - const uint8_t y = 0; + const uint8_t y = 0 + button_height; - canvas_draw_box(canvas, x - button_width, y, button_width, button_height); -#ifdef FURI_DEBUG - FURI_LOG_D( - TAG, - "rbox, x: %d, y: %d, width: %d, height: %d", - x - button_width, - y, - button_width, - button_height); -#endif - // canvas_draw_line(canvas, x - button_width - 1, y, x + button_width - 1, y + button_height - 0); - // canvas_draw_line(canvas, x - button_width - 2, y, x + button_width - 2, y + button_height - 1); - // canvas_draw_line(canvas, x - button_width - 3, y, x + button_width - 3, y + button_height - 2); + canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height); + canvas_draw_line(canvas, x - button_width - 1, y - button_height, x - button_width - 1, y - 1); + canvas_draw_line(canvas, x - button_width - 2, y - button_height, x - button_width - 2, y - 2); + canvas_draw_line(canvas, x - button_width - 3, y - button_height, x - button_width - 3, y - 3); canvas_invert_color(canvas); - canvas_draw_str(canvas, x - button_width + horizontal_offset, y + vertical_offset, str); - canvas_draw_icon(canvas, x - horizontal_offset - icon->width, y + icon_v_offset, icon); + canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str); + canvas_draw_icon( + canvas, x - horizontal_offset - icon_get_width(icon), y - icon_v_offset, icon); canvas_invert_color(canvas); } @@ -364,7 +363,7 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) { char buffer[26]; const char* attack_name = NULL; - attack_name = subbrute_get_menu_name(model->index); + attack_name = subbrute_protocol_name(model->index); // Title if(model->is_attacking) { canvas_set_color(canvas, ColorBlack); @@ -393,8 +392,9 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) { } // canvas_draw_icon_animation const uint8_t icon_h_offset = 0; - const uint8_t icon_width_with_offset = model->icon->icon->width + icon_h_offset; - const uint8_t icon_v_offset = model->icon->icon->height; // + vertical_offset; + const uint8_t icon_width_with_offset = + icon_animation_get_width(model->icon) + icon_h_offset; + const uint8_t icon_v_offset = icon_animation_get_height(model->icon); // + vertical_offset; const uint8_t x = canvas_width(canvas); const uint8_t y = canvas_height(canvas); canvas_draw_icon_animation( diff --git a/applications/plugins/subbrute/views/subbrute_attack_view.h b/applications/plugins/subbrute/views/subbrute_attack_view.h index 2aa9c4012..1e25379e2 100644 --- a/applications/plugins/subbrute/views/subbrute_attack_view.h +++ b/applications/plugins/subbrute/views/subbrute_attack_view.h @@ -1,12 +1,9 @@ #pragma once +#include "../subbrute_custom_event.h" #include -#include "assets_icons.h" #include #include -#include -#include -#include "../subbrute_custom_event.h" typedef void (*SubBruteAttackViewCallback)(SubBruteCustomEvent event, void* context); typedef struct SubBruteAttackView SubBruteAttackView; diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index c3b4174e7..9d3486797 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -1,10 +1,11 @@ #include "subbrute_main_view.h" #include "../subbrute_i.h" +#include "../subbrute_protocols.h" #include #include -#include "assets_icons.h" #include +#include #define STATUS_BAR_Y_SHIFT 14 #define TAG "SubBruteMainView" @@ -85,12 +86,12 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { canvas_set_font(canvas, FontPrimary); canvas_draw_box(canvas, 0, 0, canvas_width(canvas), STATUS_BAR_Y_SHIFT); canvas_invert_color(canvas); - canvas_draw_str_aligned(canvas, 64, 3, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); + canvas_draw_str_aligned(canvas, 64, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer v3"); canvas_invert_color(canvas); if(m->is_select_byte) { #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "key_field: %s", m->key_field); + //FURI_LOG_D(TAG, "key_field: %s", m->key_field); #endif char msg_index[18]; snprintf(msg_index, sizeof(msg_index), "Field index : %d", m->index); @@ -117,13 +118,12 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { const uint8_t item_height = 16; #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); + //FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); #endif for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { uint8_t item_position = position - model->window_position; if(item_position < items_on_screen) { - const char* str = subbrute_get_menu_name(position); if(m->index == position) { canvas_draw_str_aligned( canvas, @@ -131,7 +131,7 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignLeft, AlignCenter, - str); + subbrute_protocol_name(position)); elements_frame( canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 124, 15); } else { @@ -141,7 +141,7 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, AlignLeft, AlignCenter, - str); + subbrute_protocol_name(position)); } } } @@ -227,10 +227,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { #ifdef FURI_DEBUG with_view_model( - instance->view, (SubBruteMainViewModel * model) { - index = model->index; - return false; - }); + instance->view, SubBruteMainViewModel * model, { index = model->index; }, false); FURI_LOG_I(TAG, "Index: %d", index); #endif @@ -265,10 +262,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { #ifdef FURI_DEBUG with_view_model( - instance->view, (SubBruteMainViewModel * model) { - index = model->index; - return false; - }); + instance->view, SubBruteMainViewModel * model, { index = model->index; }, false); FURI_LOG_I(TAG, "Index: %d", index); #endif diff --git a/applications/plugins/subbrute/views/subbrute_main_view.h b/applications/plugins/subbrute/views/subbrute_main_view.h index 02eb3305a..361dbc22b 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.h +++ b/applications/plugins/subbrute/views/subbrute_main_view.h @@ -2,10 +2,8 @@ #include "../subbrute_custom_event.h" #include -#include "assets_icons.h" #include #include -#include typedef void (*SubBruteMainViewCallback)(SubBruteCustomEvent event, void* context); typedef struct SubBruteMainView SubBruteMainView;