diff --git a/applications/external/multi_fuzzer/LICENSE b/applications/external/multi_fuzzer/LICENSE new file mode 100644 index 000000000..c24a18ce0 --- /dev/null +++ b/applications/external/multi_fuzzer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 @gid9798 @xMasterX @G4N4P4T1 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/applications/external/multi_fuzzer/application.fam b/applications/external/multi_fuzzer/application.fam index 4d20930ba..208a8a9ca 100644 --- a/applications/external/multi_fuzzer/application.fam +++ b/applications/external/multi_fuzzer/application.fam @@ -11,6 +11,11 @@ App( "notification", ], stack_size=2 * 1024, + fap_author="gid9798 xMasterX", + fap_weburl="https://github.com/DarkFlippers/Multi_Fuzzer", + fap_version="1.1", + targets=["f7"], + fap_description="Fuzzer for ibutton readers", fap_icon="ibutt_10px.png", fap_category="iButton", fap_private_libs=[ @@ -36,6 +41,11 @@ App( "notification", ], stack_size=2 * 1024, + fap_author="gid9798 xMasterX", + fap_weburl="https://github.com/DarkFlippers/Multi_Fuzzer", + fap_version="1.1", + targets=["f7"], + fap_description="Fuzzer for lfrfid readers", fap_icon="icons/rfid_10px.png", fap_category="RFID", fap_private_libs=[ diff --git a/applications/external/multi_fuzzer/fuzzer.c b/applications/external/multi_fuzzer/fuzzer.c index 01a1d60df..bc9646873 100644 --- a/applications/external/multi_fuzzer/fuzzer.c +++ b/applications/external/multi_fuzzer/fuzzer.c @@ -49,6 +49,11 @@ PacsFuzzerApp* fuzzer_app_alloc() { app->popup = popup_alloc(); view_dispatcher_add_view(app->view_dispatcher, FuzzerViewIDPopup, popup_get_view(app->popup)); + // TextInput + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, FuzzerViewIDTextInput, text_input_get_view(app->text_input)); + // Main view app->main_view = fuzzer_view_main_alloc(); view_dispatcher_add_view( @@ -103,6 +108,10 @@ void fuzzer_app_free(PacsFuzzerApp* app) { view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDPopup); popup_free(app->popup); + // TextInput + view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDTextInput); + text_input_free(app->text_input); + scene_manager_free(app->scene_manager); view_dispatcher_free(app->view_dispatcher); diff --git a/applications/external/multi_fuzzer/fuzzer_i.h b/applications/external/multi_fuzzer/fuzzer_i.h index c8308adbd..46d6df13f 100644 --- a/applications/external/multi_fuzzer/fuzzer_i.h +++ b/applications/external/multi_fuzzer/fuzzer_i.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include #define FUZZ_TIME_DELAY_MAX (80) +#define KEY_NAME_SIZE 22 typedef struct { const char* custom_dict_extension; @@ -42,11 +44,13 @@ typedef struct { Popup* popup; DialogsApp* dialogs; + TextInput* text_input; FuzzerViewMain* main_view; FuzzerViewAttack* attack_view; FuzzerViewFieldEditor* field_editor_view; FuriString* file_path; + char key_name[KEY_NAME_SIZE + 1]; FuzzerState fuzzer_state; FuzzerConsts* fuzzer_const; diff --git a/applications/external/multi_fuzzer/helpers/fuzzer_custom_event.h b/applications/external/multi_fuzzer/helpers/fuzzer_custom_event.h index 321187722..5824e3c01 100644 --- a/applications/external/multi_fuzzer/helpers/fuzzer_custom_event.h +++ b/applications/external/multi_fuzzer/helpers/fuzzer_custom_event.h @@ -7,11 +7,21 @@ typedef enum { FuzzerCustomEventViewMainOk, FuzzerCustomEventViewMainPopupErr, - FuzzerCustomEventViewAttackBack, - FuzzerCustomEventViewAttackOk, - // FuzzerCustomEventViewAttackTick, // now not use FuzzerCustomEventViewAttackEnd, + FuzzerCustomEventViewAttackExit, + FuzzerCustomEventViewAttackRunAttack, + FuzzerCustomEventViewAttackPause, + FuzzerCustomEventViewAttackIdle, // Setup + FuzzerCustomEventViewAttackEmulateCurrent, + FuzzerCustomEventViewAttackSave, + FuzzerCustomEventViewAttackNextUid, + FuzzerCustomEventViewAttackPrevUid, + FuzzerCustomEventViewFieldEditorBack, FuzzerCustomEventViewFieldEditorOk, + + FuzzerCustomEventTextEditResult, + + FuzzerCustomEventPopupClosed, } FuzzerCustomEvent; \ No newline at end of file diff --git a/applications/external/multi_fuzzer/helpers/fuzzer_types.h b/applications/external/multi_fuzzer/helpers/fuzzer_types.h index bb608a5f1..a809cda01 100644 --- a/applications/external/multi_fuzzer/helpers/fuzzer_types.h +++ b/applications/external/multi_fuzzer/helpers/fuzzer_types.h @@ -10,7 +10,9 @@ typedef struct { typedef enum { FuzzerAttackStateOff = 0, FuzzerAttackStateIdle, - FuzzerAttackStateRunning, + FuzzerAttackStateAttacking, + FuzzerAttackStateEmulating, + FuzzerAttackStatePause, FuzzerAttackStateEnd, } FuzzerAttackState; @@ -23,6 +25,7 @@ typedef enum { typedef enum { FuzzerViewIDPopup, + FuzzerViewIDTextInput, FuzzerViewIDMain, FuzzerViewIDAttack, diff --git a/applications/external/multi_fuzzer/lib/worker/fake_worker.c b/applications/external/multi_fuzzer/lib/worker/fake_worker.c index 07b0479b4..d3d00d2db 100644 --- a/applications/external/multi_fuzzer/lib/worker/fake_worker.c +++ b/applications/external/multi_fuzzer/lib/worker/fake_worker.c @@ -1,4 +1,5 @@ #include "fake_worker.h" +#include "helpers/hardware_worker.h" #include "protocol_i.h" #include @@ -8,47 +9,27 @@ #include #define TAG "Fuzzer worker" +#define TOTAL_PROTOCOL_COUNT fuzzer_proto_get_count_of_protocols() +#define PROTOCOL_KEY_FOLDER EXT_PATH(PROTOCOL_KEY_FOLDER_NAME) -#if defined(RFID_125_PROTOCOL) - -#include -#include -#include - -#else - -#include -#include - -#endif - -#include +typedef uint8_t FuzzerWorkerPayload[MAX_PAYLOAD_SIZE]; struct FuzzerWorker { -#if defined(RFID_125_PROTOCOL) - LFRFIDWorker* proto_worker; - ProtocolId protocol_id; - ProtocolDict* protocols_items; -#else - iButtonWorker* proto_worker; - iButtonProtocolId protocol_id; // TODO - iButtonProtocols* protocols_items; - iButtonKey* key; -#endif + HardwareWorker* hw_worker; const FuzzerProtocol* protocol; + HwProtocolID* suported_proto; + + FuzzerWorkerPayload payload; + FuzzerWorkerAttackType attack_type; - uint16_t timer_idle_time_ms; - uint16_t timer_emu_time_ms; - - uint8_t payload[MAX_PAYLOAD_SIZE]; - Stream* uids_stream; uint16_t index; - uint8_t chusen_byte; + Stream* uids_stream; - bool treead_running; bool in_emu_phase; FuriTimer* timer; + uint16_t timer_idle_time_ms; + uint16_t timer_emu_time_ms; FuzzerWorkerUidChagedCallback tick_callback; void* tick_context; @@ -57,6 +38,85 @@ struct FuzzerWorker { void* end_context; }; +static bool fuzzer_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) { + if(!(protocol_index < TOTAL_PROTOCOL_COUNT)) { + return false; + } + + instance->protocol = &fuzzer_proto_items[protocol_index]; + return hardware_worker_set_protocol_id_by_name( + instance->hw_worker, fuzzer_proto_items[protocol_index].name); +} + +static FuzzerProtocolsID + fuzzer_worker_is_protocol_valid(FuzzerWorker* instance, HwProtocolID protocol_id) { + for(FuzzerProtocolsID i = 0; i < TOTAL_PROTOCOL_COUNT; i++) { + if(protocol_id == instance->suported_proto[i]) { + return i; + } + } + return TOTAL_PROTOCOL_COUNT; +} + +FuzzerWorkerLoadKeyState fuzzer_worker_load_key_from_file( + FuzzerWorker* instance, + FuzzerProtocolsID* protocol_index, + const char* filename) { + furi_assert(instance); + + FuzzerWorkerLoadKeyState res = FuzzerWorkerLoadKeyStateUnsuportedProto; + if(!hardware_worker_load_key_from_file(instance->hw_worker, filename)) { + FURI_LOG_E(TAG, "Load key file: cant load file"); + res = FuzzerWorkerLoadKeyStateBadFile; + } else { + FuzzerProtocolsID loaded_id = fuzzer_worker_is_protocol_valid( + instance, hardware_worker_get_protocol_id(instance->hw_worker)); + + if(!fuzzer_worker_set_protocol(instance, loaded_id)) { + FURI_LOG_E(TAG, "Load key file: Unsuported protocol"); + res = FuzzerWorkerLoadKeyStateUnsuportedProto; + } else { + if(*protocol_index != loaded_id) { + res = FuzzerWorkerLoadKeyStateDifferentProto; + } else { + res = FuzzerWorkerLoadKeyStateOk; + } + *protocol_index = loaded_id; + + hardware_worker_get_protocol_data( + instance->hw_worker, &instance->payload[0], MAX_PAYLOAD_SIZE); + } + } + + return res; +} + +static bool fuzer_worker_make_key_folder() { + Storage* storage = furi_record_open(RECORD_STORAGE); + + const bool res = storage_simply_mkdir(storage, PROTOCOL_KEY_FOLDER); + + furi_record_close(RECORD_STORAGE); + + return res; +} + +bool fuzzer_worker_save_key(FuzzerWorker* instance, const char* path) { + furi_assert(instance); + bool res = false; + + if(!fuzer_worker_make_key_folder()) { + FURI_LOG_E(TAG, "Cannot create key folder"); + } else if(!hardware_worker_save_key(instance->hw_worker, path)) { + FURI_LOG_E(TAG, "Cannot save key file"); + } else { + FURI_LOG_D(TAG, "Save key Success"); + res = true; + } + + return res; +} + static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) { furi_assert(instance); furi_assert(instance->protocol); @@ -67,7 +127,11 @@ static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) { switch(instance->attack_type) { case FuzzerWorkerAttackTypeDefaultDict: if(next) { - instance->index++; + if(instance->index < (protocol->dict.len - 1)) { + instance->index++; + } else { + break; + } } if(instance->index < protocol->dict.len) { memcpy( @@ -113,6 +177,7 @@ static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) { } break; } + furi_string_free(data_str); } break; @@ -128,18 +193,51 @@ static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) { default: break; } -#if defined(RFID_125_PROTOCOL) - protocol_dict_set_data( - instance->protocols_items, instance->protocol_id, instance->payload, MAX_PAYLOAD_SIZE); -#else - ibutton_key_set_protocol_id(instance->key, instance->protocol_id); - iButtonEditableData data; - ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data); - // TODO check data.size logic - data.size = MAX_PAYLOAD_SIZE; - memcpy(data.ptr, instance->payload, MAX_PAYLOAD_SIZE); // data.size); -#endif + if(res) { + hardware_worker_set_protocol_data( + instance->hw_worker, &instance->payload[0], protocol->data_size); + } + + return res; +} + +static bool fuzzer_worker_load_previous_key(FuzzerWorker* instance) { + furi_assert(instance); + furi_assert(instance->protocol); + bool res = false; + + const FuzzerProtocol* protocol = instance->protocol; + + switch(instance->attack_type) { + case FuzzerWorkerAttackTypeDefaultDict: + if(instance->index > 0) { + instance->index--; + memcpy( + instance->payload, + &protocol->dict.val[instance->index * protocol->data_size], + protocol->data_size); + res = true; + } + break; + + case FuzzerWorkerAttackTypeLoadFile: + if(instance->payload[instance->index] != 0x00) { + instance->payload[instance->index]--; + res = true; + } + + break; + + default: + break; + } + + if(res) { + hardware_worker_set_protocol_data( + instance->hw_worker, &instance->payload[0], protocol->data_size); + } + return res; } @@ -149,13 +247,7 @@ static void fuzzer_worker_on_tick_callback(void* context) { FuzzerWorker* instance = context; if(instance->in_emu_phase) { - if(instance->treead_running) { -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_stop(instance->proto_worker); -#else - ibutton_worker_stop(instance->proto_worker); -#endif - } + hardware_worker_stop(instance->hw_worker); instance->in_emu_phase = false; furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_idle_time_ms)); } else { @@ -165,13 +257,7 @@ static void fuzzer_worker_on_tick_callback(void* context) { instance->end_callback(instance->end_context); } } else { - if(instance->treead_running) { -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id); -#else - ibutton_worker_emulate_start(instance->proto_worker, instance->key); -#endif - } + hardware_worker_emulate_start(instance->hw_worker); instance->in_emu_phase = true; furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms)); if(instance->tick_callback) { @@ -190,24 +276,29 @@ void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output memcpy(output_key->data, instance->payload, instance->protocol->data_size); } -static void fuzzer_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) { - instance->protocol = &fuzzer_proto_items[protocol_index]; +bool fuzzer_worker_next_key(FuzzerWorker* instance) { + furi_assert(instance); + furi_assert(instance->protocol); -#if defined(RFID_125_PROTOCOL) - instance->protocol_id = - protocol_dict_get_protocol_by_name(instance->protocols_items, instance->protocol->name); -#else - // TODO iButtonProtocolIdInvalid check - instance->protocol_id = - ibutton_protocols_get_id_by_name(instance->protocols_items, instance->protocol->name); -#endif + return fuzzer_worker_load_key(instance, true); +} + +bool fuzzer_worker_previous_key(FuzzerWorker* instance) { + furi_assert(instance); + furi_assert(instance->protocol); + + return fuzzer_worker_load_previous_key(instance); } bool fuzzer_worker_init_attack_dict(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) { furi_assert(instance); bool res = false; - fuzzer_worker_set_protocol(instance, protocol_index); + + if(!fuzzer_worker_set_protocol(instance, protocol_index)) { + instance->attack_type = FuzzerWorkerAttackTypeMax; + return res; + } instance->attack_type = FuzzerWorkerAttackTypeDefaultDict; instance->index = 0; @@ -229,10 +320,15 @@ bool fuzzer_worker_init_attack_file_dict( furi_assert(file_path); bool res = false; - fuzzer_worker_set_protocol(instance, protocol_index); + + if(!fuzzer_worker_set_protocol(instance, protocol_index)) { + instance->attack_type = FuzzerWorkerAttackTypeMax; + return res; + } Storage* storage = furi_record_open(RECORD_STORAGE); instance->uids_stream = buffered_file_stream_alloc(storage); + furi_record_close(RECORD_STORAGE); if(!buffered_file_stream_open( instance->uids_stream, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) { @@ -246,7 +342,7 @@ bool fuzzer_worker_init_attack_file_dict( if(!fuzzer_worker_load_key(instance, false)) { instance->attack_type = FuzzerWorkerAttackTypeMax; buffered_file_stream_close(instance->uids_stream); - furi_record_close(RECORD_STORAGE); + stream_free(instance->uids_stream); } else { res = true; } @@ -262,88 +358,49 @@ bool fuzzer_worker_init_attack_bf_byte( furi_assert(instance); bool res = false; - fuzzer_worker_set_protocol(instance, protocol_index); + if(!fuzzer_worker_set_protocol(instance, protocol_index)) { + instance->attack_type = FuzzerWorkerAttackTypeMax; + return res; + } instance->attack_type = FuzzerWorkerAttackTypeLoadFile; instance->index = chusen; memcpy(instance->payload, new_uid->data, instance->protocol->data_size); - res = true; + hardware_worker_set_protocol_data( + instance->hw_worker, &instance->payload[0], instance->protocol->data_size); - return res; -} - -// TODO make it protocol independent -bool fuzzer_worker_load_key_from_file( - FuzzerWorker* instance, - FuzzerProtocolsID protocol_index, - const char* filename) { - furi_assert(instance); - - bool res = false; - fuzzer_worker_set_protocol(instance, protocol_index); - -#if defined(RFID_125_PROTOCOL) - ProtocolId loaded_proto_id = lfrfid_dict_file_load(instance->protocols_items, filename); - if(loaded_proto_id == PROTOCOL_NO) { - // Err Cant load file - FURI_LOG_W(TAG, "Cant load file"); - } else if(instance->protocol_id != loaded_proto_id) { // Err wrong protocol - FURI_LOG_W(TAG, "Wrong protocol"); - FURI_LOG_W( - TAG, - "Selected: %s Loaded: %s", - instance->protocol->name, - protocol_dict_get_name(instance->protocols_items, loaded_proto_id)); - } else { - protocol_dict_get_data( - instance->protocols_items, instance->protocol_id, instance->payload, MAX_PAYLOAD_SIZE); - res = true; - } -#else - if(!ibutton_protocols_load(instance->protocols_items, instance->key, filename)) { - // Err Cant load file - FURI_LOG_W(TAG, "Cant load file"); - } else { - if(instance->protocol_id != ibutton_key_get_protocol_id(instance->key)) { - // Err wrong protocol - FURI_LOG_W(TAG, "Wrong protocol"); - FURI_LOG_W( - TAG, - "Selected: %s Loaded: %s", - instance->protocol->name, - ibutton_protocols_get_name( - instance->protocols_items, ibutton_key_get_protocol_id(instance->key))); - } else { - iButtonEditableData data; - ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data); - memcpy(instance->payload, data.ptr, data.size); - res = true; - } - } -#endif - - return res; + return true; } FuzzerWorker* fuzzer_worker_alloc() { FuzzerWorker* instance = malloc(sizeof(FuzzerWorker)); -#if defined(RFID_125_PROTOCOL) - instance->protocols_items = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); + instance->hw_worker = hardware_worker_alloc(); + hardware_worker_start_thread(instance->hw_worker); - instance->proto_worker = lfrfid_worker_alloc(instance->protocols_items); -#else - instance->protocols_items = ibutton_protocols_alloc(); - instance->key = - ibutton_key_alloc(ibutton_protocols_get_max_data_size(instance->protocols_items)); + instance->suported_proto = malloc(sizeof(HwProtocolID) * TOTAL_PROTOCOL_COUNT); + + for(uint8_t i = 0; i < TOTAL_PROTOCOL_COUNT; i++) { + if(!hardware_worker_set_protocol_id_by_name( + instance->hw_worker, fuzzer_proto_items[i].name)) { + // Check protocol support + FURI_LOG_E(TAG, "Not supported protocol name: %s", fuzzer_proto_items[i].name); + furi_crash("Not supported protocol name"); + } else { + instance->suported_proto[i] = hardware_worker_get_protocol_id(instance->hw_worker); + FURI_LOG_D( + TAG, + "%u: %15s Protocol_id: %lu", + i + 1, + fuzzer_proto_items[i].name, + instance->suported_proto[i]); + } + } - instance->proto_worker = ibutton_worker_alloc(instance->protocols_items); -#endif instance->attack_type = FuzzerWorkerAttackTypeMax; instance->index = 0; - instance->treead_running = false; instance->in_emu_phase = false; memset(instance->payload, 0x00, sizeof(instance->payload)); @@ -364,16 +421,10 @@ void fuzzer_worker_free(FuzzerWorker* instance) { furi_timer_free(instance->timer); -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_free(instance->proto_worker); + free(instance->suported_proto); - protocol_dict_free(instance->protocols_items); -#else - ibutton_worker_free(instance->proto_worker); - - ibutton_key_free(instance->key); - ibutton_protocols_free(instance->protocols_items); -#endif + hardware_worker_stop_thread(instance->hw_worker); + hardware_worker_free(instance->hw_worker); free(instance); } @@ -399,25 +450,8 @@ bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_ instance->timer_emu_time_ms, instance->timer_idle_time_ms); - if(!instance->treead_running) { -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_start_thread(instance->proto_worker); -#else - ibutton_worker_start_thread(instance->proto_worker); -#endif - FURI_LOG_D(TAG, "Worker Starting"); - instance->treead_running = true; - } else { - FURI_LOG_D(TAG, "Worker UnPaused"); - } + hardware_worker_emulate_start(instance->hw_worker); -#if defined(RFID_125_PROTOCOL) - // lfrfid_worker_start_thread(instance->proto_worker); - lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id); -#else - // ibutton_worker_start_thread(instance->proto_worker); - ibutton_worker_emulate_start(instance->proto_worker, instance->key); -#endif instance->in_emu_phase = true; furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms)); return true; @@ -425,19 +459,18 @@ bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_ return false; } +void fuzzer_worker_start_emulate(FuzzerWorker* instance) { + furi_assert(instance); + + hardware_worker_emulate_start(instance->hw_worker); +} + void fuzzer_worker_pause(FuzzerWorker* instance) { furi_assert(instance); furi_timer_stop(instance->timer); - if(instance->treead_running) { -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_stop(instance->proto_worker); -#else - ibutton_worker_stop(instance->proto_worker); -#endif - FURI_LOG_D(TAG, "Worker Paused"); - } + hardware_worker_stop(instance->hw_worker); } void fuzzer_worker_stop(FuzzerWorker* instance) { @@ -445,25 +478,15 @@ void fuzzer_worker_stop(FuzzerWorker* instance) { furi_timer_stop(instance->timer); - if(instance->treead_running) { -#if defined(RFID_125_PROTOCOL) - lfrfid_worker_stop(instance->proto_worker); - lfrfid_worker_stop_thread(instance->proto_worker); -#else - ibutton_worker_stop(instance->proto_worker); - ibutton_worker_stop_thread(instance->proto_worker); -#endif - FURI_LOG_D(TAG, "Worker Stopping"); - instance->treead_running = false; - } + hardware_worker_stop(instance->hw_worker); if(instance->attack_type == FuzzerWorkerAttackTypeLoadFileCustomUids) { buffered_file_stream_close(instance->uids_stream); - furi_record_close(RECORD_STORAGE); + stream_free(instance->uids_stream); instance->attack_type = FuzzerWorkerAttackTypeMax; } - // TODO anything else + // TODO anything else } void fuzzer_worker_set_uid_chaged_callback( diff --git a/applications/external/multi_fuzzer/lib/worker/fake_worker.h b/applications/external/multi_fuzzer/lib/worker/fake_worker.h index 8b934f300..9aecb56b5 100644 --- a/applications/external/multi_fuzzer/lib/worker/fake_worker.h +++ b/applications/external/multi_fuzzer/lib/worker/fake_worker.h @@ -12,6 +12,14 @@ typedef enum { FuzzerWorkerAttackTypeMax, } FuzzerWorkerAttackType; +typedef enum { + FuzzerWorkerLoadKeyStateBadFile = -2, + FuzzerWorkerLoadKeyStateUnsuportedProto, + FuzzerWorkerLoadKeyStateOk = 0, + FuzzerWorkerLoadKeyStateDifferentProto, + +} FuzzerWorkerLoadKeyState; + typedef void (*FuzzerWorkerUidChagedCallback)(void* context); typedef void (*FuzzerWorkerEndCallback)(void* context); @@ -48,6 +56,8 @@ bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_ */ void fuzzer_worker_stop(FuzzerWorker* instance); +void fuzzer_worker_start_emulate(FuzzerWorker* instance); + /** * Suspend emulation * @@ -100,6 +110,9 @@ bool fuzzer_worker_init_attack_bf_byte( */ void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output_key); +bool fuzzer_worker_next_key(FuzzerWorker* instance); +bool fuzzer_worker_previous_key(FuzzerWorker* instance); + /** * Load UID from Flipper Format Key file * @@ -108,11 +121,13 @@ void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output * @param filename file path to the key file * @return bool True if loading is successful */ -bool fuzzer_worker_load_key_from_file( +FuzzerWorkerLoadKeyState fuzzer_worker_load_key_from_file( FuzzerWorker* instance, - FuzzerProtocolsID protocol_index, + FuzzerProtocolsID* protocol_index, const char* filename); +bool fuzzer_worker_save_key(FuzzerWorker* instance, const char* path); + /** * Set callback for uid changed * diff --git a/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.c b/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.c new file mode 100644 index 000000000..e42996afa --- /dev/null +++ b/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.c @@ -0,0 +1,198 @@ +#include "hardware_worker.h" +#include "furi.h" + +#if defined(RFID_125_PROTOCOL) + +#include +#include + +#else + +#include +#include + +#endif + +#define TAG "Fuzzer HW worker" + +struct HardwareWorker { +#if defined(RFID_125_PROTOCOL) + LFRFIDWorker* proto_worker; + ProtocolId protocol_id; + ProtocolDict* protocols_items; +#else + iButtonWorker* proto_worker; + iButtonProtocolId protocol_id; + iButtonProtocols* protocols_items; + iButtonKey* key; +#endif +}; + +HardwareWorker* hardware_worker_alloc() { + HardwareWorker* instance = malloc(sizeof(HardwareWorker)); +#if defined(RFID_125_PROTOCOL) + instance->protocols_items = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax); + + instance->proto_worker = lfrfid_worker_alloc(instance->protocols_items); +#else + instance->protocols_items = ibutton_protocols_alloc(); + instance->key = + ibutton_key_alloc(ibutton_protocols_get_max_data_size(instance->protocols_items)); + + instance->proto_worker = ibutton_worker_alloc(instance->protocols_items); +#endif + return instance; +} + +void hardware_worker_free(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + lfrfid_worker_free(instance->proto_worker); + + protocol_dict_free(instance->protocols_items); +#else + ibutton_worker_free(instance->proto_worker); + + ibutton_key_free(instance->key); + ibutton_protocols_free(instance->protocols_items); +#endif + free(instance); +} + +void hardware_worker_start_thread(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + lfrfid_worker_start_thread(instance->proto_worker); +#else + ibutton_worker_start_thread(instance->proto_worker); +#endif +} + +void hardware_worker_stop_thread(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + lfrfid_worker_stop(instance->proto_worker); + lfrfid_worker_stop_thread(instance->proto_worker); +#else + ibutton_worker_stop(instance->proto_worker); + ibutton_worker_stop_thread(instance->proto_worker); +#endif +} + +void hardware_worker_emulate_start(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id); +#else + ibutton_worker_emulate_start(instance->proto_worker, instance->key); +#endif +} + +void hardware_worker_stop(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + lfrfid_worker_stop(instance->proto_worker); +#else + ibutton_worker_stop(instance->proto_worker); +#endif +} + +void hardware_worker_set_protocol_data( + HardwareWorker* instance, + uint8_t* payload, + uint8_t payload_size) { +#if defined(RFID_125_PROTOCOL) + protocol_dict_set_data( + instance->protocols_items, instance->protocol_id, payload, payload_size); +#else + ibutton_key_set_protocol_id(instance->key, instance->protocol_id); + iButtonEditableData data; + ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data); + + furi_check(payload_size >= data.size); + memcpy(data.ptr, payload, data.size); +#endif +} + +void hardware_worker_get_protocol_data( + HardwareWorker* instance, + uint8_t* payload, + uint8_t payload_size) { +#if defined(RFID_125_PROTOCOL) + protocol_dict_get_data( + instance->protocols_items, instance->protocol_id, payload, payload_size); +#else + iButtonEditableData data; + ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data); + furi_check(payload_size >= data.size); + memcpy(payload, data.ptr, data.size); +#endif +} + +static bool hardware_worker_protocol_is_valid(HardwareWorker* instance) { +#if defined(RFID_125_PROTOCOL) + if(instance->protocol_id != PROTOCOL_NO) { + return true; + } +#else + if(instance->protocol_id != iButtonProtocolIdInvalid) { + return true; + } +#endif + return false; +} + +bool hardware_worker_set_protocol_id_by_name(HardwareWorker* instance, const char* protocol_name) { +#if defined(RFID_125_PROTOCOL) + instance->protocol_id = + protocol_dict_get_protocol_by_name(instance->protocols_items, protocol_name); + return (instance->protocol_id != PROTOCOL_NO); +#else + instance->protocol_id = + ibutton_protocols_get_id_by_name(instance->protocols_items, protocol_name); + return (instance->protocol_id != iButtonProtocolIdInvalid); +#endif +} + +HwProtocolID hardware_worker_get_protocol_id(HardwareWorker* instance) { + if(hardware_worker_protocol_is_valid(instance)) { + return instance->protocol_id; + } + return -1; +} + +bool hardware_worker_load_key_from_file(HardwareWorker* instance, const char* filename) { + bool res = false; + +#if defined(RFID_125_PROTOCOL) + ProtocolId loaded_proto_id = lfrfid_dict_file_load(instance->protocols_items, filename); + if(loaded_proto_id == PROTOCOL_NO) { + // Err Cant load file + FURI_LOG_W(TAG, "Cant load file"); + } else { + instance->protocol_id = loaded_proto_id; + res = true; + } +#else + + if(!ibutton_protocols_load(instance->protocols_items, instance->key, filename)) { + // Err Cant load file + FURI_LOG_W(TAG, "Cant load file"); + } else { + instance->protocol_id = ibutton_key_get_protocol_id(instance->key); + res = true; + } + +#endif + + return res; +} + +bool hardware_worker_save_key(HardwareWorker* instance, const char* path) { + furi_assert(instance); + bool res; + +#if defined(RFID_125_PROTOCOL) + res = lfrfid_dict_file_save(instance->protocols_items, instance->protocol_id, path); +#else + + res = ibutton_protocols_save(instance->protocols_items, instance->key, path); +#endif + + return res; +} \ No newline at end of file diff --git a/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.h b/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.h new file mode 100644 index 000000000..f2cd3842e --- /dev/null +++ b/applications/external/multi_fuzzer/lib/worker/helpers/hardware_worker.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#if defined(RFID_125_PROTOCOL) + +#include +typedef ProtocolId HwProtocolID; + +#else + +#include +typedef iButtonProtocolId HwProtocolID; + +#endif + +typedef struct HardwareWorker HardwareWorker; + +HardwareWorker* hardware_worker_alloc(); + +void hardware_worker_free(HardwareWorker* instance); + +void hardware_worker_start_thread(HardwareWorker* instance); + +void hardware_worker_stop_thread(HardwareWorker* instance); + +void hardware_worker_emulate_start(HardwareWorker* instance); + +void hardware_worker_stop(HardwareWorker* instance); + +void hardware_worker_set_protocol_data( + HardwareWorker* instance, + uint8_t* payload, + uint8_t payload_size); + +void hardware_worker_get_protocol_data( + HardwareWorker* instance, + uint8_t* payload, + uint8_t payload_size); + +bool hardware_worker_set_protocol_id_by_name(HardwareWorker* instance, const char* protocol_name); + +HwProtocolID hardware_worker_get_protocol_id(HardwareWorker* instance); + +bool hardware_worker_load_key_from_file(HardwareWorker* instance, const char* filename); + +bool hardware_worker_save_key(HardwareWorker* instance, const char* path); \ No newline at end of file diff --git a/applications/external/multi_fuzzer/lib/worker/protocol.c b/applications/external/multi_fuzzer/lib/worker/protocol.c index a64fe8767..5284f87f1 100644 --- a/applications/external/multi_fuzzer/lib/worker/protocol.c +++ b/applications/external/multi_fuzzer/lib/worker/protocol.c @@ -152,79 +152,79 @@ const uint8_t uid_list_h10301[][H10301_DATA_SIZE] = { #if defined(RFID_125_PROTOCOL) const FuzzerProtocol fuzzer_proto_items[] = { - [EM4100] = - { - .name = "EM4100", - .data_size = EM4100_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_em4100, - .len = COUNT_OF(uid_list_em4100), - }, - }, - [HIDProx] = - { - .name = "HIDProx", - .data_size = HIDProx_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_hid, - .len = COUNT_OF(uid_list_hid), - }, - }, - [PAC] = - { - .name = "PAC/Stanley", - .data_size = PAC_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_pac, - .len = COUNT_OF(uid_list_pac), - }, - }, - [H10301] = - { - .name = "H10301", - .data_size = H10301_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_h10301, - .len = COUNT_OF(uid_list_h10301), - }, - }, + // EM4100 + { + .name = "EM4100", + .data_size = EM4100_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_em4100, + .len = COUNT_OF(uid_list_em4100), + }, + }, + // HIDProx + { + .name = "HIDProx", + .data_size = HIDProx_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_hid, + .len = COUNT_OF(uid_list_hid), + }, + }, + // PAC + { + .name = "PAC/Stanley", + .data_size = PAC_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_pac, + .len = COUNT_OF(uid_list_pac), + }, + }, + // H10301 + { + .name = "H10301", + .data_size = H10301_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_h10301, + .len = COUNT_OF(uid_list_h10301), + }, + }, }; #else const FuzzerProtocol fuzzer_proto_items[] = { - [DS1990] = - { - .name = "DS1990", - .data_size = DS1990_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_ds1990, - .len = COUNT_OF(uid_list_ds1990), - }, - }, - [Metakom] = - { - .name = "Metakom", - .data_size = Metakom_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_metakom, - .len = COUNT_OF(uid_list_metakom), - }, - }, - [Cyfral] = - { - .name = "Cyfral", - .data_size = Cyfral_DATA_SIZE, - .dict = - { - .val = (const uint8_t*)&uid_list_cyfral, - .len = COUNT_OF(uid_list_cyfral), - }, - }, + // DS1990 + { + .name = "DS1990", + .data_size = DS1990_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_ds1990, + .len = COUNT_OF(uid_list_ds1990), + }, + }, + // Metakom + { + .name = "Metakom", + .data_size = Metakom_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_metakom, + .len = COUNT_OF(uid_list_metakom), + }, + }, + // Cyfral + { + .name = "Cyfral", + .data_size = Cyfral_DATA_SIZE, + .dict = + { + .val = (const uint8_t*)&uid_list_cyfral, + .len = COUNT_OF(uid_list_cyfral), + }, + }, }; #endif diff --git a/applications/external/multi_fuzzer/lib/worker/protocol.h b/applications/external/multi_fuzzer/lib/worker/protocol.h index 9c5315d00..e7c264b54 100644 --- a/applications/external/multi_fuzzer/lib/worker/protocol.h +++ b/applications/external/multi_fuzzer/lib/worker/protocol.h @@ -6,18 +6,7 @@ typedef struct FuzzerPayload FuzzerPayload; -typedef enum { -#if defined(RFID_125_PROTOCOL) - EM4100, - HIDProx, - PAC, - H10301, -#else - DS1990, - Metakom, - Cyfral, -#endif -} FuzzerProtocolsID; +typedef uint8_t FuzzerProtocolsID; typedef enum { FuzzerAttackIdDefaultValues = 0, @@ -51,8 +40,16 @@ void fuzzer_payload_free(FuzzerPayload*); */ uint8_t fuzzer_proto_get_max_data_size(); -// TODO add description +/** + * Get recomended/default emulation time + * @return Default emulation time + */ uint8_t fuzzer_proto_get_def_emu_time(); + +/** + * Get recomended/default idle time + * @return Default idle time + */ uint8_t fuzzer_proto_get_def_idle_time(); /** diff --git a/applications/external/multi_fuzzer/lib/worker/protocol_i.h b/applications/external/multi_fuzzer/lib/worker/protocol_i.h index 2f1c65fd7..6679b6d7f 100644 --- a/applications/external/multi_fuzzer/lib/worker/protocol_i.h +++ b/applications/external/multi_fuzzer/lib/worker/protocol_i.h @@ -7,11 +7,19 @@ #define PROTOCOL_DEF_IDLE_TIME (4) #define PROTOCOL_DEF_EMU_TIME (5) #define PROTOCOL_TIME_DELAY_MIN PROTOCOL_DEF_IDLE_TIME + PROTOCOL_DEF_EMU_TIME + +#define PROTOCOL_KEY_FOLDER_NAME "lfrfid" +#define PROTOCOL_KEY_EXTENSION ".rfid" + #else + #define MAX_PAYLOAD_SIZE (8) #define PROTOCOL_DEF_IDLE_TIME (2) #define PROTOCOL_DEF_EMU_TIME (2) #define PROTOCOL_TIME_DELAY_MIN PROTOCOL_DEF_IDLE_TIME + PROTOCOL_DEF_EMU_TIME + +#define PROTOCOL_KEY_FOLDER_NAME "ibutton" +#define PROTOCOL_KEY_EXTENSION ".ibtn" #endif typedef struct ProtoDict ProtoDict; diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_attack.c b/applications/external/multi_fuzzer/scenes/fuzzer_scene_attack.c index 6424e62b5..0b0f68093 100644 --- a/applications/external/multi_fuzzer/scenes/fuzzer_scene_attack.c +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_attack.c @@ -1,7 +1,7 @@ #include "../fuzzer_i.h" #include "../helpers/fuzzer_custom_event.h" -const NotificationSequence sequence_one_green_50_on_blink_blue = { +const NotificationSequence sequence_one_red_50_on_blink_blue = { &message_red_255, &message_delay_50, &message_red_0, @@ -28,35 +28,38 @@ static void fuzzer_scene_attack_set_state(PacsFuzzerApp* app, FuzzerAttackState switch(state) { case FuzzerAttackStateIdle: notification_message(app->notifications, &sequence_blink_stop); - fuzzer_view_attack_pause(app->attack_view); break; - case FuzzerAttackStateRunning: + case FuzzerAttackStateAttacking: + notification_message(app->notifications, &sequence_blink_start_blue); + break; + case FuzzerAttackStateEmulating: notification_message(app->notifications, &sequence_blink_start_blue); - fuzzer_view_attack_start(app->attack_view); break; case FuzzerAttackStateEnd: notification_message(app->notifications, &sequence_blink_stop); notification_message(app->notifications, &sequence_single_vibro); - fuzzer_view_attack_end(app->attack_view); break; case FuzzerAttackStateOff: notification_message(app->notifications, &sequence_blink_stop); - fuzzer_view_attack_stop(app->attack_view); + break; + + case FuzzerAttackStatePause: + notification_message(app->notifications, &sequence_blink_stop); break; } + + fuzzer_view_update_state(app->attack_view, state); } void fuzzer_scene_attack_worker_tick_callback(void* context) { furi_assert(context); PacsFuzzerApp* app = context; - notification_message(app->notifications, &sequence_one_green_50_on_blink_blue); + notification_message(app->notifications, &sequence_one_red_50_on_blink_blue); fuzzer_scene_attack_update_uid(app); - - // view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventViewAttackTick); } void fuzzer_scene_attack_worker_end_callback(void* context) { @@ -100,48 +103,53 @@ bool fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == FuzzerCustomEventViewAttackBack) { - if(scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) == - FuzzerAttackStateRunning) { - // Pause if attack running - fuzzer_worker_pause(app->worker); + if(event.event == FuzzerCustomEventViewAttackExit) { + // Exit + fuzzer_worker_stop(app->worker); - fuzzer_scene_attack_set_state(app, FuzzerAttackStateIdle); + fuzzer_scene_attack_set_state(app, FuzzerAttackStateOff); + if(!scene_manager_previous_scene(app->scene_manager)) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } + } else if(event.event == FuzzerCustomEventViewAttackRunAttack) { + if(fuzzer_worker_start( + app->worker, + fuzzer_view_attack_get_time_delay(app->attack_view), + fuzzer_view_attack_get_emu_time(app->attack_view))) { + fuzzer_scene_attack_set_state(app, FuzzerAttackStateAttacking); } else { - // Exit - fuzzer_worker_stop(app->worker); - - fuzzer_scene_attack_set_state(app, FuzzerAttackStateOff); - if(!scene_manager_previous_scene(app->scene_manager)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } + // Error? } - consumed = true; - } else if(event.event == FuzzerCustomEventViewAttackOk) { - if(scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) == - FuzzerAttackStateIdle) { - // Start or Continue Attack - if(fuzzer_worker_start( - app->worker, - fuzzer_view_attack_get_time_delay(app->attack_view), - fuzzer_view_attack_get_emu_time(app->attack_view))) { - fuzzer_scene_attack_set_state(app, FuzzerAttackStateRunning); - } else { - // Error? - } - } else if( - scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) == - FuzzerAttackStateRunning) { - // Pause if attack running - fuzzer_worker_pause(app->worker); + } else if(event.event == FuzzerCustomEventViewAttackEmulateCurrent) { + fuzzer_worker_start_emulate(app->worker); - fuzzer_scene_attack_set_state(app, FuzzerAttackStateIdle); + fuzzer_scene_attack_set_state(app, FuzzerAttackStateEmulating); + } else if(event.event == FuzzerCustomEventViewAttackPause) { + fuzzer_worker_pause(app->worker); + + fuzzer_scene_attack_set_state(app, FuzzerAttackStatePause); + } else if(event.event == FuzzerCustomEventViewAttackIdle) { + fuzzer_worker_pause(app->worker); + + fuzzer_scene_attack_set_state(app, FuzzerAttackStateIdle); + } else if(event.event == FuzzerCustomEventViewAttackNextUid) { + if(fuzzer_worker_next_key(app->worker)) { + fuzzer_scene_attack_update_uid(app); + } else { + notification_message(app->notifications, &sequence_blink_red_100); } - consumed = true; - // } else if(event.event == FuzzerCustomEventViewAttackTick) { - // consumed = true; - } else if(event.event == FuzzerCustomEventViewAttackEnd) { + } else if(event.event == FuzzerCustomEventViewAttackPrevUid) { + if(fuzzer_worker_previous_key(app->worker)) { + fuzzer_scene_attack_update_uid(app); + } else { + notification_message(app->notifications, &sequence_blink_red_100); + } + } else if(event.event == FuzzerCustomEventViewAttackSave) { + scene_manager_next_scene(app->scene_manager, FuzzerSceneSaveName); + } + // Callback from worker + else if(event.event == FuzzerCustomEventViewAttackEnd) { fuzzer_scene_attack_set_state(app, FuzzerAttackStateEnd); consumed = true; } diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_config.h b/applications/external/multi_fuzzer/scenes/fuzzer_scene_config.h index 711ebe1c4..b1ad9d609 100644 --- a/applications/external/multi_fuzzer/scenes/fuzzer_scene_config.h +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_config.h @@ -1,3 +1,5 @@ ADD_SCENE(fuzzer, main, Main) ADD_SCENE(fuzzer, attack, Attack) -ADD_SCENE(fuzzer, field_editor, FieldEditor) \ No newline at end of file +ADD_SCENE(fuzzer, field_editor, FieldEditor) +ADD_SCENE(fuzzer, save_name, SaveName) +ADD_SCENE(fuzzer, save_success, SaveSuccess) \ No newline at end of file diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_field_editor.c b/applications/external/multi_fuzzer/scenes/fuzzer_scene_field_editor.c index ccea123dc..a33e337cc 100644 --- a/applications/external/multi_fuzzer/scenes/fuzzer_scene_field_editor.c +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_field_editor.c @@ -22,6 +22,7 @@ void fuzzer_scene_field_editor_on_enter(void* context) { break; case FuzzerFieldEditorStateEditingOff: + memset(app->payload->data, 0x00, app->payload->data_size); fuzzer_view_field_editor_reset_data(app->field_editor_view, app->payload, false); break; diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_main.c b/applications/external/multi_fuzzer/scenes/fuzzer_scene_main.c index 0d074a121..7c53d098a 100644 --- a/applications/external/multi_fuzzer/scenes/fuzzer_scene_main.c +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_main.c @@ -2,6 +2,7 @@ #include "../helpers/fuzzer_custom_event.h" #include "../lib/worker/protocol.h" +#define TAG "Fuzzer main menu" void fuzzer_scene_main_callback(FuzzerCustomEvent event, void* context) { furi_assert(context); @@ -35,7 +36,7 @@ static bool fuzzer_scene_main_load_custom_dict(void* context) { return res; } -static bool fuzzer_scene_main_load_key(void* context) { +static bool fuzzer_scene_main_load_key_dialog(void* context) { furi_assert(context); PacsFuzzerApp* app = context; @@ -134,22 +135,32 @@ bool fuzzer_scene_main_on_event(void* context, SceneManagerEvent event) { break; case FuzzerAttackIdLoadFile: - if(!fuzzer_scene_main_load_key(app)) { + if(!fuzzer_scene_main_load_key_dialog(app)) { break; } else { - if(fuzzer_worker_load_key_from_file( - app->worker, - app->fuzzer_state.proto_index, - furi_string_get_cstr(app->file_path))) { + switch(fuzzer_worker_load_key_from_file( + app->worker, + &app->fuzzer_state.proto_index, + furi_string_get_cstr(app->file_path))) { + case FuzzerWorkerLoadKeyStateOk: + case FuzzerWorkerLoadKeyStateDifferentProto: scene_manager_set_scene_state( app->scene_manager, FuzzerSceneFieldEditor, FuzzerFieldEditorStateEditingOn); scene_manager_next_scene(app->scene_manager, FuzzerSceneFieldEditor); - FURI_LOG_I("Scene", "Load ok"); - } else { - fuzzer_scene_main_show_error(app, "Unsupported protocol\nor broken file"); - FURI_LOG_W("Scene", "Load err"); + FURI_LOG_I(TAG, "Load ok"); + break; + + case FuzzerWorkerLoadKeyStateBadFile: + fuzzer_scene_main_show_error(app, "Cant load\nor broken file"); + FURI_LOG_E(TAG, "Cant load or broken file"); + break; + + case FuzzerWorkerLoadKeyStateUnsuportedProto: + fuzzer_scene_main_show_error(app, "Unsupported protocol"); + FURI_LOG_E(TAG, "Unsupported protocol"); + break; } } break; diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_name.c b/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_name.c new file mode 100644 index 000000000..983bf0a58 --- /dev/null +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_name.c @@ -0,0 +1,67 @@ +#include "../fuzzer_i.h" + +#include +#include + +static void fuzzer_scene_save_name_text_input_callback(void* context) { + PacsFuzzerApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventTextEditResult); +} + +void fuzzer_scene_save_name_on_enter(void* context) { + PacsFuzzerApp* app = context; + TextInput* text_input = app->text_input; + + set_random_name(app->key_name, KEY_NAME_SIZE); + + text_input_set_header_text(text_input, "Name the key"); + text_input_set_result_callback( + text_input, + fuzzer_scene_save_name_text_input_callback, + app, + app->key_name, + KEY_NAME_SIZE, + false); + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + app->fuzzer_const->path_key_folder, app->fuzzer_const->key_extension, app->key_name); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDTextInput); +} + +bool fuzzer_scene_save_name_on_event(void* context, SceneManagerEvent event) { + PacsFuzzerApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == FuzzerCustomEventTextEditResult) { + consumed = true; + furi_string_printf( + app->file_path, + "%s/%s%s", + app->fuzzer_const->path_key_folder, + app->key_name, + app->fuzzer_const->key_extension); + + if(fuzzer_worker_save_key(app->worker, furi_string_get_cstr(app->file_path))) { + scene_manager_next_scene(app->scene_manager, FuzzerSceneSaveSuccess); + } else { + scene_manager_previous_scene(app->scene_manager); + } + } + } + + return consumed; +} + +void fuzzer_scene_save_name_on_exit(void* context) { + PacsFuzzerApp* app = context; + TextInput* text_input = app->text_input; + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + + text_input_reset(text_input); +} diff --git a/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_success.c b/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_success.c new file mode 100644 index 000000000..773ba6ddc --- /dev/null +++ b/applications/external/multi_fuzzer/scenes/fuzzer_scene_save_success.c @@ -0,0 +1,44 @@ +#include "../fuzzer_i.h" + +static void fuzzer_scene_save_popup_timeout_callback(void* context) { + PacsFuzzerApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventPopupClosed); +} + +void fuzzer_scene_save_success_on_enter(void* context) { + PacsFuzzerApp* app = context; + Popup* popup = app->popup; + + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); + popup_set_context(popup, app); + popup_set_callback(popup, fuzzer_scene_save_popup_timeout_callback); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDPopup); +} + +bool fuzzer_scene_save_success_on_event(void* context, SceneManagerEvent event) { + PacsFuzzerApp* app = context; + bool consumed = false; + + if((event.type == SceneManagerEventTypeBack) || + ((event.type == SceneManagerEventTypeCustom) && + (event.event == FuzzerCustomEventPopupClosed))) { + bool result = scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, FuzzerSceneAttack); + if(!result) { + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, FuzzerSceneMain); + } + consumed = true; + } + + return consumed; +} + +void fuzzer_scene_save_success_on_exit(void* context) { + PacsFuzzerApp* app = context; + + popup_reset(app->popup); +} diff --git a/applications/external/multi_fuzzer/views/attack.c b/applications/external/multi_fuzzer/views/attack.c index 87aa9f659..4748c3686 100644 --- a/applications/external/multi_fuzzer/views/attack.c +++ b/applications/external/multi_fuzzer/views/attack.c @@ -6,7 +6,12 @@ #define ATTACK_SCENE_MAX_UID_LENGTH 25 #define UID_MAX_DISPLAYED_LEN (8U) -#define LIFT_RIGHT_OFFSET (3) +#define LEFT_RIGHT_OFFSET (3U) + +#define LINE_1_Y (12U) +#define LINE_2_Y (24U) +#define LINE_3_Y (36U) +#define LINE_4_Y (48U) struct FuzzerViewAttack { View* view; @@ -60,44 +65,11 @@ void fuzzer_view_attack_set_uid(FuzzerViewAttack* view, const FuzzerPayload* uid true); } -void fuzzer_view_attack_start(FuzzerViewAttack* view) { +void fuzzer_view_update_state(FuzzerViewAttack* view, FuzzerAttackState state) { furi_assert(view); with_view_model( - view->view, - FuzzerViewAttackModel * model, - { model->attack_state = FuzzerAttackStateRunning; }, - true); -} - -void fuzzer_view_attack_stop(FuzzerViewAttack* view) { - furi_assert(view); - - with_view_model( - view->view, - FuzzerViewAttackModel * model, - { model->attack_state = FuzzerAttackStateOff; }, - true); -} - -void fuzzer_view_attack_pause(FuzzerViewAttack* view) { - furi_assert(view); - - with_view_model( - view->view, - FuzzerViewAttackModel * model, - { model->attack_state = FuzzerAttackStateIdle; }, - true); -} - -void fuzzer_view_attack_end(FuzzerViewAttack* view) { - furi_assert(view); - - with_view_model( - view->view, - FuzzerViewAttackModel * model, - { model->attack_state = FuzzerAttackStateEnd; }, - true); + view->view, FuzzerViewAttackModel * model, { model->attack_state = state; }, true); } void fuzzer_view_attack_set_callback( @@ -110,35 +82,31 @@ void fuzzer_view_attack_set_callback( view_attack->context = context; } -void fuzzer_view_attack_draw(Canvas* canvas, FuzzerViewAttackModel* model) { - char temp_str[50]; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, model->attack_name); - +static void + fuzzer_view_attack_draw_time_delays_line(Canvas* canvas, FuzzerViewAttackModel* model) { + char temp_str[25]; uint16_t crt; + const uint16_t y = LINE_2_Y; + canvas_set_font(canvas, FontPrimary); if(!model->td_emt_cursor) { canvas_set_font(canvas, FontSecondary); snprintf(temp_str, sizeof(temp_str), "Time delay:"); - canvas_draw_str_aligned(canvas, LIFT_RIGHT_OFFSET, 21, AlignLeft, AlignBottom, temp_str); + canvas_draw_str_aligned(canvas, LEFT_RIGHT_OFFSET, y, AlignLeft, AlignBottom, temp_str); crt = canvas_string_width(canvas, temp_str); canvas_set_font(canvas, FontPrimary); snprintf( temp_str, sizeof(temp_str), "%d.%d", model->time_delay / 10, model->time_delay % 10); canvas_draw_str_aligned( - canvas, crt + LIFT_RIGHT_OFFSET + 3, 21, AlignLeft, AlignBottom, temp_str); + canvas, crt + LEFT_RIGHT_OFFSET + 3, y, AlignLeft, AlignBottom, temp_str); canvas_set_font(canvas, FontSecondary); snprintf( temp_str, sizeof(temp_str), "EmT: %d.%d", model->emu_time / 10, model->emu_time % 10); canvas_draw_str_aligned( - canvas, 128 - LIFT_RIGHT_OFFSET, 21, AlignRight, AlignBottom, temp_str); + canvas, 128 - LEFT_RIGHT_OFFSET, y, AlignRight, AlignBottom, temp_str); } else { canvas_set_font(canvas, FontSecondary); snprintf( @@ -148,138 +116,206 @@ void fuzzer_view_attack_draw(Canvas* canvas, FuzzerViewAttackModel* model) { model->time_delay / 10, model->time_delay % 10); - canvas_draw_str_aligned(canvas, LIFT_RIGHT_OFFSET, 21, AlignLeft, AlignBottom, temp_str); + canvas_draw_str_aligned(canvas, LEFT_RIGHT_OFFSET, y, AlignLeft, AlignBottom, temp_str); canvas_set_font(canvas, FontPrimary); snprintf(temp_str, sizeof(temp_str), "%d.%d", model->emu_time / 10, model->emu_time % 10); canvas_draw_str_aligned( - canvas, 128 - LIFT_RIGHT_OFFSET, 21, AlignRight, AlignBottom, temp_str); + canvas, 128 - LEFT_RIGHT_OFFSET, y, AlignRight, AlignBottom, temp_str); crt = canvas_string_width(canvas, temp_str); canvas_set_font(canvas, FontSecondary); snprintf(temp_str, sizeof(temp_str), "Emulation time:"); canvas_draw_str_aligned( - canvas, 128 - LIFT_RIGHT_OFFSET - crt - 3, 21, AlignRight, AlignBottom, temp_str); + canvas, 128 - LEFT_RIGHT_OFFSET - crt - 3, y, AlignRight, AlignBottom, temp_str); } +} + +static void fuzzer_view_attack_draw_time_delays_str(Canvas* canvas, FuzzerViewAttackModel* model) { + char temp_str[20]; + uint16_t crt; + const uint16_t y = LINE_2_Y; canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, model->protocol_name); + snprintf( + temp_str, + sizeof(temp_str), + "TD: %d.%d Emt: %d.%d", + model->time_delay / 10, + model->time_delay % 10, + model->emu_time / 10, + model->emu_time % 10); + crt = canvas_string_width(canvas, temp_str); + + canvas_draw_str_aligned( + canvas, 128 - LEFT_RIGHT_OFFSET - crt, y, AlignLeft, AlignBottom, temp_str); +} + +static void fuzzer_view_attack_draw_idle(Canvas* canvas, FuzzerViewAttackModel* model) { + if(model->td_emt_cursor) { + elements_button_center(canvas, "Start"); + elements_button_left(canvas, "EmT -"); + elements_button_right(canvas, "+ EmT"); + } else { + elements_button_center(canvas, "Start"); + elements_button_left(canvas, "TD -"); + elements_button_right(canvas, "+ TD"); + } +} + +static void fuzzer_view_attack_draw_running(Canvas* canvas, FuzzerViewAttackModel* model) { + UNUSED(model); + elements_button_left(canvas, "Stop"); + elements_button_center(canvas, "Pause"); +} + +static void fuzzer_view_attack_draw_end(Canvas* canvas, FuzzerViewAttackModel* model) { + UNUSED(model); + // elements_button_center(canvas, "Restart"); // Reset + elements_button_left(canvas, "Exit"); +} + +void fuzzer_view_attack_draw(Canvas* canvas, FuzzerViewAttackModel* model) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + // Header - Attack name + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, LINE_1_Y, AlignCenter, AlignBottom, model->attack_name); + + // Time delays line or Status line + switch(model->attack_state) { + case FuzzerAttackStateIdle: + fuzzer_view_attack_draw_time_delays_line(canvas, model); + break; + + case FuzzerAttackStateAttacking: + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, LEFT_RIGHT_OFFSET, LINE_2_Y, "Attacking"); + fuzzer_view_attack_draw_time_delays_str(canvas, model); + + break; + + case FuzzerAttackStateEmulating: + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, LINE_2_Y, AlignCenter, AlignBottom, "Emulating:"); + + break; + + case FuzzerAttackStatePause: + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, LEFT_RIGHT_OFFSET, LINE_2_Y, "Paused"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_icon_ex(canvas, 62, LINE_2_Y - 9, &I_Pin_arrow_up_7x9, IconRotation180); + canvas_draw_icon(canvas, 69, LINE_2_Y - 9, &I_Pin_arrow_up_7x9); + canvas_draw_str(canvas, 79, LINE_2_Y, "Change UID"); + break; + + case FuzzerAttackStateEnd: + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, LINE_2_Y, AlignCenter, AlignBottom, "Attack is over"); + + break; + + default: + break; + } + + // Protocol name + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 64, LINE_3_Y, AlignCenter, AlignBottom, model->protocol_name); + + // Current UID canvas_set_font(canvas, FontPrimary); if(128 < canvas_string_width(canvas, furi_string_get_cstr(model->uid_str))) { canvas_set_font(canvas, FontSecondary); } canvas_draw_str_aligned( - canvas, 64, 38, AlignCenter, AlignTop, furi_string_get_cstr(model->uid_str)); + canvas, 64, LINE_4_Y, AlignCenter, AlignBottom, furi_string_get_cstr(model->uid_str)); + // Btns canvas_set_font(canvas, FontSecondary); - if(model->attack_state == FuzzerAttackStateRunning) { - elements_button_center(canvas, "Stop"); + if(model->attack_state == FuzzerAttackStateAttacking || + model->attack_state == FuzzerAttackStateEmulating) { + fuzzer_view_attack_draw_running(canvas, model); } else if(model->attack_state == FuzzerAttackStateIdle) { - if(model->td_emt_cursor) { - elements_button_center(canvas, "Start"); - elements_button_left(canvas, "EmT -"); - elements_button_right(canvas, "+ EmT"); - } else { - elements_button_center(canvas, "Start"); - elements_button_left(canvas, "TD -"); - elements_button_right(canvas, "+ TD"); - } - + fuzzer_view_attack_draw_idle(canvas, model); + } else if(model->attack_state == FuzzerAttackStatePause) { + elements_button_left(canvas, "Back"); + elements_button_right(canvas, "Save"); + elements_button_center(canvas, "Emu"); } else if(model->attack_state == FuzzerAttackStateEnd) { - // elements_button_center(canvas, "Restart"); // Reset - elements_button_left(canvas, "Exit"); + fuzzer_view_attack_draw_end(canvas, model); } } -bool fuzzer_view_attack_input(InputEvent* event, void* context) { - furi_assert(context); - FuzzerViewAttack* view_attack = context; - +static bool fuzzer_view_attack_input_idle( + FuzzerViewAttack* view_attack, + InputEvent* event, + FuzzerViewAttackModel* model) { if(event->key == InputKeyBack && event->type == InputTypeShort) { - view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context); + view_attack->callback(FuzzerCustomEventViewAttackExit, view_attack->context); return true; } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - view_attack->callback(FuzzerCustomEventViewAttackOk, view_attack->context); + view_attack->callback(FuzzerCustomEventViewAttackRunAttack, view_attack->context); return true; } else if(event->key == InputKeyLeft) { - with_view_model( - view_attack->view, - FuzzerViewAttackModel * model, - { - if(model->attack_state == FuzzerAttackStateIdle) { - if(!model->td_emt_cursor) { - // TimeDelay -- - if(event->type == InputTypeShort) { - if(model->time_delay > model->time_delay_min) { - model->time_delay--; - } - } else if(event->type == InputTypeLong) { - if((model->time_delay - 10) >= model->time_delay_min) { - model->time_delay -= 10; - } else { - model->time_delay = model->time_delay_min; - } - } - } else { - // EmuTime -- - if(event->type == InputTypeShort) { - if(model->emu_time > model->emu_time_min) { - model->emu_time--; - } - } else if(event->type == InputTypeLong) { - if((model->emu_time - 10) >= model->emu_time_min) { - model->emu_time -= 10; - } else { - model->emu_time = model->emu_time_min; - } - } - } - } else if( - (model->attack_state == FuzzerAttackStateEnd) && - (event->type == InputTypeShort)) { - // Exit if Ended - view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context); + if(!model->td_emt_cursor) { + // TimeDelay -- + if(event->type == InputTypeShort) { + if(model->time_delay > model->time_delay_min) { + model->time_delay--; } - }, - true); + } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) { + if((model->time_delay - 10) >= model->time_delay_min) { + model->time_delay -= 10; + } else { + model->time_delay = model->time_delay_min; + } + } + } else { + // EmuTime -- + if(event->type == InputTypeShort) { + if(model->emu_time > model->emu_time_min) { + model->emu_time--; + } + } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) { + if((model->emu_time - 10) >= model->emu_time_min) { + model->emu_time -= 10; + } else { + model->emu_time = model->emu_time_min; + } + } + } return true; } else if(event->key == InputKeyRight) { - with_view_model( - view_attack->view, - FuzzerViewAttackModel * model, - { - if(model->attack_state == FuzzerAttackStateIdle) { - if(!model->td_emt_cursor) { - // TimeDelay ++ - if(event->type == InputTypeShort) { - if(model->time_delay < FUZZ_TIME_DELAY_MAX) { - model->time_delay++; - } - } else if(event->type == InputTypeLong) { - model->time_delay += 10; - if(model->time_delay > FUZZ_TIME_DELAY_MAX) { - model->time_delay = FUZZ_TIME_DELAY_MAX; - } - } - } else { - // EmuTime ++ - if(event->type == InputTypeShort) { - if(model->emu_time < FUZZ_TIME_DELAY_MAX) { - model->emu_time++; - } - } else if(event->type == InputTypeLong) { - model->emu_time += 10; - if(model->emu_time > FUZZ_TIME_DELAY_MAX) { - model->emu_time = FUZZ_TIME_DELAY_MAX; - } - } - } - } else { - // Nothing + if(!model->td_emt_cursor) { + // TimeDelay ++ + if(event->type == InputTypeShort) { + if(model->time_delay < FUZZ_TIME_DELAY_MAX) { + model->time_delay++; } - }, - true); + } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) { + model->time_delay += 10; + if(model->time_delay > FUZZ_TIME_DELAY_MAX) { + model->time_delay = FUZZ_TIME_DELAY_MAX; + } + } + } else { + // EmuTime ++ + if(event->type == InputTypeShort) { + if(model->emu_time < FUZZ_TIME_DELAY_MAX) { + model->emu_time++; + } + } else if(event->type == InputTypeLong || event->type == InputTypeRepeat) { + model->emu_time += 10; + if(model->emu_time > FUZZ_TIME_DELAY_MAX) { + model->emu_time = FUZZ_TIME_DELAY_MAX; + } + } + } return true; } else if( (event->key == InputKeyUp || event->key == InputKeyDown) && @@ -291,6 +327,81 @@ bool fuzzer_view_attack_input(InputEvent* event, void* context) { true); return true; } + return true; +} + +static bool fuzzer_view_attack_input_end( + FuzzerViewAttack* view_attack, + InputEvent* event, + FuzzerViewAttackModel* model) { + UNUSED(model); + if((event->key == InputKeyBack || event->key == InputKeyLeft) && + event->type == InputTypeShort) { + // Exit if Ended + view_attack->callback(FuzzerCustomEventViewAttackExit, view_attack->context); + } + return true; +} + +bool fuzzer_view_attack_input(InputEvent* event, void* context) { + furi_assert(context); + FuzzerViewAttack* view_attack = context; + + // if(event->key == InputKeyBack && event->type == InputTypeShort) { + // view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context); + // return true; + // } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + // view_attack->callback(FuzzerCustomEventViewAttackOk, view_attack->context); + // return true; + // } else + // { + with_view_model( + view_attack->view, + FuzzerViewAttackModel * model, + { + switch(model->attack_state) { + case FuzzerAttackStateIdle: + fuzzer_view_attack_input_idle(view_attack, event, model); + break; + + case FuzzerAttackStateEnd: + fuzzer_view_attack_input_end(view_attack, event, model); + break; + + case FuzzerAttackStateAttacking: + case FuzzerAttackStateEmulating: + if((event->key == InputKeyBack || event->key == InputKeyLeft) && + event->type == InputTypeShort) { + view_attack->callback(FuzzerCustomEventViewAttackIdle, view_attack->context); + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + view_attack->callback(FuzzerCustomEventViewAttackPause, view_attack->context); + } + break; + + case FuzzerAttackStatePause: + if((event->key == InputKeyBack || event->key == InputKeyLeft) && + event->type == InputTypeShort) { + view_attack->callback(FuzzerCustomEventViewAttackIdle, view_attack->context); + } else if(event->key == InputKeyRight && event->type == InputTypeShort) { + view_attack->callback(FuzzerCustomEventViewAttackSave, view_attack->context); + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + view_attack->callback( + FuzzerCustomEventViewAttackEmulateCurrent, view_attack->context); + } else if(event->key == InputKeyUp && event->type == InputTypeShort) { + view_attack->callback( + FuzzerCustomEventViewAttackPrevUid, view_attack->context); + } else if(event->key == InputKeyDown && event->type == InputTypeShort) { + view_attack->callback( + FuzzerCustomEventViewAttackNextUid, view_attack->context); + } + break; + + default: + break; + } + }, + true); + // } return true; } diff --git a/applications/external/multi_fuzzer/views/attack.h b/applications/external/multi_fuzzer/views/attack.h index 66e96d7d6..08706db71 100644 --- a/applications/external/multi_fuzzer/views/attack.h +++ b/applications/external/multi_fuzzer/views/attack.h @@ -29,13 +29,7 @@ void fuzzer_view_attack_reset_data( void fuzzer_view_attack_set_uid(FuzzerViewAttack* view, const FuzzerPayload* uid); -void fuzzer_view_attack_start(FuzzerViewAttack* view); - -void fuzzer_view_attack_stop(FuzzerViewAttack* view); - -void fuzzer_view_attack_pause(FuzzerViewAttack* view); - -void fuzzer_view_attack_end(FuzzerViewAttack* view); +void fuzzer_view_update_state(FuzzerViewAttack* view, FuzzerAttackState state); uint8_t fuzzer_view_attack_get_time_delay(FuzzerViewAttack* view); diff --git a/applications/external/subghz_remote/application.fam b/applications/external/subghz_remote/application.fam index 030ed030f..b175f8c8d 100644 --- a/applications/external/subghz_remote/application.fam +++ b/applications/external/subghz_remote/application.fam @@ -6,5 +6,6 @@ App( stack_size=2 * 1024, order=11, fap_icon="subrem_10px.png", + fap_description="SubGhz Remote, uses up to 5 .sub files", fap_category="Sub-GHz", ) diff --git a/applications/external/subghz_remote/helpers/subrem_custom_event.h b/applications/external/subghz_remote/helpers/subrem_custom_event.h index 8d93ab1fd..e6b9e8ac6 100644 --- a/applications/external/subghz_remote/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote/helpers/subrem_custom_event.h @@ -1,13 +1,27 @@ #pragma once +typedef enum { + SubRemEditMenuStateUP = 0, + SubRemEditMenuStateDOWN, + SubRemEditMenuStateLEFT, + SubRemEditMenuStateRIGHT, + SubRemEditMenuStateOK, +} SubRemEditMenuState; + typedef enum { // StartSubmenuIndex SubmenuIndexSubRemOpenMapFile = 0, + SubmenuIndexSubRemEditMapFile, + SubmenuIndexSubRemNewMapFile, #if FURI_DEBUG SubmenuIndexSubRemRemoteView, #endif // SubmenuIndexSubRemAbout, + // EditSubmenuIndex + EditSubmenuIndexEditLabel, + EditSubmenuIndexEditFile, + // SubRemCustomEvent SubRemCustomEventViewRemoteStartUP = 100, SubRemCustomEventViewRemoteStartDOWN, @@ -17,4 +31,21 @@ typedef enum { SubRemCustomEventViewRemoteBack, SubRemCustomEventViewRemoteStop, SubRemCustomEventViewRemoteForcedStop, + + SubRemCustomEventViewEditMenuBack, + SubRemCustomEventViewEditMenuUP, + SubRemCustomEventViewEditMenuDOWN, + SubRemCustomEventViewEditMenuEdit, + SubRemCustomEventViewEditMenuSave, + + SubRemCustomEventSceneEditsubmenu, + SubRemCustomEventSceneEditLabelInputDone, + SubRemCustomEventSceneEditLabelWidgetAcces, + SubRemCustomEventSceneEditLabelWidgetBack, + + SubRemCustomEventSceneEditOpenSubErrorPopup, + + SubRemCustomEventSceneEditPreviewSaved, + + SubRemCustomEventSceneNewName, } SubRemCustomEvent; \ No newline at end of file diff --git a/applications/external/subghz_remote/helpers/subrem_types.h b/applications/external/subghz_remote/helpers/subrem_types.h index b392de17e..b43f8499d 100644 --- a/applications/external/subghz_remote/helpers/subrem_types.h +++ b/applications/external/subghz_remote/helpers/subrem_types.h @@ -18,7 +18,11 @@ typedef enum { typedef enum { SubRemViewIDSubmenu, + SubRemViewIDWidget, + SubRemViewIDPopup, + SubRemViewIDTextInput, SubRemViewIDRemote, + SubRemViewIDEditMenu, } SubRemViewID; typedef enum { diff --git a/applications/external/subghz_remote/icon.png b/applications/external/subghz_remote/icon.png deleted file mode 100644 index c6b410f4c..000000000 Binary files a/applications/external/subghz_remote/icon.png and /dev/null differ diff --git a/applications/external/subghz_remote/scenes/subrem_scene_config.h b/applications/external/subghz_remote/scenes/subrem_scene_config.h index 45e55850a..08486be74 100644 --- a/applications/external/subghz_remote/scenes/subrem_scene_config.h +++ b/applications/external/subghz_remote/scenes/subrem_scene_config.h @@ -1,5 +1,9 @@ -#ifndef SUBREM_LIGHT ADD_SCENE(subrem, start, Start) -#endif ADD_SCENE(subrem, open_map_file, OpenMapFile) -ADD_SCENE(subrem, remote, Remote) \ No newline at end of file +ADD_SCENE(subrem, remote, Remote) +ADD_SCENE(subrem, edit_menu, EditMenu) +ADD_SCENE(subrem, edit_submenu, EditSubMenu) +ADD_SCENE(subrem, edit_label, EditLabel) +ADD_SCENE(subrem, open_sub_file, OpenSubFile) +ADD_SCENE(subrem, edit_preview, EditPreview) +ADD_SCENE(subrem, enter_new_name, EnterNewName) \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_label.c b/applications/external/subghz_remote/scenes/subrem_scene_edit_label.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_label.c rename to applications/external/subghz_remote/scenes/subrem_scene_edit_label.c diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_menu.c b/applications/external/subghz_remote/scenes/subrem_scene_edit_menu.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_menu.c rename to applications/external/subghz_remote/scenes/subrem_scene_edit_menu.c diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_preview.c b/applications/external/subghz_remote/scenes/subrem_scene_edit_preview.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_preview.c rename to applications/external/subghz_remote/scenes/subrem_scene_edit_preview.c diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_submenu.c b/applications/external/subghz_remote/scenes/subrem_scene_edit_submenu.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_submenu.c rename to applications/external/subghz_remote/scenes/subrem_scene_edit_submenu.c diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c b/applications/external/subghz_remote/scenes/subrem_scene_enter_new_name.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c rename to applications/external/subghz_remote/scenes/subrem_scene_enter_new_name.c diff --git a/applications/external/subghz_remote/scenes/subrem_scene_open_map_file.c b/applications/external/subghz_remote/scenes/subrem_scene_open_map_file.c index 1e917580c..b91a35129 100644 --- a/applications/external/subghz_remote/scenes/subrem_scene_open_map_file.c +++ b/applications/external/subghz_remote/scenes/subrem_scene_open_map_file.c @@ -5,30 +5,16 @@ void subrem_scene_open_map_file_on_enter(void* context) { SubGhzRemoteApp* app = context; SubRemLoadMapState load_state = subrem_load_from_file(app); + uint32_t start_scene_state = + scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart); - if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) { + if(load_state == SubRemLoadMapStateBack) { + scene_manager_previous_scene(app->scene_manager); + } else if(start_scene_state == SubmenuIndexSubRemEditMapFile) { + scene_manager_set_scene_state(app->scene_manager, SubRemSceneEditMenu, SubRemSubKeyNameUp); + scene_manager_next_scene(app->scene_manager, SubRemSceneEditMenu); + } else if(start_scene_state == SubmenuIndexSubRemOpenMapFile) { scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); - } else { - if(load_state != SubRemLoadMapStateBack) { -#ifdef SUBREM_LIGHT - dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); -#else - DialogMessage* message = dialog_message_alloc(); - - dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter); - dialog_message_set_text( - message, "Can't load\nMap file", 64, 32, AlignCenter, AlignCenter); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_show(app->dialogs, message); - - dialog_message_free(message); -#endif - } - // TODO: Map Preset Reset - if(!scene_manager_previous_scene(app->scene_manager)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } } } diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c b/applications/external/subghz_remote/scenes/subrem_scene_open_sub_file.c similarity index 100% rename from applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c rename to applications/external/subghz_remote/scenes/subrem_scene_open_sub_file.c diff --git a/applications/external/subghz_remote/scenes/subrem_scene_remote.c b/applications/external/subghz_remote/scenes/subrem_scene_remote.c index ebc582991..e8d57dae7 100644 --- a/applications/external/subghz_remote/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote/scenes/subrem_scene_remote.c @@ -39,6 +39,9 @@ void subrem_scene_remote_on_enter(void* context) { SubGhzRemoteApp* app = context; subrem_view_remote_update_data_labels(app->subrem_remote_view, app->map_preset->subs_preset); + subrem_view_remote_set_radio( + app->subrem_remote_view, + subghz_txrx_radio_device_get(app->txrx) != SubGhzRadioDeviceTypeInternal); subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app); diff --git a/applications/external/subghz_remote/scenes/subrem_scene_start.c b/applications/external/subghz_remote/scenes/subrem_scene_start.c index e780b54ce..0f3399b7c 100644 --- a/applications/external/subghz_remote/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote/scenes/subrem_scene_start.c @@ -27,16 +27,28 @@ void subrem_scene_start_on_enter(void* context) { subrem_scene_start_submenu_callback, app); #endif + submenu_add_item( + submenu, + "Edit Map File", + SubmenuIndexSubRemEditMapFile, + subrem_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "New Map File", + SubmenuIndexSubRemNewMapFile, + subrem_scene_start_submenu_callback, + app); // submenu_add_item( // submenu, // "About", // SubmenuIndexSubGhzRemoteAbout, // subrem_scene_start_submenu_callback, // app); -#ifndef SUBREM_LIGHT + submenu_set_selected_item( submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); -#endif + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDSubmenu); } @@ -48,23 +60,33 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSubRemOpenMapFile) { -#ifndef SUBREM_LIGHT scene_manager_set_scene_state( app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemOpenMapFile); -#endif + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); consumed = true; } - // } else if(event.event == SubmenuIndexSubRemAbout) { - // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); - // consumed = true; - // } #if FURI_DEBUG else if(event.event == SubmenuIndexSubRemRemoteView) { scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); consumed = true; } #endif + else if(event.event == SubmenuIndexSubRemEditMapFile) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemEditMapFile); + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); + consumed = true; + } else if(event.event == SubmenuIndexSubRemNewMapFile) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemNewMapFile); + scene_manager_next_scene(app->scene_manager, SubRemSceneEnterNewName); + consumed = true; + } + // } else if(event.event == SubmenuIndexSubRemAbout) { + // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); + // consumed = true; + // } } return consumed; diff --git a/applications/external/subghz_remote/subghz_remote_app.c b/applications/external/subghz_remote/subghz_remote_app.c index 1f04ffc08..1af39f57d 100644 --- a/applications/external/subghz_remote/subghz_remote_app.c +++ b/applications/external/subghz_remote/subghz_remote_app.c @@ -1,5 +1,4 @@ #include "subghz_remote_app_i.h" -#include static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -19,26 +18,23 @@ static void subghz_remote_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } -SubGhzRemoteApp* subghz_remote_app_alloc(char* p) { - SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); +static void subghz_remote_make_app_folder(SubGhzRemoteApp* app) { + furi_assert(app); Storage* storage = furi_record_open(RECORD_STORAGE); + + // Migrate old users data storage_common_migrate(storage, EXT_PATH("unirf"), SUBREM_APP_FOLDER); - storage_common_migrate(storage, EXT_PATH("subghz/unirf"), SUBREM_APP_FOLDER); if(!storage_simply_mkdir(storage, SUBREM_APP_FOLDER)) { - //FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER); + // FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER); + dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); } furi_record_close(RECORD_STORAGE); +} - // // Enable power for External CC1101 if it is connected - // furi_hal_subghz_enable_ext_power(); - // // Auto switch to internal radio if external radio is not available - // furi_delay_ms(15); - // if(!furi_hal_subghz_check_radio()) { - // furi_hal_subghz_select_radio_type(SubGhzRadioInternal); - // furi_hal_subghz_init_radio_type(SubGhzRadioInternal); - // } +SubGhzRemoteApp* subghz_remote_app_alloc() { + SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); furi_hal_power_suppress_charge_enter(); @@ -75,6 +71,20 @@ SubGhzRemoteApp* subghz_remote_app_alloc(char* p) { // Dialog app->dialogs = furi_record_open(RECORD_DIALOGS); + // TextInput + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewIDTextInput, text_input_get_view(app->text_input)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewIDWidget, widget_get_view(app->widget)); + + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view(app->view_dispatcher, SubRemViewIDPopup, popup_get_view(app->popup)); + // Remote view app->subrem_remote_view = subrem_view_remote_alloc(); view_dispatcher_add_view( @@ -82,6 +92,13 @@ SubGhzRemoteApp* subghz_remote_app_alloc(char* p) { SubRemViewIDRemote, subrem_view_remote_get_view(app->subrem_remote_view)); + // Edit Menu view + app->subrem_edit_menu = subrem_view_edit_menu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewIDEditMenu, + subrem_view_edit_menu_get_view(app->subrem_edit_menu)); + app->map_preset = malloc(sizeof(SubRemMapPreset)); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc(); @@ -91,19 +108,7 @@ SubGhzRemoteApp* subghz_remote_app_alloc(char* p) { subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app); - if(p && strlen(p)) { - furi_string_set(app->file_path, p); - subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); - scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); - } else { -#ifdef SUBREM_LIGHT - scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); -#else - scene_manager_next_scene(app->scene_manager, SubRemSceneStart); - scene_manager_set_scene_state( - app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemOpenMapFile); -#endif - } + app->map_not_saved = false; return app; } @@ -113,11 +118,6 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { furi_hal_power_suppress_charge_exit(); - // // Disable power for External CC1101 if it was enabled and module is connected - // furi_hal_subghz_disable_ext_power(); - // // Reinit SPI handles for internal radio / nfc - // furi_hal_subghz_init_radio_type(SubGhzRadioInternal); - // Submenu view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDSubmenu); submenu_free(app->submenu); @@ -125,10 +125,26 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { // Dialog furi_record_close(RECORD_DIALOGS); + // TextInput + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDTextInput); + text_input_free(app->text_input); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDWidget); + widget_free(app->widget); + + // Popup + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDPopup); + popup_free(app->popup); + // Remote view view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); subrem_view_remote_free(app->subrem_remote_view); + // Edit view + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDEditMenu); + subrem_view_edit_menu_free(app->subrem_edit_menu); + scene_manager_free(app->scene_manager); view_dispatcher_free(app->view_dispatcher); @@ -152,10 +168,33 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { free(app); } -int32_t subghz_remote_app(char* p) { - UNUSED(p); - dolphin_deed(DolphinDeedPluginStart); - SubGhzRemoteApp* subghz_remote_app = subghz_remote_app_alloc(p); +int32_t subghz_remote_app(void* arg) { + SubGhzRemoteApp* subghz_remote_app = subghz_remote_app_alloc(); + + subghz_remote_make_app_folder(subghz_remote_app); + + bool map_loaded = false; + + if((arg != NULL) && (strlen(arg) != 0)) { + furi_string_set(subghz_remote_app->file_path, (const char*)arg); + SubRemLoadMapState load_state = subrem_map_file_load( + subghz_remote_app, furi_string_get_cstr(subghz_remote_app->file_path)); + + if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) { + map_loaded = true; + } else { + // TODO Replace + dialog_message_show_storage_error(subghz_remote_app->dialogs, "Cannot load\nmap file"); + } + } + + if(map_loaded) { + scene_manager_next_scene(subghz_remote_app->scene_manager, SubRemSceneRemote); + } else { + furi_string_set(subghz_remote_app->file_path, SUBREM_APP_FOLDER); + scene_manager_next_scene(subghz_remote_app->scene_manager, SubRemSceneStart); + scene_manager_next_scene(subghz_remote_app->scene_manager, SubRemSceneOpenMapFile); + } view_dispatcher_run(subghz_remote_app->view_dispatcher); diff --git a/applications/external/subghz_remote/subghz_remote_app_i.c b/applications/external/subghz_remote/subghz_remote_app_i.c index 26659ccb1..82e762c2a 100644 --- a/applications/external/subghz_remote/subghz_remote_app_i.c +++ b/applications/external/subghz_remote/subghz_remote_app_i.c @@ -7,10 +7,8 @@ // #include // #include -#ifdef APP_SUBGHZREMOTE #include #include -#endif #define TAG "SubGhzRemote" @@ -22,7 +20,7 @@ static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { [SubRemSubKeyNameOk] = {"OK", "OKLABEL"}, }; -static void subrem_map_preset_reset(SubRemMapPreset* map_preset) { +void subrem_map_preset_reset(SubRemMapPreset* map_preset) { furi_assert(map_preset); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { @@ -228,9 +226,7 @@ bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) NULL, 0); -#ifdef APP_SUBGHZREMOTE subghz_custom_btns_reset(); -#endif if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) { ret = true; @@ -246,12 +242,12 @@ bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { subghz_txrx_stop(app->txrx); -#ifdef APP_SUBGHZREMOTE + if(sub_preset->type == SubGhzProtocolTypeDynamic) { subghz_txrx_reset_dynamic_and_custom_btns(app->txrx); } subghz_custom_btns_reset(); -#endif + return true; } @@ -278,3 +274,47 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { return ret; } + +bool subrem_save_map_to_file(SubGhzRemoteApp* app) { + furi_assert(app); + + const char* file_name = furi_string_get_cstr(app->file_path); + bool saved = false; + FlipperFormat* fff_data = flipper_format_string_alloc(); + + SubRemSubFilePreset* sub_preset; + + flipper_format_write_header_cstr( + fff_data, SUBREM_APP_APP_FILE_TYPE, SUBREM_APP_APP_FILE_VERSION); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = app->map_preset->subs_preset[i]; + if(!furi_string_empty(sub_preset->file_path)) { + flipper_format_write_string(fff_data, map_file_labels[i][0], sub_preset->file_path); + } + } + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = app->map_preset->subs_preset[i]; + if(!furi_string_empty(sub_preset->file_path)) { + flipper_format_write_string(fff_data, map_file_labels[i][1], sub_preset->label); + } + } + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* flipper_format_stream = flipper_format_get_raw_stream(fff_data); + + do { + if(!storage_simply_remove(storage, file_name)) { + break; + } + //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); + stream_save_to_file(flipper_format_stream, storage, file_name, FSOM_CREATE_ALWAYS); + + saved = true; + } while(0); + + furi_record_close(RECORD_STORAGE); + flipper_format_free(fff_data); + + return saved; +} \ No newline at end of file diff --git a/applications/external/subghz_remote/subghz_remote_app_i.h b/applications/external/subghz_remote/subghz_remote_app_i.h index fbcc55111..42e9576fd 100644 --- a/applications/external/subghz_remote/subghz_remote_app_i.h +++ b/applications/external/subghz_remote/subghz_remote_app_i.h @@ -1,8 +1,5 @@ #pragma once -#define SUBREM_LIGHT 1 -#define APP_SUBGHZREMOTE 1 - #include "helpers/subrem_types.h" #include "helpers/subrem_presets.h" #include "scenes/subrem_scene.h" @@ -12,6 +9,7 @@ #include #include "views/remote.h" +#include "views/edit_menu.h" #include #include @@ -35,16 +33,23 @@ typedef struct { SceneManager* scene_manager; NotificationApp* notifications; DialogsApp* dialogs; + Widget* widget; + Popup* popup; + TextInput* text_input; Submenu* submenu; FuriString* file_path; + char file_name_tmp[SUBREM_MAX_LEN_NAME]; SubRemViewRemote* subrem_remote_view; + SubRemViewEditMenu* subrem_edit_menu; SubRemMapPreset* map_preset; SubGhzTxRx* txrx; + bool map_not_saved; + uint8_t chusen_sub; } SubGhzRemoteApp; @@ -54,6 +59,10 @@ bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced); -void subrem_save_active_sub(void* context); - SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path); + +void subrem_map_preset_reset(SubRemMapPreset* map_preset); + +bool subrem_save_map_to_file(SubGhzRemoteApp* app); + +void subrem_save_active_sub(void* context); diff --git a/applications/external/subghz_remote_configurator/views/edit_menu.c b/applications/external/subghz_remote/views/edit_menu.c similarity index 100% rename from applications/external/subghz_remote_configurator/views/edit_menu.c rename to applications/external/subghz_remote/views/edit_menu.c diff --git a/applications/external/subghz_remote_configurator/views/edit_menu.h b/applications/external/subghz_remote/views/edit_menu.h similarity index 100% rename from applications/external/subghz_remote_configurator/views/edit_menu.h rename to applications/external/subghz_remote/views/edit_menu.h diff --git a/applications/external/subghz_remote/views/remote.c b/applications/external/subghz_remote/views/remote.c index c2b41cfd6..fc7608624 100644 --- a/applications/external/subghz_remote/views/remote.c +++ b/applications/external/subghz_remote/views/remote.c @@ -22,6 +22,7 @@ typedef struct { SubRemViewRemoteState state; uint8_t pressed_btn; + bool is_external; } SubRemViewRemoteModel; void subrem_view_remote_set_callback( @@ -106,6 +107,15 @@ void subrem_view_remote_set_state( true); } +void subrem_view_remote_set_radio(SubRemViewRemote* subrem_view_remote, bool external) { + furi_assert(subrem_view_remote); + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->is_external = external; }, + true); +} + void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); @@ -143,6 +153,8 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { elements_button_right(canvas, "Save"); } else { canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); + canvas_draw_str_aligned( + canvas, 126, 62, AlignRight, AlignBottom, ((model->is_external) ? "Ext" : "Int")); } //Status text and indicator @@ -267,6 +279,7 @@ SubRemViewRemote* subrem_view_remote_alloc() { } model->pressed_btn = 0; + model->is_external = false; }, true); return subrem_view_remote; diff --git a/applications/external/subghz_remote/views/remote.h b/applications/external/subghz_remote/views/remote.h index 5b1e8153a..39f9a007d 100644 --- a/applications/external/subghz_remote/views/remote.h +++ b/applications/external/subghz_remote/views/remote.h @@ -33,4 +33,6 @@ void subrem_view_remote_update_data_labels( void subrem_view_remote_set_state( SubRemViewRemote* subrem_view_remote, SubRemViewRemoteState state, - uint8_t presed_btn); \ No newline at end of file + uint8_t presed_btn); + +void subrem_view_remote_set_radio(SubRemViewRemote* subrem_view_remote, bool external); \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/application.fam b/applications/external/subghz_remote_configurator/application.fam deleted file mode 100644 index 29b7ed082..000000000 --- a/applications/external/subghz_remote_configurator/application.fam +++ /dev/null @@ -1,15 +0,0 @@ -App( - appid="subrem_configurator", - name="Remote Maker", - apptype=FlipperAppType.EXTERNAL, - entry_point="subghz_remote_config_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=50, - fap_description="File Editor for the SubGhz Remote app", - fap_category="Sub-GHz", - fap_icon="subrem_10px.png", -) diff --git a/applications/external/subghz_remote_configurator/helpers/subrem_custom_event.h b/applications/external/subghz_remote_configurator/helpers/subrem_custom_event.h deleted file mode 100644 index da3de2aae..000000000 --- a/applications/external/subghz_remote_configurator/helpers/subrem_custom_event.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -typedef enum { - SubRemEditMenuStateUP = 0, - SubRemEditMenuStateDOWN, - SubRemEditMenuStateLEFT, - SubRemEditMenuStateRIGHT, - SubRemEditMenuStateOK, -} SubRemEditMenuState; - -typedef enum { - // StartSubmenuIndex - SubmenuIndexSubRemEditMapFile = 0, - SubmenuIndexSubRemNewMapFile, -#if FURI_DEBUG - SubmenuIndexSubRemRemoteView, -#endif - // SubmenuIndexSubRemAbout, - - // EditSubmenuIndex - EditSubmenuIndexEditLabel, - EditSubmenuIndexEditFile, - - // SubRemCustomEvent - SubRemCustomEventViewRemoteStartUP = 100, - SubRemCustomEventViewRemoteStartDOWN, - SubRemCustomEventViewRemoteStartLEFT, - SubRemCustomEventViewRemoteStartRIGHT, - SubRemCustomEventViewRemoteStartOK, - SubRemCustomEventViewRemoteBack, - SubRemCustomEventViewRemoteStop, - SubRemCustomEventViewRemoteForcedStop, - - SubRemCustomEventViewEditMenuBack, - SubRemCustomEventViewEditMenuUP, - SubRemCustomEventViewEditMenuDOWN, - SubRemCustomEventViewEditMenuEdit, - SubRemCustomEventViewEditMenuSave, - - SubRemCustomEventSceneEditsubmenu, - SubRemCustomEventSceneEditLabelInputDone, - SubRemCustomEventSceneEditLabelWidgetAcces, - SubRemCustomEventSceneEditLabelWidgetBack, - - SubRemCustomEventSceneEditOpenSubErrorPopup, - - SubRemCustomEventSceneEditPreviewSaved, - - SubRemCustomEventSceneNewName, -} SubRemCustomEvent; \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/helpers/subrem_presets.c b/applications/external/subghz_remote_configurator/helpers/subrem_presets.c deleted file mode 100644 index 75ced8e00..000000000 --- a/applications/external/subghz_remote_configurator/helpers/subrem_presets.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "subrem_presets.h" - -#define TAG "SubRemPresets" - -SubRemSubFilePreset* subrem_sub_file_preset_alloc() { - SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); - - sub_preset->fff_data = flipper_format_string_alloc(); - sub_preset->file_path = furi_string_alloc(); - sub_preset->protocaol_name = furi_string_alloc(); - sub_preset->label = furi_string_alloc(); - - sub_preset->freq_preset.name = furi_string_alloc(); - - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; - - return sub_preset; -} - -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); - - furi_string_free(sub_preset->label); - furi_string_free(sub_preset->protocaol_name); - furi_string_free(sub_preset->file_path); - flipper_format_free(sub_preset->fff_data); - - furi_string_free(sub_preset->freq_preset.name); - - free(sub_preset); -} - -void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); - - furi_string_set_str(sub_preset->label, ""); - furi_string_reset(sub_preset->protocaol_name); - furi_string_reset(sub_preset->file_path); - - Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); - stream_clean(fff_data_stream); - - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; -} - -SubRemLoadSubState subrem_sub_preset_load( - SubRemSubFilePreset* sub_preset, - SubGhzTxRx* txrx, - FlipperFormat* fff_data_file) { - furi_assert(sub_preset); - furi_assert(txrx); - furi_assert(fff_data_file); - - Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); - - SubRemLoadSubState ret; - FuriString* temp_str = furi_string_alloc(); - uint32_t temp_data32; - uint32_t repeat = 200; - - ret = SubRemLoadSubStateError; - - do { - stream_clean(fff_data_stream); - if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - break; - } - - if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || - (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && - temp_data32 == SUBGHZ_KEY_FILE_VERSION) { - } else { - FURI_LOG_E(TAG, "Type or version mismatch"); - break; - } - - SubGhzSetting* setting = subghz_txrx_get_setting(txrx); - - //Load frequency or using default from settings - ret = SubRemLoadSubStateErrorFreq; - if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); - sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting); - } else if(!subghz_txrx_radio_device_is_frequecy_valid(txrx, temp_data32)) { - FURI_LOG_E(TAG, "Frequency not supported on chosen radio module"); - break; - } - sub_preset->freq_preset.frequency = temp_data32; - - //Load preset - ret = SubRemLoadSubStateErrorMod; - if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { - FURI_LOG_E(TAG, "Missing Preset"); - break; - } - - furi_string_set_str( - temp_str, subghz_txrx_get_preset_name(txrx, furi_string_get_cstr(temp_str))); - if(!strcmp(furi_string_get_cstr(temp_str), "")) { - break; - } - - if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) { - FURI_LOG_E(TAG, "CUSTOM preset is not supported"); - break; - // TODO Custom preset loading logic if need - // sub_preset->freq_preset.preset_index = - // subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str)); - } - - furi_string_set(sub_preset->freq_preset.name, temp_str); - - // Load protocol - ret = SubRemLoadSubStateErrorProtocol; - if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - FlipperFormat* fff_data = sub_preset->fff_data; - if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { - //if RAW - subghz_protocol_raw_gen_fff_data( - fff_data, - furi_string_get_cstr(sub_preset->file_path), - subghz_txrx_radio_device_get_name(txrx)); - } else { - stream_copy_full( - flipper_format_get_raw_stream(fff_data_file), - flipper_format_get_raw_stream(fff_data)); - } - - if(subghz_txrx_load_decoder_by_name_protocol(txrx, furi_string_get_cstr(temp_str))) { - SubGhzProtocolStatus status = - subghz_protocol_decoder_base_deserialize(subghz_txrx_get_decoder(txrx), fff_data); - if(status != SubGhzProtocolStatusOk) { - break; - } - } else { - FURI_LOG_E(TAG, "Protocol not found"); - break; - } - - const SubGhzProtocol* protocol = subghz_txrx_get_decoder(txrx)->protocol; - - if(protocol->flag & SubGhzProtocolFlag_Send) { - if((protocol->type == SubGhzProtocolTypeStatic) || - (protocol->type == SubGhzProtocolTypeDynamic) || - (protocol->type == SubGhzProtocolTypeBinRAW) || - (protocol->type == SubGhzProtocolTypeRAW)) { - sub_preset->type = protocol->type; - } else { - FURI_LOG_E(TAG, "Unsuported Protocol"); - break; - } - - furi_string_set(sub_preset->protocaol_name, temp_str); - } else { - FURI_LOG_E(TAG, "Protocol does not support transmission"); - break; - } - - if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - ret = SubRemLoadSubStateOK; - -#if FURI_DEBUG - FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); -#endif - } while(false); - - furi_string_free(temp_str); - sub_preset->load_state = ret; - return ret; -} diff --git a/applications/external/subghz_remote_configurator/helpers/subrem_presets.h b/applications/external/subghz_remote_configurator/helpers/subrem_presets.h deleted file mode 100644 index d66181b90..000000000 --- a/applications/external/subghz_remote_configurator/helpers/subrem_presets.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "subrem_types.h" -#include "txrx/subghz_txrx.h" - -#include -#include - -typedef struct { - FuriString* name; - uint32_t frequency; - // size_t preset_index; // Need for custom preset -} FreqPreset; - -// Sub File preset -typedef struct { - FlipperFormat* fff_data; - FreqPreset freq_preset; - FuriString* file_path; - FuriString* protocaol_name; - FuriString* label; - SubGhzProtocolType type; - SubRemLoadSubState load_state; -} SubRemSubFilePreset; - -typedef struct { - SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; -} SubRemMapPreset; - -SubRemSubFilePreset* subrem_sub_file_preset_alloc(); - -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); - -void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset); - -SubRemLoadSubState subrem_sub_preset_load( - SubRemSubFilePreset* sub_preset, - SubGhzTxRx* txrx, - FlipperFormat* fff_data_file); diff --git a/applications/external/subghz_remote_configurator/helpers/subrem_types.h b/applications/external/subghz_remote_configurator/helpers/subrem_types.h deleted file mode 100644 index b43f8499d..000000000 --- a/applications/external/subghz_remote_configurator/helpers/subrem_types.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include - -#define SUBREM_APP_APP_FILE_VERSION 1 -#define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file" -#define SUBREM_APP_EXTENSION ".txt" - -typedef enum { - SubRemSubKeyNameUp = (0U), - SubRemSubKeyNameDown, - SubRemSubKeyNameLeft, - SubRemSubKeyNameRight, - SubRemSubKeyNameOk, - SubRemSubKeyNameMaxCount, -} SubRemSubKeyName; - -typedef enum { - SubRemViewIDSubmenu, - SubRemViewIDWidget, - SubRemViewIDPopup, - SubRemViewIDTextInput, - SubRemViewIDRemote, - SubRemViewIDEditMenu, -} SubRemViewID; - -typedef enum { - SubRemLoadSubStateNotSet = 0, - SubRemLoadSubStatePreloaded, - SubRemLoadSubStateError, - SubRemLoadSubStateErrorIncorectPath, - SubRemLoadSubStateErrorNoFile, - SubRemLoadSubStateErrorFreq, - SubRemLoadSubStateErrorMod, - SubRemLoadSubStateErrorProtocol, - SubRemLoadSubStateOK, -} SubRemLoadSubState; - -typedef enum { - SubRemLoadMapStateBack = 0, - SubRemLoadMapStateError, - SubRemLoadMapStateErrorOpenError, - SubRemLoadMapStateErrorStorage, - SubRemLoadMapStateErrorBrokenFile, - SubRemLoadMapStateNotAllOK, - SubRemLoadMapStateOK, -} SubRemLoadMapState; \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.c b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.c deleted file mode 100644 index db485a2aa..000000000 --- a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.c +++ /dev/null @@ -1,670 +0,0 @@ -#include "subghz_txrx_i.h" - -#include -#include -#include - -#include - -#define TAG "SubGhz" - -static void subghz_txrx_radio_device_power_on(SubGhzTxRx* instance) { - UNUSED(instance); - uint8_t attempts = 0; - while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - furi_hal_power_enable_otg(); - //CC1101 power-up time - furi_delay_ms(10); - } -} - -static void subghz_txrx_radio_device_power_off(SubGhzTxRx* instance) { - UNUSED(instance); - if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); -} - -SubGhzTxRx* subghz_txrx_alloc() { - SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); - instance->setting = subghz_setting_alloc(); - subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user")); - - instance->preset = malloc(sizeof(SubGhzRadioPreset)); - instance->preset->name = furi_string_alloc(); - subghz_txrx_set_preset( - instance, "AM650", subghz_setting_get_default_frequency(instance->setting), NULL, 0); - - instance->txrx_state = SubGhzTxRxStateSleep; - - subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF); - subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable); - subghz_txrx_set_debug_pin_state(instance, false); - - instance->worker = subghz_worker_alloc(); - instance->fff_data = flipper_format_string_alloc(); - - instance->environment = subghz_environment_alloc(); - instance->is_database_loaded = - subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_NAME); - subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_USER_NAME); - subghz_environment_set_came_atomo_rainbow_table_file_name( - instance->environment, SUBGHZ_CAME_ATOMO_DIR_NAME); - subghz_environment_set_alutech_at_4n_rainbow_table_file_name( - instance->environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); - subghz_environment_set_nice_flor_s_rainbow_table_file_name( - instance->environment, SUBGHZ_NICE_FLOR_S_DIR_NAME); - subghz_environment_set_protocol_registry( - instance->environment, (void*)&subghz_protocol_registry); - instance->receiver = subghz_receiver_alloc_init(instance->environment); - - subghz_worker_set_overrun_callback( - instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); - subghz_worker_set_pair_callback( - instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); - subghz_worker_set_context(instance->worker, instance->receiver); - - //set default device Internal - subghz_devices_init(); - instance->radio_device_type = SubGhzRadioDeviceTypeInternal; - instance->radio_device_type = - subghz_txrx_radio_device_set(instance, SubGhzRadioDeviceTypeInternal); - - return instance; -} - -void subghz_txrx_free(SubGhzTxRx* instance) { - furi_assert(instance); - - if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) { - subghz_txrx_radio_device_power_off(instance); - subghz_devices_end(instance->radio_device); - } - - subghz_devices_deinit(); - - subghz_worker_free(instance->worker); - subghz_receiver_free(instance->receiver); - subghz_environment_free(instance->environment); - flipper_format_free(instance->fff_data); - furi_string_free(instance->preset->name); - subghz_setting_free(instance->setting); - - free(instance->preset); - free(instance); -} - -bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->is_database_loaded; -} - -void subghz_txrx_set_preset( - SubGhzTxRx* instance, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(instance); - furi_string_set(instance->preset->name, preset_name); - SubGhzRadioPreset* preset = instance->preset; - preset->frequency = frequency; - preset->data = preset_data; - preset->data_size = preset_data_size; -} - -const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) { - UNUSED(instance); - const char* preset_name = ""; - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - preset_name = "AM270"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - preset_name = "AM650"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - preset_name = "FM238"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - preset_name = "FM476"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - preset_name = "CUSTOM"; - } else { - FURI_LOG_E(TAG, "Unknown preset"); - } - return preset_name; -} - -SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) { - furi_assert(instance); - return *instance->preset; -} - -void subghz_txrx_get_frequency_and_modulation( - SubGhzTxRx* instance, - FuriString* frequency, - FuriString* modulation, - bool long_name) { - furi_assert(instance); - SubGhzRadioPreset* preset = instance->preset; - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - preset->frequency / 1000000 % 1000, - preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - if(long_name) { - furi_string_printf(modulation, "%s", furi_string_get_cstr(preset->name)); - } else { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name)); - } - } -} - -static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { - furi_assert(instance); - subghz_devices_reset(instance->radio_device); - subghz_devices_idle(instance->radio_device); - subghz_devices_load_preset(instance->radio_device, FuriHalSubGhzPresetCustom, preset_data); - instance->txrx_state = SubGhzTxRxStateIDLE; -} - -static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { - furi_assert(instance); - furi_assert( - instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); - - subghz_devices_idle(instance->radio_device); - - uint32_t value = subghz_devices_set_frequency(instance->radio_device, frequency); - subghz_devices_flush_rx(instance->radio_device); - subghz_txrx_speaker_on(instance); - - subghz_devices_start_async_rx( - instance->radio_device, subghz_worker_rx_callback, instance->worker); - subghz_worker_start(instance->worker); - instance->txrx_state = SubGhzTxRxStateRx; - return value; -} - -static void subghz_txrx_idle(SubGhzTxRx* instance) { - furi_assert(instance); - furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); - subghz_devices_idle(instance->radio_device); - subghz_txrx_speaker_off(instance); - instance->txrx_state = SubGhzTxRxStateIDLE; -} - -static void subghz_txrx_rx_end(SubGhzTxRx* instance) { - furi_assert(instance); - furi_assert(instance->txrx_state == SubGhzTxRxStateRx); - - if(subghz_worker_is_running(instance->worker)) { - subghz_worker_stop(instance->worker); - subghz_devices_stop_async_rx(instance->radio_device); - } - subghz_devices_idle(instance->radio_device); - subghz_txrx_speaker_off(instance); - instance->txrx_state = SubGhzTxRxStateIDLE; -} - -void subghz_txrx_sleep(SubGhzTxRx* instance) { - furi_assert(instance); - subghz_devices_sleep(instance->radio_device); - instance->txrx_state = SubGhzTxRxStateSleep; -} - -static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { - furi_assert(instance); - furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); - - subghz_devices_idle(instance->radio_device); - subghz_devices_set_frequency(instance->radio_device, frequency); - - bool ret = subghz_devices_set_tx(instance->radio_device); - if(ret) { - subghz_txrx_speaker_on(instance); - instance->txrx_state = SubGhzTxRxStateTx; - } - - return ret; -} - -SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) { - furi_assert(instance); - furi_assert(flipper_format); - - subghz_txrx_stop(instance); - - SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers; - FuriString* temp_str = furi_string_alloc(); - uint32_t repeat = 200; - do { - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - ret = SubGhzTxRxStartTxStateOk; - - SubGhzRadioPreset* preset = instance->preset; - instance->transmitter = - subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str)); - - if(instance->transmitter) { - if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) == - SubGhzProtocolStatusOk) { - if(strcmp(furi_string_get_cstr(preset->name), "") != 0) { - subghz_txrx_begin( - instance, - subghz_setting_get_preset_data_by_name( - instance->setting, furi_string_get_cstr(preset->name))); - if(preset->frequency) { - if(!subghz_txrx_tx(instance, preset->frequency)) { - FURI_LOG_E(TAG, "Only Rx"); - ret = SubGhzTxRxStartTxStateErrorOnlyRx; - } - } else { - ret = SubGhzTxRxStartTxStateErrorParserOthers; - } - - } else { - FURI_LOG_E( - TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name)); - ret = SubGhzTxRxStartTxStateErrorParserOthers; - } - - if(ret == SubGhzTxRxStartTxStateOk) { - //Start TX - subghz_devices_start_async_tx( - instance->radio_device, subghz_transmitter_yield, instance->transmitter); - } - } else { - ret = SubGhzTxRxStartTxStateErrorParserOthers; - } - } else { - ret = SubGhzTxRxStartTxStateErrorParserOthers; - } - if(ret != SubGhzTxRxStartTxStateOk) { - subghz_transmitter_free(instance->transmitter); - if(instance->txrx_state != SubGhzTxRxStateIDLE) { - subghz_txrx_idle(instance); - } - } - - } while(false); - furi_string_free(temp_str); - return ret; -} - -void subghz_txrx_rx_start(SubGhzTxRx* instance) { - furi_assert(instance); - subghz_txrx_stop(instance); - subghz_txrx_begin( - instance, - subghz_setting_get_preset_data_by_name( - subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name))); - subghz_txrx_rx(instance, instance->preset->frequency); -} - -void subghz_txrx_set_need_save_callback( - SubGhzTxRx* instance, - SubGhzTxRxNeedSaveCallback callback, - void* context) { - furi_assert(instance); - instance->need_save_callback = callback; - instance->need_save_context = context; -} - -static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { - furi_assert(instance); - furi_assert(instance->txrx_state == SubGhzTxRxStateTx); - //Stop TX - subghz_devices_stop_async_tx(instance->radio_device); - subghz_transmitter_stop(instance->transmitter); - subghz_transmitter_free(instance->transmitter); - - //if protocol dynamic then we save the last upload - if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { - if(instance->need_save_callback) { - instance->need_save_callback(instance->need_save_context); - } - } - subghz_txrx_idle(instance); - subghz_txrx_speaker_off(instance); - //Todo: Show message -} - -FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->fff_data; -} - -SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->setting; -} - -void subghz_txrx_stop(SubGhzTxRx* instance) { - furi_assert(instance); - - switch(instance->txrx_state) { - case SubGhzTxRxStateTx: - subghz_txrx_tx_stop(instance); - subghz_txrx_speaker_unmute(instance); - break; - case SubGhzTxRxStateRx: - subghz_txrx_rx_end(instance); - subghz_txrx_speaker_mute(instance); - break; - - default: - break; - } -} - -void subghz_txrx_hopper_update(SubGhzTxRx* instance) { - furi_assert(instance); - - switch(instance->hopper_state) { - case SubGhzHopperStateOFF: - case SubGhzHopperStatePause: - return; - case SubGhzHopperStateRSSITimeOut: - if(instance->hopper_timeout != 0) { - instance->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = subghz_devices_get_rssi(instance->radio_device); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - instance->hopper_timeout = 10; - instance->hopper_state = SubGhzHopperStateRSSITimeOut; - return; - } - } else { - instance->hopper_state = SubGhzHopperStateRunning; - } - // Select next frequency - if(instance->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(instance->setting) - 1) { - instance->hopper_idx_frequency++; - } else { - instance->hopper_idx_frequency = 0; - } - - if(instance->txrx_state == SubGhzTxRxStateRx) { - subghz_txrx_rx_end(instance); - }; - if(instance->txrx_state == SubGhzTxRxStateIDLE) { - subghz_receiver_reset(instance->receiver); - instance->preset->frequency = - subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency); - subghz_txrx_rx(instance, instance->preset->frequency); - } -} - -SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->hopper_state; -} - -void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) { - furi_assert(instance); - instance->hopper_state = state; -} - -void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->hopper_state == SubGhzHopperStatePause) { - instance->hopper_state = SubGhzHopperStateRunning; - } -} - -void subghz_txrx_hopper_pause(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->hopper_state == SubGhzHopperStateRunning) { - instance->hopper_state = SubGhzHopperStatePause; - } -} - -void subghz_txrx_speaker_on(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton); - } - - if(instance->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_acquire(30)) { - if(!instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); - } - } else { - instance->speaker_state = SubGhzSpeakerStateDisable; - } - } -} - -void subghz_txrx_speaker_off(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); - } - if(instance->speaker_state != SubGhzSpeakerStateDisable) { - if(furi_hal_speaker_is_mine()) { - if(!instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); - } - furi_hal_speaker_release(); - if(instance->speaker_state == SubGhzSpeakerStateShutdown) - instance->speaker_state = SubGhzSpeakerStateDisable; - } - } -} - -void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); - } - if(instance->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_is_mine()) { - if(!instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, NULL); - } - } - } -} - -void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { - furi_assert(instance); - if(instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_ibutton); - } - if(instance->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_is_mine()) { - if(!instance->debug_pin_state) { - subghz_devices_set_async_mirror_pin(instance->radio_device, &gpio_speaker); - } - } - } -} - -void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) { - furi_assert(instance); - instance->speaker_state = state; -} - -SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->speaker_state; -} - -bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) { - furi_assert(instance); - furi_assert(name_protocol); - bool res = false; - instance->decoder_result = - subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol); - if(instance->decoder_result) { - res = true; - } - return res; -} - -SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->decoder_result; -} - -bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) { - furi_assert(instance); - return ( - (instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == - SubGhzProtocolFlag_Save); -} - -bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) { - furi_assert(instance); - const SubGhzProtocol* protocol = instance->decoder_result->protocol; - if(check_type) { - return ( - ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && - protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic); - } - return ( - ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && - protocol->encoder->deserialize); -} - -void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) { - furi_assert(instance); - subghz_receiver_set_filter(instance->receiver, filter); -} - -void subghz_txrx_set_rx_calback( - SubGhzTxRx* instance, - SubGhzReceiverCallback callback, - void* context) { - subghz_receiver_set_rx_callback(instance->receiver, callback, context); -} - -void subghz_txrx_set_raw_file_encoder_worker_callback_end( - SubGhzTxRx* instance, - SubGhzProtocolEncoderRAWCallbackEnd callback, - void* context) { - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter), - callback, - context); -} - -bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name) { - furi_assert(instance); - - bool is_connect = false; - bool is_otg_enabled = furi_hal_power_is_otg_enabled(); - - if(!is_otg_enabled) { - subghz_txrx_radio_device_power_on(instance); - } - - const SubGhzDevice* device = subghz_devices_get_by_name(name); - if(device) { - is_connect = subghz_devices_is_connect(device); - } - - if(!is_otg_enabled) { - subghz_txrx_radio_device_power_off(instance); - } - return is_connect; -} - -SubGhzRadioDeviceType - subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type) { - furi_assert(instance); - - if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && - subghz_txrx_radio_device_is_external_connected(instance, SUBGHZ_DEVICE_CC1101_EXT_NAME)) { - subghz_txrx_radio_device_power_on(instance); - instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); - subghz_devices_begin(instance->radio_device); - instance->radio_device_type = SubGhzRadioDeviceTypeExternalCC1101; - } else { - subghz_txrx_radio_device_power_off(instance); - if(instance->radio_device_type != SubGhzRadioDeviceTypeInternal) { - subghz_devices_end(instance->radio_device); - } - instance->radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); - instance->radio_device_type = SubGhzRadioDeviceTypeInternal; - } - - return instance->radio_device_type; -} - -SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->radio_device_type; -} - -float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance) { - furi_assert(instance); - return subghz_devices_get_rssi(instance->radio_device); -} - -const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance) { - furi_assert(instance); - return subghz_devices_get_name(instance->radio_device); -} - -bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency) { - furi_assert(instance); - return subghz_devices_is_frequency_valid(instance->radio_device, frequency); -} - -bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency) { - furi_assert(instance); - furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); - - subghz_devices_idle(instance->radio_device); - subghz_devices_set_frequency(instance->radio_device, frequency); - - bool ret = subghz_devices_set_tx(instance->radio_device); - subghz_devices_idle(instance->radio_device); - - return ret; -} - -void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { - furi_assert(instance); - instance->debug_pin_state = state; -} - -bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->debug_pin_state; -} - -void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) { - furi_assert(instance); - subghz_environment_reset_keeloq(instance->environment); - - subghz_custom_btns_reset(); -} - -SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) { - furi_assert(instance); - return instance->receiver; -} \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.h b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.h deleted file mode 100644 index 8bb7f2aee..000000000 --- a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.h +++ /dev/null @@ -1,375 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -typedef struct SubGhzTxRx SubGhzTxRx; - -typedef void (*SubGhzTxRxNeedSaveCallback)(void* context); - -typedef enum { - SubGhzTxRxStartTxStateOk, - SubGhzTxRxStartTxStateErrorOnlyRx, - SubGhzTxRxStartTxStateErrorParserOthers, -} SubGhzTxRxStartTxState; - -// Type from subghz_types.h need for txrx working -/** SubGhzTxRx state */ -typedef enum { - SubGhzTxRxStateIDLE, - SubGhzTxRxStateRx, - SubGhzTxRxStateTx, - SubGhzTxRxStateSleep, -} SubGhzTxRxState; - -/** SubGhzHopperState state */ -typedef enum { - SubGhzHopperStateOFF, - SubGhzHopperStateRunning, - SubGhzHopperStatePause, - SubGhzHopperStateRSSITimeOut, -} SubGhzHopperState; - -/** SubGhzSpeakerState state */ -typedef enum { - SubGhzSpeakerStateDisable, - SubGhzSpeakerStateShutdown, - SubGhzSpeakerStateEnable, -} SubGhzSpeakerState; - -/** SubGhzRadioDeviceType */ -typedef enum { - SubGhzRadioDeviceTypeAuto, - SubGhzRadioDeviceTypeInternal, - SubGhzRadioDeviceTypeExternalCC1101, -} SubGhzRadioDeviceType; - -/** - * Allocate SubGhzTxRx - * - * @return SubGhzTxRx* pointer to SubGhzTxRx - */ -SubGhzTxRx* subghz_txrx_alloc(); - -/** - * Free SubGhzTxRx - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_free(SubGhzTxRx* instance); - -/** - * Check if the database is loaded - * - * @param instance Pointer to a SubGhzTxRx - * @return bool True if the database is loaded - */ -bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance); - -/** - * Set preset - * - * @param instance Pointer to a SubGhzTxRx - * @param preset_name Name of preset - * @param frequency Frequency in Hz - * @param preset_data Data of preset - * @param preset_data_size Size of preset data - */ -void subghz_txrx_set_preset( - SubGhzTxRx* instance, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); - -/** - * Get name of preset - * - * @param instance Pointer to a SubGhzTxRx - * @param preset String of preset - * @return const char* Name of preset - */ -const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset); - -/** - * Get of preset - * - * @param instance Pointer to a SubGhzTxRx - * @return SubGhzRadioPreset Preset - */ -SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance); - -/** - * Get string frequency and modulation - * - * @param instance Pointer to a SubGhzTxRx - * @param frequency Pointer to a string frequency - * @param modulation Pointer to a string modulation - */ -void subghz_txrx_get_frequency_and_modulation( - SubGhzTxRx* instance, - FuriString* frequency, - FuriString* modulation, - bool long_name); - -/** - * Start TX CC1101 - * - * @param instance Pointer to a SubGhzTxRx - * @param flipper_format Pointer to a FlipperFormat - * @return SubGhzTxRxStartTxState - */ -SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format); - -/** - * Start RX CC1101 - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_rx_start(SubGhzTxRx* instance); - -/** - * Stop TX/RX CC1101 - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_stop(SubGhzTxRx* instance); - -/** - * Set sleep mode CC1101 - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_sleep(SubGhzTxRx* instance); - -/** - * Update frequency CC1101 in automatic mode (hopper) - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_hopper_update(SubGhzTxRx* instance); - -/** - * Get state hopper - * - * @param instance Pointer to a SubGhzTxRx - * @return SubGhzHopperState - */ -SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance); - -/** - * Set state hopper - * - * @param instance Pointer to a SubGhzTxRx - * @param state State hopper - */ -void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state); - -/** - * Unpause hopper - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_hopper_unpause(SubGhzTxRx* instance); - -/** - * Set pause hopper - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_hopper_pause(SubGhzTxRx* instance); - -/** - * Speaker on - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_speaker_on(SubGhzTxRx* instance); - -/** - * Speaker off - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_speaker_off(SubGhzTxRx* instance); - -/** - * Speaker mute - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_speaker_mute(SubGhzTxRx* instance); - -/** - * Speaker unmute - * - * @param instance Pointer to a SubGhzTxRx - */ -void subghz_txrx_speaker_unmute(SubGhzTxRx* instance); - -/** - * Set state speaker - * - * @param instance Pointer to a SubGhzTxRx - * @param state State speaker - */ -void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state); - -/** - * Get state speaker - * - * @param instance Pointer to a SubGhzTxRx - * @return SubGhzSpeakerState - */ -SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); - -/** - * load decoder by name protocol - * - * @param instance Pointer to a SubGhzTxRx - * @param name_protocol Name protocol - * @return bool True if the decoder is loaded - */ -bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol); - -/** - * Get decoder - * - * @param instance Pointer to a SubGhzTxRx - * @return SubGhzProtocolDecoderBase* Pointer to a SubGhzProtocolDecoderBase - */ -SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance); - -/** - * Set callback for save data - * - * @param instance Pointer to a SubGhzTxRx - * @param callback Callback for save data - * @param context Context for callback - */ -void subghz_txrx_set_need_save_callback( - SubGhzTxRx* instance, - SubGhzTxRxNeedSaveCallback callback, - void* context); - -/** - * Get pointer to a load data key - * - * @param instance Pointer to a SubGhzTxRx - * @return FlipperFormat* - */ -FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance); - -/** - * Get pointer to a SugGhzSetting - * - * @param instance Pointer to a SubGhzTxRx - * @return SubGhzSetting* - */ -SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance); - -/** - * Is it possible to save this protocol - * - * @param instance Pointer to a SubGhzTxRx - * @return bool True if it is possible to save this protocol - */ -bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance); - -/** - * Is it possible to send this protocol - * - * @param instance Pointer to a SubGhzTxRx - * @return bool True if it is possible to send this protocol - */ -bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type); - -/** - * Set filter, what types of decoder to use - * - * @param instance Pointer to a SubGhzTxRx - * @param filter Filter - */ -void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter); - -/** - * Set callback for receive data - * - * @param instance Pointer to a SubGhzTxRx - * @param callback Callback for receive data - * @param context Context for callback - */ -void subghz_txrx_set_rx_calback( - SubGhzTxRx* instance, - SubGhzReceiverCallback callback, - void* context); - -/** - * Set callback for Raw decoder, end of data transfer - * - * @param instance Pointer to a SubGhzTxRx - * @param callback Callback for Raw decoder, end of data transfer - * @param context Context for callback - */ -void subghz_txrx_set_raw_file_encoder_worker_callback_end( - SubGhzTxRx* instance, - SubGhzProtocolEncoderRAWCallbackEnd callback, - void* context); - -/* Checking if an external radio device is connected -* -* @param instance Pointer to a SubGhzTxRx -* @param name Name of external radio device -* @return bool True if is connected to the external radio device -*/ -bool subghz_txrx_radio_device_is_external_connected(SubGhzTxRx* instance, const char* name); - -/* Set the selected radio device to use -* -* @param instance Pointer to a SubGhzTxRx -* @param radio_device_type Radio device type -* @return SubGhzRadioDeviceType Type of installed radio device -*/ -SubGhzRadioDeviceType - subghz_txrx_radio_device_set(SubGhzTxRx* instance, SubGhzRadioDeviceType radio_device_type); - -/* Get the selected radio device to use -* -* @param instance Pointer to a SubGhzTxRx -* @return SubGhzRadioDeviceType Type of installed radio device -*/ -SubGhzRadioDeviceType subghz_txrx_radio_device_get(SubGhzTxRx* instance); - -/* Get RSSI the selected radio device to use -* -* @param instance Pointer to a SubGhzTxRx -* @return float RSSI -*/ -float subghz_txrx_radio_device_get_rssi(SubGhzTxRx* instance); - -/* Get name the selected radio device to use -* -* @param instance Pointer to a SubGhzTxRx -* @return const char* Name of installed radio device -*/ -const char* subghz_txrx_radio_device_get_name(SubGhzTxRx* instance); - -/* Get get intelligence whether frequency the selected radio device to use -* -* @param instance Pointer to a SubGhzTxRx -* @return bool True if the frequency is valid -*/ -bool subghz_txrx_radio_device_is_frequecy_valid(SubGhzTxRx* instance, uint32_t frequency); - -bool subghz_txrx_radio_device_is_tx_alowed(SubGhzTxRx* instance, uint32_t frequency); - -void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); -bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); - -void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance); - -SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance); // TODO use only in DecodeRaw diff --git a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx_i.h b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx_i.h deleted file mode 100644 index f058c2282..000000000 --- a/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx_i.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "subghz_txrx.h" - -struct SubGhzTxRx { - SubGhzWorker* worker; - - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzTransmitter* transmitter; - SubGhzProtocolDecoderBase* decoder_result; - FlipperFormat* fff_data; - - SubGhzRadioPreset* preset; - SubGhzSetting* setting; - - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - bool is_database_loaded; - SubGhzHopperState hopper_state; - - SubGhzTxRxState txrx_state; - SubGhzSpeakerState speaker_state; - const SubGhzDevice* radio_device; - SubGhzRadioDeviceType radio_device_type; - - SubGhzTxRxNeedSaveCallback need_save_callback; - void* need_save_context; - - bool debug_pin_state; -}; diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene.c deleted file mode 100644 index c45285b96..000000000 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../subghz_remote_app_i.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const subrem_scene_on_enter_handlers[])(void*) = { -#include "subrem_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const subrem_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "subrem_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const subrem_scene_on_exit_handlers[])(void* context) = { -#include "subrem_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers subrem_scene_handlers = { - .on_enter_handlers = subrem_scene_on_enter_handlers, - .on_event_handlers = subrem_scene_on_event_handlers, - .on_exit_handlers = subrem_scene_on_exit_handlers, - .scene_num = SubRemSceneNum, -}; diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene.h b/applications/external/subghz_remote_configurator/scenes/subrem_scene.h deleted file mode 100644 index 5c01f8ca5..000000000 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) SubRemScene##id, -typedef enum { -#include "subrem_scene_config.h" - SubRemSceneNum, -} SubRemScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers subrem_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "subrem_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "subrem_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "subrem_scene_config.h" -#undef ADD_SCENE diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_config.h b/applications/external/subghz_remote_configurator/scenes/subrem_scene_config.h deleted file mode 100644 index 720eba42f..000000000 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_config.h +++ /dev/null @@ -1,8 +0,0 @@ -ADD_SCENE(subrem, start, Start) -ADD_SCENE(subrem, open_map_file, OpenMapFile) -ADD_SCENE(subrem, edit_menu, EditMenu) -ADD_SCENE(subrem, edit_submenu, EditSubMenu) -ADD_SCENE(subrem, edit_label, EditLabel) -ADD_SCENE(subrem, open_sub_file, OpenSubFile) -ADD_SCENE(subrem, edit_preview, EditPreview) -ADD_SCENE(subrem, enter_new_name, EnterNewName) \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_map_file.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_map_file.c deleted file mode 100644 index 77f2d2d56..000000000 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_map_file.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "../subghz_remote_app_i.h" - -void subrem_scene_open_map_file_on_enter(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - - SubRemLoadMapState load_state = subrem_load_from_file(app); - uint32_t start_scene_state = - scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart); - - // TODO if optimization - - if(load_state == SubRemLoadMapStateBack) { - scene_manager_previous_scene(app->scene_manager); - } else if(start_scene_state == SubmenuIndexSubRemEditMapFile) { - scene_manager_set_scene_state(app->scene_manager, SubRemSceneEditMenu, SubRemSubKeyNameUp); - scene_manager_next_scene(app->scene_manager, SubRemSceneEditMenu); - } -} - -bool subrem_scene_open_map_file_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void subrem_scene_open_map_file_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_start.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_start.c deleted file mode 100644 index e5a254111..000000000 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_start.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "../subghz_remote_app_i.h" -#include "../helpers/subrem_custom_event.h" - -void subrem_scene_start_submenu_callback(void* context, uint32_t index) { - furi_assert(context); - SubGhzRemoteApp* app = context; - - view_dispatcher_send_custom_event(app->view_dispatcher, index); -} - -void subrem_scene_start_on_enter(void* context) { - furi_assert(context); - - SubGhzRemoteApp* app = context; - Submenu* submenu = app->submenu; - submenu_add_item( - submenu, - "Edit Map File", - SubmenuIndexSubRemEditMapFile, - subrem_scene_start_submenu_callback, - app); - submenu_add_item( - submenu, - "New Map File", - SubmenuIndexSubRemNewMapFile, - subrem_scene_start_submenu_callback, - app); - // submenu_add_item( - // submenu, - // "About", - // SubmenuIndexSubGhzRemoteAbout, - // subrem_scene_start_submenu_callback, - // app); - - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); - - view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDSubmenu); -} - -bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { - furi_assert(context); - - SubGhzRemoteApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSubRemEditMapFile) { - scene_manager_set_scene_state( - app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemEditMapFile); - scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); - consumed = true; - } else if(event.event == SubmenuIndexSubRemNewMapFile) { - scene_manager_set_scene_state( - app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemNewMapFile); - scene_manager_next_scene(app->scene_manager, SubRemSceneEnterNewName); - consumed = true; - } - // } else if(event.event == SubmenuIndexSubRemAbout) { - // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); - // consumed = true; - // } - } - - return consumed; -} - -void subrem_scene_start_on_exit(void* context) { - furi_assert(context); - - SubGhzRemoteApp* app = context; - submenu_reset(app->submenu); -} diff --git a/applications/external/subghz_remote_configurator/subghz_remote_app.c b/applications/external/subghz_remote_configurator/subghz_remote_app.c deleted file mode 100644 index 7cbbabfcb..000000000 --- a/applications/external/subghz_remote_configurator/subghz_remote_app.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "subghz_remote_app_i.h" - -static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - SubGhzRemoteApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool subghz_remote_app_back_event_callback(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void subghz_remote_app_tick_event_callback(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -SubGhzRemoteApp* subghz_remote_app_alloc() { - SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); - - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate(storage, EXT_PATH("unirf"), SUBREM_APP_FOLDER); - storage_common_migrate(storage, EXT_PATH("subghz/unirf"), SUBREM_APP_FOLDER); - - if(!storage_simply_mkdir(storage, SUBREM_APP_FOLDER)) { - //FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER); - } - furi_record_close(RECORD_STORAGE); - - // furi_hal_power_suppress_charge_enter(); - - app->file_path = furi_string_alloc(); - furi_string_set(app->file_path, SUBREM_APP_FOLDER); - - // GUI - app->gui = furi_record_open(RECORD_GUI); - - // View Dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - - app->scene_manager = scene_manager_alloc(&subrem_scene_handlers, app); - view_dispatcher_enable_queue(app->view_dispatcher); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, subghz_remote_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, subghz_remote_app_back_event_callback); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, subghz_remote_app_tick_event_callback, 100); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Open Notification record - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // SubMenu - app->submenu = submenu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SubRemViewIDSubmenu, submenu_get_view(app->submenu)); - - // Dialog - app->dialogs = furi_record_open(RECORD_DIALOGS); - - // TextInput - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SubRemViewIDTextInput, text_input_get_view(app->text_input)); - - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SubRemViewIDWidget, widget_get_view(app->widget)); - - // Popup - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, SubRemViewIDPopup, popup_get_view(app->popup)); - - // Remote view - app->subrem_remote_view = subrem_view_remote_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SubRemViewIDRemote, - subrem_view_remote_get_view(app->subrem_remote_view)); - - // Edit Menu view - app->subrem_edit_menu = subrem_view_edit_menu_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SubRemViewIDEditMenu, - subrem_view_edit_menu_get_view(app->subrem_edit_menu)); - - app->map_preset = malloc(sizeof(SubRemMapPreset)); - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc(); - } - - app->txrx = subghz_txrx_alloc(); - - subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app); - - app->map_not_saved = false; - -#ifdef SUBREM_LIGHT - scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); -#else - scene_manager_next_scene(app->scene_manager, SubRemSceneStart); - scene_manager_set_scene_state( - app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemEditMapFile); -#endif - - return app; -} - -void subghz_remote_app_free(SubGhzRemoteApp* app) { - furi_assert(app); - - // furi_hal_power_suppress_charge_exit(); - - // Submenu - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDSubmenu); - submenu_free(app->submenu); - - // Dialog - furi_record_close(RECORD_DIALOGS); - - // TextInput - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDTextInput); - text_input_free(app->text_input); - - // Widget - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDWidget); - widget_free(app->widget); - - // Popup - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDPopup); - popup_free(app->popup); - - // Remote view - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); - subrem_view_remote_free(app->subrem_remote_view); - - // Edit view - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDEditMenu); - subrem_view_edit_menu_free(app->subrem_edit_menu); - - scene_manager_free(app->scene_manager); - view_dispatcher_free(app->view_dispatcher); - - subghz_txrx_free(app->txrx); - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_free(app->map_preset->subs_preset[i]); - } - free(app->map_preset); - - // Notifications - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - - // Close records - furi_record_close(RECORD_GUI); - - // Path strings - furi_string_free(app->file_path); - - free(app); -} - -int32_t subghz_remote_config_app(void* p) { - UNUSED(p); - SubGhzRemoteApp* subghz_remote_app = subghz_remote_app_alloc(); - - furi_string_set(subghz_remote_app->file_path, SUBREM_APP_FOLDER); - - view_dispatcher_run(subghz_remote_app->view_dispatcher); - - subghz_remote_app_free(subghz_remote_app); - - return 0; -} diff --git a/applications/external/subghz_remote_configurator/subghz_remote_app_i.c b/applications/external/subghz_remote_configurator/subghz_remote_app_i.c deleted file mode 100644 index 1eb64541f..000000000 --- a/applications/external/subghz_remote_configurator/subghz_remote_app_i.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "subghz_remote_app_i.h" -#include -#include - -#include "helpers/txrx/subghz_txrx.h" - -// #include -// #include - -// #include -// #include - -#define TAG "SubGhzRemote" - -static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { - [SubRemSubKeyNameUp] = {"UP", "ULABEL"}, - [SubRemSubKeyNameDown] = {"DOWN", "DLABEL"}, - [SubRemSubKeyNameLeft] = {"LEFT", "LLABEL"}, - [SubRemSubKeyNameRight] = {"RIGHT", "RLABEL"}, - [SubRemSubKeyNameOk] = {"OK", "OKLABEL"}, -}; - -void subrem_map_preset_reset(SubRemMapPreset* map_preset) { - furi_assert(map_preset); - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_reset(map_preset->subs_preset[i]); - } -} - -static SubRemLoadMapState subrem_map_preset_check( - SubRemMapPreset* map_preset, - SubGhzTxRx* txrx, - FlipperFormat* fff_data_file) { - furi_assert(map_preset); - furi_assert(txrx); - - bool all_loaded = true; - SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; - - SubRemLoadSubState sub_loadig_state; - SubRemSubFilePreset* sub_preset; - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = map_preset->subs_preset[i]; - - sub_loadig_state = SubRemLoadSubStateErrorNoFile; - - if(furi_string_empty(sub_preset->file_path)) { - // FURI_LOG_I(TAG, "Empty file path"); - } else if(!flipper_format_file_open_existing( - fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { - sub_preset->load_state = SubRemLoadSubStateErrorNoFile; - FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); - } else { - sub_loadig_state = subrem_sub_preset_load(sub_preset, txrx, fff_data_file); - } - - if(sub_loadig_state != SubRemLoadSubStateOK) { - all_loaded = false; - } else { - ret = SubRemLoadMapStateNotAllOK; - } - - if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { - ret = SubRemLoadMapStateOK; - } - - flipper_format_file_close(fff_data_file); - } - - return ret; -} - -static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* fff_data_file) { - furi_assert(map_preset); - bool ret = false; - SubRemSubFilePreset* sub_preset; - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = map_preset->subs_preset[i]; - if(!flipper_format_read_string( - fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { -#if FURI_DEBUG - FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); -#endif - sub_preset->type = SubGhzProtocolTypeUnknown; - } else if(!path_contains_only_ascii(furi_string_get_cstr(sub_preset->file_path))) { - FURI_LOG_E(TAG, "Incorrect characters in [%s] file path", map_file_labels[i][0]); - sub_preset->type = SubGhzProtocolTypeUnknown; - } else if(!flipper_format_rewind(fff_data_file)) { - // Rewind error - } else if(!flipper_format_read_string( - fff_data_file, map_file_labels[i][1], sub_preset->label)) { -#if FURI_DEBUG - FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); -#endif - ret = true; - } else { - ret = true; - } - if(ret) { - // Preload seccesful - FURI_LOG_I( - TAG, - "%-5s: %s %s", - map_file_labels[i][0], - furi_string_get_cstr(sub_preset->label), - furi_string_get_cstr(sub_preset->file_path)); - sub_preset->load_state = SubRemLoadSubStatePreloaded; - } - - flipper_format_rewind(fff_data_file); - } - return ret; -} - -SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { - furi_assert(app); - furi_assert(file_path); -#if FURI_DEBUG - FURI_LOG_I(TAG, "Load Map File Start"); -#endif - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - SubRemLoadMapState ret = SubRemLoadMapStateErrorOpenError; -#if FURI_DEBUG - FURI_LOG_I(TAG, "Open Map File.."); -#endif - subrem_map_preset_reset(app->map_preset); - - if(!flipper_format_file_open_existing(fff_data_file, file_path)) { - FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); - ret = SubRemLoadMapStateErrorOpenError; - } else { - if(!subrem_map_preset_load(app->map_preset, fff_data_file)) { - FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); - // ret = // error for popup - } else if(!flipper_format_file_close(fff_data_file)) { - ret = SubRemLoadMapStateErrorOpenError; - } else { - ret = subrem_map_preset_check(app->map_preset, app->txrx, fff_data_file); - } - } - - if(ret == SubRemLoadMapStateOK) { - FURI_LOG_I(TAG, "Load Map File Seccesful"); - } else if(ret == SubRemLoadMapStateNotAllOK) { - FURI_LOG_I(TAG, "Load Map File Seccesful [Not all files]"); - } else { - FURI_LOG_E(TAG, "Broken Map File"); - } - - flipper_format_file_close(fff_data_file); - flipper_format_free(fff_data_file); - - furi_record_close(RECORD_STORAGE); - return ret; -} - -bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* sub_file_name) { - furi_assert(flipper_format); - furi_assert(sub_file_name); - - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); - - bool saved = false; - uint32_t repeat = 200; - FuriString* file_dir = furi_string_alloc(); - - path_extract_dirname(sub_file_name, file_dir); - do { - // removing additional fields - flipper_format_delete_key(flipper_format, "Repeat"); - // flipper_format_delete_key(flipper_format, "Manufacture"); - - if(!storage_simply_remove(storage, sub_file_name)) { - break; - } - - //ToDo check Write - stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, sub_file_name, FSOM_CREATE_ALWAYS); - - if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - saved = true; - } while(0); - - furi_string_free(file_dir); - furi_record_close(RECORD_STORAGE); - return saved; -} - -void subrem_save_active_sub(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - - SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; - subrem_save_protocol_to_file( - sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); -} - -SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { - furi_assert(app); - - FuriString* file_path = furi_string_alloc(); - SubRemLoadMapState ret = SubRemLoadMapStateBack; - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_subrem_10px); - browser_options.base_path = SUBREM_APP_FOLDER; - - // Input events and views are managed by file_select - if(!dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) { - } else { - ret = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); - } - - furi_string_free(file_path); - - return ret; -} - -bool subrem_save_map_to_file(SubGhzRemoteApp* app) { - furi_assert(app); - - const char* file_name = furi_string_get_cstr(app->file_path); - bool saved = false; - FlipperFormat* fff_data = flipper_format_string_alloc(); - - SubRemSubFilePreset* sub_preset; - - flipper_format_write_header_cstr( - fff_data, SUBREM_APP_APP_FILE_TYPE, SUBREM_APP_APP_FILE_VERSION); - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->map_preset->subs_preset[i]; - if(!furi_string_empty(sub_preset->file_path)) { - flipper_format_write_string(fff_data, map_file_labels[i][0], sub_preset->file_path); - } - } - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->map_preset->subs_preset[i]; - if(!furi_string_empty(sub_preset->file_path)) { - flipper_format_write_string(fff_data, map_file_labels[i][1], sub_preset->label); - } - } - - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* flipper_format_stream = flipper_format_get_raw_stream(fff_data); - - do { - if(!storage_simply_remove(storage, file_name)) { - break; - } - //ToDo check Write - stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, file_name, FSOM_CREATE_ALWAYS); - - saved = true; - } while(0); - - furi_record_close(RECORD_STORAGE); - flipper_format_free(fff_data); - - return saved; -} \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/subghz_remote_app_i.h b/applications/external/subghz_remote_configurator/subghz_remote_app_i.h deleted file mode 100644 index f096a7d46..000000000 --- a/applications/external/subghz_remote_configurator/subghz_remote_app_i.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "helpers/subrem_types.h" -#include "helpers/subrem_presets.h" -#include "scenes/subrem_scene.h" - -#include "helpers/txrx/subghz_txrx.h" -#include - -#include "views/remote.h" -#include "views/edit_menu.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define SUBREM_APP_FOLDER EXT_PATH("subghz/remote") -#define SUBREM_MAX_LEN_NAME 64 - -typedef struct { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - NotificationApp* notifications; - DialogsApp* dialogs; - Widget* widget; - Popup* popup; - TextInput* text_input; - Submenu* submenu; - - FuriString* file_path; - char file_name_tmp[SUBREM_MAX_LEN_NAME]; - - SubRemViewRemote* subrem_remote_view; - SubRemViewEditMenu* subrem_edit_menu; - - SubRemMapPreset* map_preset; - - SubGhzTxRx* txrx; - - bool map_not_saved; - - uint8_t chusen_sub; -} SubGhzRemoteApp; - -SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); - -SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path); - -void subrem_map_preset_reset(SubRemMapPreset* map_preset); - -bool subrem_save_map_to_file(SubGhzRemoteApp* app); - -void subrem_save_active_sub(void* context); diff --git a/applications/external/subghz_remote_configurator/subrem_10px.png b/applications/external/subghz_remote_configurator/subrem_10px.png deleted file mode 100644 index c6b410f4c..000000000 Binary files a/applications/external/subghz_remote_configurator/subrem_10px.png and /dev/null differ diff --git a/applications/external/subghz_remote_configurator/views/remote.c b/applications/external/subghz_remote_configurator/views/remote.c deleted file mode 100644 index c2b41cfd6..000000000 --- a/applications/external/subghz_remote_configurator/views/remote.c +++ /dev/null @@ -1,294 +0,0 @@ -#include "remote.h" -#include "../subghz_remote_app_i.h" - -#include -#include - -#include - -#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 30 -#define SUBREM_VIEW_REMOTE_LEFT_OFFSET 10 -#define SUBREM_VIEW_REMOTE_RIGHT_OFFSET 22 - -struct SubRemViewRemote { - View* view; - SubRemViewRemoteCallback callback; - void* context; -}; - -typedef struct { - char* labels[SubRemSubKeyNameMaxCount]; - - SubRemViewRemoteState state; - - uint8_t pressed_btn; -} SubRemViewRemoteModel; - -void subrem_view_remote_set_callback( - SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteCallback callback, - void* context) { - furi_assert(subrem_view_remote); - - subrem_view_remote->callback = callback; - subrem_view_remote->context = context; -} - -void subrem_view_remote_update_data_labels( - SubRemViewRemote* subrem_view_remote, - SubRemSubFilePreset** subs_presets) { - furi_assert(subrem_view_remote); - furi_assert(subs_presets); - - FuriString* labels[SubRemSubKeyNameMaxCount]; - SubRemSubFilePreset* sub_preset; - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = subs_presets[i]; - switch(sub_preset->load_state) { - case SubRemLoadSubStateOK: - if(!furi_string_empty(sub_preset->label)) { - labels[i] = furi_string_alloc_set(sub_preset->label); - } else if(!furi_string_empty(sub_preset->file_path)) { - labels[i] = furi_string_alloc(); - path_extract_filename(sub_preset->file_path, labels[i], true); - } else { - labels[i] = furi_string_alloc_set("Empty Label"); - } - break; - - case SubRemLoadSubStateErrorNoFile: - labels[i] = furi_string_alloc_set("[X] Can't open file"); - break; - - case SubRemLoadSubStateErrorFreq: - case SubRemLoadSubStateErrorMod: - case SubRemLoadSubStateErrorProtocol: - labels[i] = furi_string_alloc_set("[X] Error in .sub file"); - break; - - default: - labels[i] = furi_string_alloc_set(""); - break; - } - } - - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - strncpy( - model->labels[i], - furi_string_get_cstr(labels[i]), - SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - } - }, - true); - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - furi_string_free(labels[i]); - } -} - -void subrem_view_remote_set_state( - SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state, - uint8_t presed_btn) { - furi_assert(subrem_view_remote); - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { - model->state = state; - model->pressed_btn = presed_btn; - }, - true); -} - -void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - canvas_clear(canvas); - - //Icons for Labels - //canvas_draw_icon(canvas, 0, 0, &I_SubGHzRemote_LeftAlignedButtons_9x64); - canvas_draw_icon(canvas, 1, 5, &I_ButtonUp_7x4); - canvas_draw_icon(canvas, 1, 15, &I_ButtonDown_7x4); - canvas_draw_icon(canvas, 2, 23, &I_ButtonLeft_4x7); - canvas_draw_icon(canvas, 2, 33, &I_ButtonRight_4x7); - canvas_draw_icon(canvas, 0, 42, &I_Ok_btn_9x9); - canvas_draw_icon(canvas, 0, 53, &I_back_10px); - - //Labels - canvas_set_font(canvas, FontSecondary); - uint8_t y = 0; - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - elements_text_box( - canvas, - SUBREM_VIEW_REMOTE_LEFT_OFFSET, - y + 2, - 126 - SUBREM_VIEW_REMOTE_LEFT_OFFSET - SUBREM_VIEW_REMOTE_RIGHT_OFFSET, - 12, - AlignLeft, - AlignBottom, - model->labels[i], - false); - y += 10; - } - - if(model->state == SubRemViewRemoteStateOFF) { - elements_button_left(canvas, "Back"); - elements_button_right(canvas, "Save"); - } else { - canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); - } - - //Status text and indicator - canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); - - if(model->state == SubRemViewRemoteStateIdle || model->state == SubRemViewRemoteStateOFF) { - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); - } else { - switch(model->state) { - case SubRemViewRemoteStateSending: - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Send"); - break; - case SubRemViewRemoteStateLoading: - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Load"); - break; - default: -#if FURI_DEBUG - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Wrong_state"); -#endif - break; - } - - switch(model->pressed_btn) { - case SubRemSubKeyNameUp: - canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9); - break; - case SubRemSubKeyNameDown: - canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); - break; - case SubRemSubKeyNameLeft: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); - break; - case SubRemSubKeyNameRight: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); - break; - case SubRemSubKeyNameOk: - canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); - break; - } - } -} - -bool subrem_view_remote_input(InputEvent* event, void* context) { - furi_assert(context); - SubRemViewRemote* subrem_view_remote = context; - - if(event->key == InputKeyBack && event->type == InputTypeLong) { - subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 0; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteForcedStop, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyBack) { - return true; - } - // BACK button processing end - - if(event->key == InputKeyUp && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyDown && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartDOWN, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyLeft && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartLEFT, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyRight && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartRIGHT, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyOk && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartOK, subrem_view_remote->context); - return true; - } else if(event->type == InputTypeRelease) { - subrem_view_remote->callback(SubRemCustomEventViewRemoteStop, subrem_view_remote->context); - return true; - } - - return true; -} - -void subrem_view_remote_enter(void* context) { - furi_assert(context); -} - -void subrem_view_remote_exit(void* context) { - furi_assert(context); -} - -SubRemViewRemote* subrem_view_remote_alloc() { - SubRemViewRemote* subrem_view_remote = malloc(sizeof(SubRemViewRemote)); - - // View allocation and configuration - subrem_view_remote->view = view_alloc(); - view_allocate_model( - subrem_view_remote->view, ViewModelTypeLocking, sizeof(SubRemViewRemoteModel)); - view_set_context(subrem_view_remote->view, subrem_view_remote); - view_set_draw_callback(subrem_view_remote->view, (ViewDrawCallback)subrem_view_remote_draw); - view_set_input_callback(subrem_view_remote->view, subrem_view_remote_input); - view_set_enter_callback(subrem_view_remote->view, subrem_view_remote_enter); - view_set_exit_callback(subrem_view_remote->view, subrem_view_remote_exit); - - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { - model->state = SubRemViewRemoteStateIdle; - - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - model->labels[i] = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - strcpy(model->labels[i], ""); - } - - model->pressed_btn = 0; - }, - true); - return subrem_view_remote; -} - -void subrem_view_remote_free(SubRemViewRemote* subghz_remote) { - furi_assert(subghz_remote); - - with_view_model( - subghz_remote->view, - SubRemViewRemoteModel * model, - { - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - free(model->labels[i]); - } - }, - true); - view_free(subghz_remote->view); - free(subghz_remote); -} - -View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote) { - furi_assert(subrem_view_remote); - return subrem_view_remote->view; -} \ No newline at end of file diff --git a/applications/external/subghz_remote_configurator/views/remote.h b/applications/external/subghz_remote_configurator/views/remote.h deleted file mode 100644 index 5b1e8153a..000000000 --- a/applications/external/subghz_remote_configurator/views/remote.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include "../helpers/subrem_custom_event.h" -#include "../helpers/subrem_presets.h" - -typedef enum { - SubRemViewRemoteStateIdle, - SubRemViewRemoteStateLoading, - SubRemViewRemoteStateSending, - SubRemViewRemoteStateOFF, -} SubRemViewRemoteState; - -typedef struct SubRemViewRemote SubRemViewRemote; - -typedef void (*SubRemViewRemoteCallback)(SubRemCustomEvent event, void* context); - -void subrem_view_remote_set_callback( - SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteCallback callback, - void* context); - -SubRemViewRemote* subrem_view_remote_alloc(); - -void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote); - -View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote); - -void subrem_view_remote_update_data_labels( - SubRemViewRemote* subrem_view_remote, - SubRemSubFilePreset** subs_presets); - -void subrem_view_remote_set_state( - SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state, - uint8_t presed_btn); \ No newline at end of file