diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index d6d6d025f..cf7b64fb0 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -86,3 +86,5 @@ typedef enum { SubGhzViewReceiverModeLive, SubGhzViewReceiverModeFile, } SubGhzViewReceiverMode; + +#define SUBGHZ_HISTORY_REMOVE_SAVED_ITEMS 1 diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index c2731910b..fcc579d93 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -12,10 +12,12 @@ ADD_SCENE(subghz, show_only_rx, ShowOnlyRx) ADD_SCENE(subghz, saved_menu, SavedMenu) ADD_SCENE(subghz, delete, Delete) ADD_SCENE(subghz, delete_success, DeleteSuccess) +#if FURI_DEBUG ADD_SCENE(subghz, test, Test) ADD_SCENE(subghz, test_static, TestStatic) ADD_SCENE(subghz, test_carrier, TestCarrier) ADD_SCENE(subghz, test_packet, TestPacket) +#endif ADD_SCENE(subghz, set_type, SetType) ADD_SCENE(subghz, set_fix_faac_868, SetFixFaac868) ADD_SCENE(subghz, set_cnt_faac_868, SetCntFaac868) diff --git a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c index 1f1957e32..8889dac83 100644 --- a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c +++ b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c @@ -31,7 +31,7 @@ bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent e return true; } else if(event.event == SubGhzCustomEventViewReceiverUnlock) { // Don't need to save, we already saved on short event -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_W(TAG, "Goto next scene!"); #endif scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 7392221dc..b83ad700f 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -134,12 +134,22 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { //Restore default setting - subghz_preset_init( - subghz, - subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset), - subghz->last_settings->frequency, - NULL, - 0); + if(subghz->raw_send_only) { + subghz_preset_init( + subghz, + "AM650", + subghz_setting_get_default_frequency(subghz->setting), + NULL, + 0); + } else { + subghz_preset_init( + subghz, + subghz_setting_get_preset_name( + subghz->setting, subghz->last_settings->preset), + subghz->last_settings->frequency, + NULL, + 0); + } if(!scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneSaved)) { if(!scene_manager_search_and_switch_to_previous_scene( @@ -340,6 +350,10 @@ void subghz_scene_read_raw_on_exit(void* context) { subghz->state_notifications = SubGhzNotificationStateIDLE; notification_message(subghz->notifications, &sequence_reset_rgb); - //filter restoration +//filter restoration +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + subghz_last_settings_set_detect_raw_values(subghz); +#else subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); +#endif } \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 4a35c5f2c..4fb79a8f1 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -185,6 +185,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case SubGhzCustomEventViewReceiverOK: + // Show file info, scene: receiver_info subghz->txrx->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 0175cd0fd..6d9d2fef5 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -29,10 +29,12 @@ const char* const detect_raw_text[DETECT_RAW_COUNT] = { "ON", }; +#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = { SubGhzProtocolFlag_Decodable, SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW, }; +#endif #define RSSI_THRESHOLD_COUNT 7 const char* const rssi_threshold_text[RSSI_THRESHOLD_COUNT] = { @@ -105,6 +107,7 @@ uint8_t subghz_scene_receiver_config_hopper_value_index( } } +#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING uint8_t subghz_scene_receiver_config_detect_raw_value_index( const SubGhzProtocolFlag value, const SubGhzProtocolFlag values[], @@ -118,6 +121,7 @@ uint8_t subghz_scene_receiver_config_detect_raw_value_index( } return index; } +#endif uint8_t subghz_scene_receiver_config_rssi_threshold_value_index( const int value, @@ -186,12 +190,18 @@ static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, detect_raw_text[index]); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + subghz->last_settings->detect_raw = index; + + subghz_last_settings_set_detect_raw_values(subghz); +#else subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]); subghz_protocol_decoder_raw_set_auto_mode( subghz_receiver_search_decoder_base_by_name( subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), (index == 1)); +#endif } static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { @@ -244,10 +254,10 @@ void subghz_scene_receiver_config_on_enter(void* context) { VariableItem* item; uint8_t value_index; -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_D( TAG, - "last frequency: %d, preset: %d", + "Last frequency: %d, Preset: %d", subghz->last_settings->frequency, subghz->last_settings->preset); #endif @@ -304,10 +314,14 @@ void subghz_scene_receiver_config_on_enter(void* context) { DETECT_RAW_COUNT, subghz_scene_receiver_config_set_detect_raw, subghz); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + value_index = subghz->last_settings->detect_raw; +#else value_index = subghz_scene_receiver_config_detect_raw_value_index( subghz_receiver_get_filter(subghz->txrx->receiver), detect_raw_value, DETECT_RAW_COUNT); +#endif variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, detect_raw_text[value_index]); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 5621bb847..be171f421 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -26,6 +26,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { subghz->txrx->receiver, subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); if(subghz->txrx->decoder_result) { + // In this case flipper format was changed to short file content subghz_protocol_decoder_base_deserialize( subghz->txrx->decoder_result, subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index 652499d05..5d5ae235e 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -1,4 +1,6 @@ #include "../subghz_i.h" +#include +#include typedef enum { SubGhzRpcStateIdle, @@ -97,4 +99,9 @@ void subghz_scene_rpc_on_exit(void* context) { popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); popup_set_icon(popup, 0, 0, NULL); + + keeloq_reset_mfname(); + keeloq_reset_kl_type(); + star_line_reset_mfname(); + star_line_reset_kl_type(); } diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index 35c7ecb9c..752fb8a92 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -21,11 +21,15 @@ void subghz_scene_start_on_enter(void* context) { if(subghz->state_notifications == SubGhzNotificationStateStarting) { subghz->state_notifications = SubGhzNotificationStateIDLE; } +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + subghz_last_settings_set_detect_raw_values(subghz); +#else subghz_protocol_decoder_raw_set_auto_mode( subghz_receiver_search_decoder_base_by_name( subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), false); subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); +#endif submenu_add_item( subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); @@ -49,10 +53,12 @@ void subghz_scene_start_on_enter(void* context) { SubmenuIndexFrequencyAnalyzer, subghz_scene_start_submenu_callback, subghz); +#if FURI_DEBUG if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { submenu_add_item( subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); } +#endif submenu_set_selected_item( subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart)); @@ -93,12 +99,16 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer); return true; - } else if(event.event == SubmenuIndexTest) { + + } +#if FURI_DEBUG + else if(event.event == SubmenuIndexTest) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest); return true; } +#endif } return false; } diff --git a/applications/main/subghz/scenes/subghz_scene_test.c b/applications/main/subghz/scenes/subghz_scene_test.c index 65f9bbdef..64473015b 100644 --- a/applications/main/subghz/scenes/subghz_scene_test.c +++ b/applications/main/subghz/scenes/subghz_scene_test.c @@ -1,3 +1,4 @@ +#if FURI_DEBUG #include "../subghz_i.h" enum SubmenuIndex { @@ -59,3 +60,4 @@ void subghz_scene_test_on_exit(void* context) { SubGhz* subghz = context; submenu_reset(subghz->submenu); } +#endif \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_test_carrier.c b/applications/main/subghz/scenes/subghz_scene_test_carrier.c index 9677792ba..4682a627c 100644 --- a/applications/main/subghz/scenes/subghz_scene_test_carrier.c +++ b/applications/main/subghz/scenes/subghz_scene_test_carrier.c @@ -1,3 +1,4 @@ +#if FURI_DEBUG #include "../subghz_i.h" #include "../views/subghz_test_carrier.h" @@ -28,3 +29,4 @@ bool subghz_scene_test_carrier_on_event(void* context, SceneManagerEvent event) void subghz_scene_test_carrier_on_exit(void* context) { UNUSED(context); } +#endif \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_test_packet.c b/applications/main/subghz/scenes/subghz_scene_test_packet.c index 99f0ab179..4757f9f3a 100644 --- a/applications/main/subghz/scenes/subghz_scene_test_packet.c +++ b/applications/main/subghz/scenes/subghz_scene_test_packet.c @@ -1,3 +1,4 @@ +#if FURI_DEBUG #include "../subghz_i.h" #include "../views/subghz_test_packet.h" @@ -28,3 +29,4 @@ bool subghz_scene_test_packet_on_event(void* context, SceneManagerEvent event) { void subghz_scene_test_packet_on_exit(void* context) { UNUSED(context); } +#endif \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_test_static.c b/applications/main/subghz/scenes/subghz_scene_test_static.c index 10e6d02a1..959eb75b8 100644 --- a/applications/main/subghz/scenes/subghz_scene_test_static.c +++ b/applications/main/subghz/scenes/subghz_scene_test_static.c @@ -1,3 +1,4 @@ +#if FURI_DEBUG #include "../subghz_i.h" #include "../views/subghz_test_static.h" @@ -28,3 +29,4 @@ bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) { void subghz_scene_test_static_on_exit(void* context) { UNUSED(context); } +#endif \ No newline at end of file diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 8b9dd399f..176e9079e 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -61,7 +61,7 @@ void subghz_blink_stop(SubGhz* instance) { notification_message(instance->notifications, &sequence_blink_stop); } -SubGhz* subghz_alloc() { +SubGhz* subghz_alloc(bool alloc_for_tx_only) { SubGhz* subghz = malloc(sizeof(SubGhz)); string_init(subghz->file_path); @@ -88,38 +88,43 @@ SubGhz* subghz_alloc() { // Open Notification record subghz->notifications = furi_record_open(RECORD_NOTIFICATION); - // SubMenu - subghz->submenu = submenu_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewIdMenu, submenu_get_view(subghz->submenu)); - - // Receiver - subghz->subghz_receiver = subghz_view_receiver_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdReceiver, - subghz_view_receiver_get_view(subghz->subghz_receiver)); + if(!alloc_for_tx_only) { + // SubMenu + subghz->submenu = submenu_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, SubGhzViewIdMenu, submenu_get_view(subghz->submenu)); + // Receiver + subghz->subghz_receiver = subghz_view_receiver_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewIdReceiver, + subghz_view_receiver_get_view(subghz->subghz_receiver)); + } // Popup subghz->popup = popup_alloc(); view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewIdPopup, popup_get_view(subghz->popup)); + if(!alloc_for_tx_only) { + // Text Input + subghz->text_input = text_input_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewIdTextInput, + text_input_get_view(subghz->text_input)); - // Text Input - subghz->text_input = text_input_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewIdTextInput, text_input_get_view(subghz->text_input)); - - // Byte Input - subghz->byte_input = byte_input_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewIdByteInput, byte_input_get_view(subghz->byte_input)); - - // Custom Widget - subghz->widget = widget_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewIdWidget, widget_get_view(subghz->widget)); + // Byte Input + subghz->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewIdByteInput, + byte_input_get_view(subghz->byte_input)); + // Custom Widget + subghz->widget = widget_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, SubGhzViewIdWidget, widget_get_view(subghz->widget)); + } //Dialog subghz->dialogs = furi_record_open(RECORD_DIALOGS); @@ -129,28 +134,29 @@ SubGhz* subghz_alloc() { subghz->view_dispatcher, SubGhzViewIdTransmitter, subghz_view_transmitter_get_view(subghz->subghz_transmitter)); + if(!alloc_for_tx_only) { + // Variable Item List + subghz->variable_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewIdVariableItemList, + variable_item_list_get_view(subghz->variable_item_list)); - // Variable Item List - subghz->variable_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdVariableItemList, - variable_item_list_get_view(subghz->variable_item_list)); - - // Frequency Analyzer - subghz->subghz_frequency_analyzer = subghz_frequency_analyzer_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdFrequencyAnalyzer, - subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer)); - + // Frequency Analyzer + subghz->subghz_frequency_analyzer = subghz_frequency_analyzer_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewIdFrequencyAnalyzer, + subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer)); + } // Read RAW - subghz->subghz_read_raw = subghz_read_raw_alloc(); + subghz->subghz_read_raw = subghz_read_raw_alloc(alloc_for_tx_only); view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewIdReadRAW, subghz_read_raw_get_view(subghz->subghz_read_raw)); +#if FURI_DEBUG // Carrier Test Module subghz->subghz_test_carrier = subghz_test_carrier_alloc(); view_dispatcher_add_view( @@ -171,41 +177,64 @@ SubGhz* subghz_alloc() { subghz->view_dispatcher, SubGhzViewIdStatic, subghz_test_static_get_view(subghz->subghz_test_static)); +#endif //init setting subghz->setting = subghz_setting_alloc(); - subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user")); + if(alloc_for_tx_only) { + subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"), false); + } else { + subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user"), true); + } // Load last used values for Read, Read RAW, etc. or default - subghz->last_settings = subghz_last_settings_alloc(); - subghz_last_settings_load( - subghz->last_settings, subghz_setting_get_preset_count(subghz->setting)); + if(!alloc_for_tx_only) { + subghz->last_settings = subghz_last_settings_alloc(); + subghz_last_settings_load( + subghz->last_settings, subghz_setting_get_preset_count(subghz->setting)); #if FURI_DEBUG - FURI_LOG_D( - TAG, - "last frequency: %d, preset: %d", - subghz->last_settings->frequency, - subghz->last_settings->preset); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + FURI_LOG_D( + TAG, + "last frequency: %d, preset: %d, detect_raw: %d", + subghz->last_settings->frequency, + subghz->last_settings->preset, + subghz->last_settings->detect_raw); +#else + FURI_LOG_D( + TAG, + "last frequency: %d, preset: %d", + subghz->last_settings->frequency, + subghz->last_settings->preset); #endif - subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency); - +#endif + subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency); + } //init Worker & Protocol & History & KeyBoard subghz->lock = SubGhzLockOff; subghz->txrx = malloc(sizeof(SubGhzTxRx)); subghz->txrx->preset = malloc(sizeof(SubGhzPresetDefinition)); string_init(subghz->txrx->preset->name); - subghz_preset_init( - subghz, - subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset), - subghz->last_settings->frequency, - NULL, - 0); - + if(!alloc_for_tx_only) { + subghz_preset_init( + subghz, + subghz_setting_get_preset_name(subghz->setting, subghz->last_settings->preset), + subghz->last_settings->frequency, + NULL, + 0); + } else { + subghz_preset_init( + subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + } subghz->txrx->txrx_state = SubGhzTxRxStateSleep; subghz->txrx->hopper_state = SubGhzHopperStateOFF; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; - subghz->txrx->history = subghz_history_alloc(); + if(!alloc_for_tx_only) { + subghz->txrx->history = subghz_history_alloc(); + } + subghz->txrx->worker = subghz_worker_alloc(); + subghz->txrx->fff_data = flipper_format_string_alloc(); subghz->txrx->secure_data = malloc(sizeof(SecureData)); @@ -214,8 +243,13 @@ SubGhz* subghz_alloc() { subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo")); subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s")); + subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + subghz_last_settings_set_detect_raw_values(subghz); +#else subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); +#endif subghz_worker_set_overrun_callback( subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); @@ -229,7 +263,7 @@ SubGhz* subghz_alloc() { return subghz; } -void subghz_free(SubGhz* subghz) { +void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { furi_assert(subghz); if(subghz->rpc_ctx) { @@ -239,6 +273,7 @@ void subghz_free(SubGhz* subghz) { subghz->rpc_ctx = NULL; } +#if FURI_DEBUG // Packet Test view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket); subghz_test_packet_free(subghz->subghz_test_packet); @@ -250,46 +285,48 @@ void subghz_free(SubGhz* subghz) { // Static view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdStatic); subghz_test_static_free(subghz->subghz_test_static); +#endif - // Receiver - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReceiver); - subghz_view_receiver_free(subghz->subghz_receiver); + if(!alloc_for_tx_only) { + // Receiver + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReceiver); + subghz_view_receiver_free(subghz->subghz_receiver); - // TextInput - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTextInput); - text_input_free(subghz->text_input); + // TextInput + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTextInput); + text_input_free(subghz->text_input); - // ByteInput - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdByteInput); - byte_input_free(subghz->byte_input); - - // Custom Widget - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdWidget); - widget_free(subghz->widget); + // ByteInput + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdByteInput); + byte_input_free(subghz->byte_input); + // Custom Widget + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdWidget); + widget_free(subghz->widget); + } //Dialog furi_record_close(RECORD_DIALOGS); // Transmitter view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTransmitter); subghz_view_transmitter_free(subghz->subghz_transmitter); + if(!alloc_for_tx_only) { + // Variable Item List + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); + variable_item_list_free(subghz->variable_item_list); - // Variable Item List - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); - variable_item_list_free(subghz->variable_item_list); - - // Frequency Analyzer - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer); - subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer); - + // Frequency Analyzer + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdFrequencyAnalyzer); + subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer); + } // Read RAW view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReadRAW); subghz_read_raw_free(subghz->subghz_read_raw); - - // Submenu - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdMenu); - submenu_free(subghz->submenu); - + if(!alloc_for_tx_only) { + // Submenu + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdMenu); + submenu_free(subghz->submenu); + } // Popup view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdPopup); popup_free(subghz->popup); @@ -306,14 +343,21 @@ void subghz_free(SubGhz* subghz) { //setting subghz_setting_free(subghz->setting); - subghz_last_settings_free(subghz->last_settings); - + if(!alloc_for_tx_only) { + subghz_last_settings_free(subghz->last_settings); + } //Worker & Protocol & History + subghz_receiver_free(subghz->txrx->receiver); + subghz_environment_free(subghz->txrx->environment); + subghz_worker_free(subghz->txrx->worker); + flipper_format_free(subghz->txrx->fff_data); - subghz_history_free(subghz->txrx->history); + if(!alloc_for_tx_only) { + subghz_history_free(subghz->txrx->history); + } string_clear(subghz->txrx->preset->name); free(subghz->txrx->preset); free(subghz->txrx->secure_data); @@ -335,7 +379,20 @@ void subghz_free(SubGhz* subghz) { } int32_t subghz_app(void* p) { - SubGhz* subghz = subghz_alloc(); + bool alloc_for_tx; + if(p && strlen(p)) { + alloc_for_tx = true; + } else { + alloc_for_tx = false; + } + + SubGhz* subghz = subghz_alloc(alloc_for_tx); + + if(alloc_for_tx) { + subghz->raw_send_only = true; + } else { + subghz->raw_send_only = false; + } //Load database bool load_database = subghz_environment_load_keystore( @@ -394,7 +451,7 @@ int32_t subghz_app(void* p) { furi_hal_power_suppress_charge_exit(); - subghz_free(subghz); + subghz_free(subghz, alloc_for_tx); return 0; } diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 0af8c0a15..6784b3a0e 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -1,14 +1,28 @@ #include "subghz_history.h" +#include "subghz_history_private.h" #include -#include -#include +#include #define SUBGHZ_HISTORY_MAX 65 + +/** + * @brief Settings for temporary files + * + */ +#define SUBGHZ_HISTORY_TMP_DIR EXT_PATH("subghz/tmp_history") +#define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp" +#define SUBGHZ_HISTORY_TMP_SIGNAL_MAX_LEVEL_DURATION 700 +#define SUBGHZ_HISTORY_TMP_SIGNAL_MIN_LEVEL_DURATION 100 +#define SUBGHZ_HISTORY_TMP_REMOVE_FILES false +#define SUBGHZ_HISTORY_TMP_RAW_KEY "RAW_Data" + #define TAG "SubGhzHistory" typedef struct { string_t item_str; FlipperFormat* flipper_string; + string_t protocol_name; + bool is_file; uint8_t type; SubGhzPresetDefinition* preset; } SubGhzHistoryItem; @@ -26,30 +40,143 @@ struct SubGhzHistory { uint16_t last_index_write; uint8_t code_last_hash_data; string_t tmp_string; + bool write_tmp_files; + Storage* storage; SubGhzHistoryStruct* history; }; +#ifdef FURI_DEBUG +#define LOG_DELAY 0 +#endif + +void subghz_history_generate_temp_filename(string_t filename, uint32_t index) { + FuriHalRtcDateTime datetime = {0}; + furi_hal_rtc_get_datetime(&datetime); + string_init_printf(filename, "%03d%s", index, SUBGHZ_HISTORY_TMP_EXTENSION); +} + +bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) { + FileInfo file_info; + storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info); + + if(storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info) == FSE_OK) { + if(file_info.flags & FSF_DIRECTORY) { + return true; + } + } + + return false; +} + +bool subghz_history_check_sdcard(SubGhzHistory* instance) { +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "check_sdcard"); + uint32_t start_time = furi_get_tick(); +#endif + + bool result = false; + // Stage 0 - check SD Card + FS_Error status = storage_sd_status(instance->storage); + if(status == FSE_OK) { + result = subghz_history_is_tmp_dir_exists(instance); + if(!subghz_history_is_tmp_dir_exists(instance)) { + result = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR); + } + } else { + FURI_LOG_W(TAG, "SD storage not installed! Status: %d", status); + } +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Running time (check_sdcard): %d ms", furi_get_tick() - start_time); +#endif + + return result; +} + +void subghz_history_clear_tmp_dir(SubGhzHistory* instance) { + furi_assert(instance); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "clear_tmp_dir"); +#endif + + if(!instance->write_tmp_files) { + // Nothing to do here! + return; + } + uint32_t start_time = furi_get_tick(); +#ifdef SUBGHZ_HISTORY_TMP_REMOVE_FILES + // Stage 0 - Dir exists? + bool res = subghz_history_is_tmp_dir_exists(instance); + if(res) { + // Stage 1 - delete all content if exists + FileInfo fileinfo; + storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &fileinfo); + + res = fileinfo.flags & FSF_DIRECTORY ? + storage_simply_remove_recursive(instance->storage, SUBGHZ_HISTORY_TMP_DIR) : + (storage_common_remove(instance->storage, SUBGHZ_HISTORY_TMP_DIR) == FSE_OK); + } + + // Stage 2 - create dir if necessary + res = !storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR); + if(!res) { + FURI_LOG_E(TAG, "Cannot process temp dir!"); + } +#endif + uint32_t stop_time = furi_get_tick() - start_time; + FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time); +} + SubGhzHistory* subghz_history_alloc(void) { SubGhzHistory* instance = malloc(sizeof(SubGhzHistory)); string_init(instance->tmp_string); instance->history = malloc(sizeof(SubGhzHistoryStruct)); SubGhzHistoryItemArray_init(instance->history->data); + instance->storage = furi_record_open(RECORD_STORAGE); + instance->write_tmp_files = subghz_history_check_sdcard(instance); + + if(!instance->write_tmp_files) { + FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!"); + } + return instance; } +void subghz_history_item_free(void* current_item) { + furi_assert(current_item); + SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item; + string_clear(item->item_str); + string_clear(item->preset->name); + string_clear(item->protocol_name); + + free(item->preset); + item->type = 0; + item->is_file = false; + + if(item->flipper_string != NULL) { + flipper_format_free(item->flipper_string); + } +} + +void subghz_history_clean_item_array(SubGhzHistory* instance) { + for + M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { + subghz_history_item_free(item); + } +} + void subghz_history_free(SubGhzHistory* instance) { furi_assert(instance); string_clear(instance->tmp_string); - for - M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } + + subghz_history_clean_item_array(instance); SubGhzHistoryItemArray_clear(instance->history->data); free(instance->history); + + // Delete all temporary file, on exit it's ok + subghz_history_clear_tmp_dir(instance); + + furi_record_close(RECORD_STORAGE); + free(instance); } @@ -74,14 +201,9 @@ const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) { void subghz_history_reset(SubGhzHistory* instance) { furi_assert(instance); string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } + + subghz_history_clean_item_array(instance); + SubGhzHistoryItemArray_reset(instance->history->data); instance->last_index_write = 0; instance->code_last_hash_data = 0; @@ -101,12 +223,8 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx) const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - string_reset(instance->tmp_string); - } - return string_get_cstr(instance->tmp_string); + + return string_get_cstr(item->protocol_name); } FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) { @@ -115,17 +233,67 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx if(item->flipper_string) { return item->flipper_string; } else { - return NULL; + bool result_ok = false; + if(instance->write_tmp_files && item->is_file) { + // We have files! + string_t filename; + string_t dir_path; + string_init(filename); + string_init(dir_path); + subghz_history_generate_temp_filename(filename, idx); + string_init_printf( + dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename)); + + if(storage_file_exists(instance->storage, string_get_cstr(dir_path))) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Exist: %s", dir_path); + furi_delay_ms(LOG_DELAY); +#endif + // Set to current anyway it has NULL value + item->flipper_string = flipper_format_string_alloc(); + Stream* dst_stream = flipper_format_get_raw_stream(item->flipper_string); + stream_clean(dst_stream); + + size_t size = stream_load_from_file( + dst_stream, instance->storage, string_get_cstr(dir_path)); + if(size > 0) { +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Save ok!"); + furi_delay_ms(LOG_DELAY); +#endif + // We changed contents of file, so we no needed to load + // content from disk for the next time + item->is_file = false; + result_ok = true; + } else { + FURI_LOG_E(TAG, "Stream copy failed!"); + flipper_format_free(item->flipper_string); + } + } else { + FURI_LOG_E(TAG, "Can't convert filename to file"); + } + + string_clear(filename); + string_clear(dir_path); + } else { +#ifdef FURI_DEBUG + FURI_LOG_W(TAG, "Write TMP files failed!"); + furi_delay_ms(LOG_DELAY); +#endif + } + return result_ok ? item->flipper_string : NULL; } } + bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { furi_assert(instance); if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { if(output != NULL) string_printf(output, "Memory is FULL"); return true; } - if(output != NULL) + if(output != NULL) { string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); + } return false; } @@ -141,7 +309,9 @@ bool subghz_history_add_to_history( furi_assert(instance); furi_assert(context); - if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) { + return false; + } SubGhzProtocolDecoderBase* decoder_base = context; if((instance->code_last_hash_data == @@ -153,7 +323,6 @@ bool subghz_history_add_to_history( instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); instance->last_update_timestamp = furi_get_tick(); - string_t text; string_init(text); SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data); @@ -166,6 +335,11 @@ bool subghz_history_add_to_history( item->preset->data_size = preset->data_size; string_init(item->item_str); + string_init(item->protocol_name); + + bool tmp_file_for_raw = false; + + // At this point file mapped to memory otherwise file cannot decode item->flipper_string = flipper_format_string_alloc(); subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); @@ -177,6 +351,8 @@ bool subghz_history_add_to_history( if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { FURI_LOG_E(TAG, "Missing Protocol"); break; + } else { + string_init_printf(item->protocol_name, "%s", string_get_cstr(instance->tmp_string)); } if(!strcmp(string_get_cstr(instance->tmp_string), "RAW")) { string_printf( @@ -188,7 +364,7 @@ bool subghz_history_add_to_history( if(!flipper_format_rewind(item->flipper_string)) { FURI_LOG_E(TAG, "Rewind error"); } - + tmp_file_for_raw = true; break; } else if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) { string_set_str(instance->tmp_string, "KL "); @@ -234,7 +410,72 @@ bool subghz_history_add_to_history( } } while(false); + // If we can write to files + if(instance->write_tmp_files && tmp_file_for_raw) { + string_t filename; + string_t dir_path; + string_init(filename); + string_init(dir_path); + + subghz_history_generate_temp_filename(filename, instance->last_index_write); + string_cat_printf(dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename)); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Save temp file: %s", string_get_cstr(dir_path)); +#endif + if(!subghz_history_tmp_write_file_split(instance, item, dir_path)) { + // Plan B! + subghz_history_tmp_write_file_full(instance, item, dir_path); + } + string_clear(filename); + string_clear(dir_path); + + } else { +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Old fashion way"); +#endif + } + string_clear(text); + instance->last_index_write++; return true; } + +bool subghz_history_tmp_write_file_split( + SubGhzHistory* instance, + void* current_item, + string_t dir_path) { + UNUSED(instance); + UNUSED(current_item); + UNUSED(dir_path); + /*furi_assert(instance); + furi_assert(current_item); + furi_assert(dir_path);*/ + //SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item; + + return false; +} + +void subghz_history_tmp_write_file_full( + SubGhzHistory* instance, + void* current_item, + string_t dir_path) { + SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item; +#ifdef FURI_DEBUG + FURI_LOG_W(TAG, "Save temp file full: %s", string_get_cstr(dir_path)); +#endif + Stream* dst = flipper_format_get_raw_stream(item->flipper_string); + stream_rewind(dst); + if(stream_save_to_file(dst, instance->storage, string_get_cstr(dir_path), FSOM_CREATE_ALWAYS) > + 0) { + flipper_format_free(item->flipper_string); + item->flipper_string = NULL; +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "Save done!"); +#endif + // This item contains fake data to load from SD + item->is_file = true; + } else { + FURI_LOG_E(TAG, "Stream copy failed!"); + } +} \ No newline at end of file diff --git a/applications/main/subghz/subghz_history_private.h b/applications/main/subghz/subghz_history_private.h new file mode 100644 index 000000000..0ff802835 --- /dev/null +++ b/applications/main/subghz/subghz_history_private.h @@ -0,0 +1,79 @@ +#pragma once + +#include "subghz_history.h" + +/** + * @brief Generate filename like 000.tmp + * + * @param filename - input parameter + * @param index - index of file, timestamp doesn't accepted! + */ +void subghz_history_generate_temp_filename(string_t filename, uint32_t index); + +/** + * @brief Check if directory for temporary files is exists + * + * @param instance SubGhzHistory* + * @return true + * @return false + */ +bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance); + +/** + * @brief Check SD card and create temporary dir if not exists, + * Result write_tmp_files without this unstable work is GUARANTEED + * + * @param instance - SubGhzHistory* + * @return - true all ok + * @return - false we have a problems + */ +bool subghz_history_check_sdcard(SubGhzHistory* instance); + +/** + * @brief Recursive delete dir and files and create new temp dir + * + * @param instance - SubGhzHistory* + * @return true - if all ok + * @return false - if something failed + */ +void subghz_history_clear_tmp_dir(SubGhzHistory* instance); + +/** + * @brief Free item and free all resources + * + * @param current_item - SubGhzHistoryItem* + */ +void subghz_history_item_free(void* current_item); + +/** + * @brief free all items in array + * + * @param instance + */ +void subghz_history_clean_item_array(SubGhzHistory* instance); + +/** + * @brief Write temp file fully, without spliting + * + * @param instance - SubGhzHistory* + * @param current_item - SubGhzHistoryItem* + * @param dir_path - full path to file + */ +void subghz_history_tmp_write_file_full( + SubGhzHistory* instance, + void* current_item, + string_t dir_path); + +/** + * @brief Write temp splited to lines + * + * @param instance - SubGhzHistory* + * @param current_item - SubGhzHistoryItem* + * @param dir_path - full path to file + * @return true - file saved + * @return false - error occured + */ +bool subghz_history_tmp_write_file_split( + SubGhzHistory* instance, + void* current_item, + string_t dir_path); \ No newline at end of file diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 8872d31f6..b177c1ba7 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -7,10 +7,11 @@ #include "views/subghz_frequency_analyzer.h" #include "views/subghz_read_raw.h" +#if FURI_DEBUG #include "views/subghz_test_static.h" #include "views/subghz_test_carrier.h" #include "views/subghz_test_packet.h" - +#endif // #include // #include #include @@ -96,9 +97,12 @@ struct SubGhz { SubGhzFrequencyAnalyzer* subghz_frequency_analyzer; SubGhzReadRAW* subghz_read_raw; + bool raw_send_only; +#if FURI_DEBUG SubGhzTestStatic* subghz_test_static; SubGhzTestCarrier* subghz_test_carrier; SubGhzTestPacket* subghz_test_packet; +#endif string_t error_str; SubGhzSetting* setting; SubGhzLastSettings* last_settings; diff --git a/applications/main/subghz/subghz_last_settings.c b/applications/main/subghz/subghz_last_settings.c index b24273cf3..6382253b8 100644 --- a/applications/main/subghz/subghz_last_settings.c +++ b/applications/main/subghz/subghz_last_settings.c @@ -1,5 +1,8 @@ #include "subghz_last_settings.h" -#include +#include "subghz_i.h" +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING +#include +#endif #define TAG "SubGhzLastSettings" @@ -11,6 +14,14 @@ #define SUBGHZ_LAST_SETTING_DEFAULT_PRESET 1 #define SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY 433920000 +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING +#define SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW 0 +#define SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW "DetectRaw" +#endif + +#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency" +#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset" + SubGhzLastSettings* subghz_last_settings_alloc(void) { SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings)); return instance; @@ -23,7 +34,7 @@ void subghz_last_settings_free(SubGhzLastSettings* instance) { void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count) { furi_assert(instance); -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_I(TAG, "subghz_last_settings_load"); #endif @@ -32,11 +43,20 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count uint32_t temp_frequency = 0; int32_t temp_preset = 0; +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + uint32_t temp_read_raw = 0; +#endif if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH && flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) { - flipper_format_read_int32(fff_data_file, "Preset", (int32_t*)&temp_preset, 1); - flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&temp_frequency, 1); + flipper_format_read_int32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_PRESET, (int32_t*)&temp_preset, 1); + flipper_format_read_uint32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, (uint32_t*)&temp_frequency, 1); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + flipper_format_read_uint32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, (uint32_t*)&temp_read_raw, 1); +#endif } else { FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH); } @@ -45,8 +65,14 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count FURI_LOG_W(TAG, "Last used frequency not found or can't be used!"); instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY; instance->preset = SUBGHZ_LAST_SETTING_DEFAULT_PRESET; +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + instance->detect_raw = SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW; +#endif } else { instance->frequency = temp_frequency; +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + instance->detect_raw = temp_read_raw; +#endif if(temp_preset > (int32_t)preset_count - 1 || temp_preset < 0) { FURI_LOG_W(TAG, "Last used preset no found"); @@ -63,8 +89,8 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count bool subghz_last_settings_save(SubGhzLastSettings* instance) { furi_assert(instance); -#if FURI_DEBUG - FURI_LOG_I(TAG, "subghz_last_settings_save"); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "last_settings_save"); #endif bool saved = false; @@ -84,12 +110,20 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION)) break; - if(!flipper_format_insert_or_update_int32(file, "Preset", &instance->preset, 1)) { + if(!flipper_format_insert_or_update_int32( + file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset, 1)) { break; } - if(!flipper_format_insert_or_update_uint32(file, "Frequency", &instance->frequency, 1)) { + if(!flipper_format_insert_or_update_uint32( + file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) { break; } +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + if(!flipper_format_insert_or_update_uint32( + file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, &instance->detect_raw, 1)) { + break; + } +#endif saved = true; } while(0); @@ -102,4 +136,18 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { furi_record_close(RECORD_STORAGE); return saved; -} \ No newline at end of file +} + +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING +void subghz_last_settings_set_detect_raw_values(void* context) { + furi_assert(context); + SubGhz* instance = (SubGhz*)context; + bool is_detect_raw = instance->last_settings->detect_raw > 0; + subghz_receiver_set_filter( + instance->txrx->receiver, is_detect_raw ? DETECT_RAW_TRUE : DETECT_RAW_FALSE); + subghz_protocol_decoder_raw_set_auto_mode( + subghz_receiver_search_decoder_base_by_name( + instance->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), + is_detect_raw); +} +#endif \ No newline at end of file diff --git a/applications/main/subghz/subghz_last_settings.h b/applications/main/subghz/subghz_last_settings.h index 8067bb66a..116eacadd 100644 --- a/applications/main/subghz/subghz_last_settings.h +++ b/applications/main/subghz/subghz_last_settings.h @@ -1,12 +1,23 @@ #pragma once +// Enable saving detect raw setting state +// #define SUBGHZ_SAVE_DETECT_RAW_SETTING 1 + #include #include #include #include +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING +#include +#define DETECT_RAW_FALSE SubGhzProtocolFlag_Decodable +#define DETECT_RAW_TRUE SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW +#endif typedef struct { uint32_t frequency; +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING + uint32_t detect_raw; +#endif int32_t preset; } SubGhzLastSettings; @@ -16,4 +27,7 @@ void subghz_last_settings_free(SubGhzLastSettings* instance); void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count); -bool subghz_last_settings_save(SubGhzLastSettings* instance); \ No newline at end of file +bool subghz_last_settings_save(SubGhzLastSettings* instance); +#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING +void subghz_last_settings_set_detect_raw_values(void* context); +#endif \ No newline at end of file diff --git a/applications/main/subghz/subghz_setting.c b/applications/main/subghz/subghz_setting.c index 2e94011cf..8f116322f 100644 --- a/applications/main/subghz/subghz_setting.c +++ b/applications/main/subghz/subghz_setting.c @@ -181,7 +181,7 @@ void subghz_setting_load_default(SubGhzSetting* instance) { instance, subghz_frequency_list, subghz_hopper_frequency_list); } -void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { +void subghz_setting_load(SubGhzSetting* instance, const char* file_path, bool not_skip_frequencies) { furi_assert(instance); Storage* storage = furi_record_open(RECORD_STORAGE); @@ -214,53 +214,56 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { } // Standard frequencies (optional) - temp_bool = true; - flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1); - if(!temp_bool) { - FURI_LOG_I(TAG, "Removing standard frequencies"); - FrequencyList_reset(instance->frequencies); - FrequencyList_reset(instance->hopper_frequencies); - } else { - FURI_LOG_I(TAG, "Keeping standard frequencies"); - } - - // Load frequencies - if(!flipper_format_rewind(fff_data_file)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - while(flipper_format_read_uint32( - fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { - if(furi_hal_subghz_is_frequency_valid(temp_data32)) { - FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); - FrequencyList_push_back(instance->frequencies, temp_data32); + if(not_skip_frequencies) { + temp_bool = true; + flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1); + if(!temp_bool) { + FURI_LOG_I(TAG, "Removing standard frequencies"); + FrequencyList_reset(instance->frequencies); + FrequencyList_reset(instance->hopper_frequencies); } else { - FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32); + FURI_LOG_I(TAG, "Keeping standard frequencies"); } - } - // Load hopper frequencies - if(!flipper_format_rewind(fff_data_file)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - while(flipper_format_read_uint32( - fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) { - if(furi_hal_subghz_is_frequency_valid(temp_data32)) { - FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32); - FrequencyList_push_back(instance->hopper_frequencies, temp_data32); - } else { - FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32); + // Load frequencies + if(!flipper_format_rewind(fff_data_file)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + while(flipper_format_read_uint32( + fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { + if(furi_hal_subghz_is_frequency_valid(temp_data32)) { + FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); + FrequencyList_push_back(instance->frequencies, temp_data32); + } else { + FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32); + } } - } - // Default frequency (optional) - if(!flipper_format_rewind(fff_data_file)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(flipper_format_read_uint32(fff_data_file, "Default_frequency", &temp_data32, 1)) { - subghz_setting_set_default_frequency(instance, temp_data32); + // Load hopper frequencies + if(!flipper_format_rewind(fff_data_file)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + while(flipper_format_read_uint32( + fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) { + if(furi_hal_subghz_is_frequency_valid(temp_data32)) { + FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32); + FrequencyList_push_back(instance->hopper_frequencies, temp_data32); + } else { + FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32); + } + } + + // Default frequency (optional) + if(!flipper_format_rewind(fff_data_file)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(flipper_format_read_uint32( + fff_data_file, "Default_frequency", &temp_data32, 1)) { + subghz_setting_set_default_frequency(instance, temp_data32); + } } // custom preset (optional) diff --git a/applications/main/subghz/subghz_setting.h b/applications/main/subghz/subghz_setting.h index d6fde1bd6..3b3b1131a 100644 --- a/applications/main/subghz/subghz_setting.h +++ b/applications/main/subghz/subghz_setting.h @@ -14,7 +14,7 @@ SubGhzSetting* subghz_setting_alloc(void); void subghz_setting_free(SubGhzSetting* instance); -void subghz_setting_load(SubGhzSetting* instance, const char* file_path); +void subghz_setting_load(SubGhzSetting* instance, const char* file_path, bool not_skip_frequencies); size_t subghz_setting_get_frequency_count(SubGhzSetting* instance); diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index 98b3fe01d..461b10974 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -194,7 +194,7 @@ uint32_t subghz_frequency_find_correct(uint32_t input) { uint32_t prev_freq = 0; uint32_t current = 0; uint32_t result = 0; -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_D(TAG, "input: %d", input); #endif for(size_t i = 0; i < sizeof(subghz_frequency_list); i++) { @@ -274,7 +274,7 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { frequency_candidate = subghz_frequency_find_correct(frequency_candidate); } if(frequency_candidate > 0 && frequency_candidate != model->frequency_to_save) { -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_D( TAG, "frequency_to_save: %d, candidate: %d", @@ -289,7 +289,7 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { return true; }); -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_I( TAG, "updated: %d, long: %d, type: %d", @@ -304,7 +304,7 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { // First device receive short, then when user release button we get long if(event->type == InputTypeLong) { -#if FURI_DEBUG +#ifdef FURI_DEBUG FURI_LOG_I(TAG, "Longpress!"); #endif // Stop blinking diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index ccffaf42f..2d24d9411 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -27,6 +27,7 @@ typedef struct { uint8_t ind_write; uint8_t ind_sin; SubGhzReadRAWStatus status; + bool raw_send_only; } SubGhzReadRAWModel; void subghz_read_raw_set_callback( @@ -232,9 +233,11 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { elements_button_right(canvas, "Save"); break; case SubGhzReadRAWStatusLoadKeyIDLE: - elements_button_left(canvas, "New"); + if(!model->raw_send_only) { + elements_button_left(canvas, "New"); + elements_button_right(canvas, "More"); + } elements_button_center(canvas, "Send"); - elements_button_right(canvas, "More"); elements_text_box( canvas, 4, @@ -362,31 +365,35 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { with_view_model( instance->view, (SubGhzReadRAWModel * model) { - if(model->status == SubGhzReadRAWStatusStart) { - //Config - instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context); - } else if( - (model->status == SubGhzReadRAWStatusIDLE) || - (model->status == SubGhzReadRAWStatusLoadKeyIDLE)) { - //Erase - model->status = SubGhzReadRAWStatusStart; - model->rssi_history_end = false; - model->ind_write = 0; - string_set_str(model->sample_write, "0 spl."); - string_reset(model->file_name); - instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context); + if(!model->raw_send_only) { + if(model->status == SubGhzReadRAWStatusStart) { + //Config + instance->callback(SubGhzCustomEventViewReadRAWConfig, instance->context); + } else if( + (model->status == SubGhzReadRAWStatusIDLE) || + (model->status == SubGhzReadRAWStatusLoadKeyIDLE)) { + //Erase + model->status = SubGhzReadRAWStatusStart; + model->rssi_history_end = false; + model->ind_write = 0; + string_set_str(model->sample_write, "0 spl."); + string_reset(model->file_name); + instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context); + } } return true; }); } else if(event->key == InputKeyRight && event->type == InputTypeShort) { with_view_model( instance->view, (SubGhzReadRAWModel * model) { - if(model->status == SubGhzReadRAWStatusIDLE) { - //Save - instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context); - } else if(model->status == SubGhzReadRAWStatusLoadKeyIDLE) { - //More - instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context); + if(!model->raw_send_only) { + if(model->status == SubGhzReadRAWStatusIDLE) { + //Save + instance->callback(SubGhzCustomEventViewReadRAWSave, instance->context); + } else if(model->status == SubGhzReadRAWStatusLoadKeyIDLE) { + //More + instance->callback(SubGhzCustomEventViewReadRAWMore, instance->context); + } } return true; }); @@ -487,7 +494,7 @@ void subghz_read_raw_exit(void* context) { }); } -SubGhzReadRAW* subghz_read_raw_alloc() { +SubGhzReadRAW* subghz_read_raw_alloc(bool raw_send_only) { SubGhzReadRAW* instance = malloc(sizeof(SubGhzReadRAW)); // View allocation and configuration @@ -505,6 +512,7 @@ SubGhzReadRAW* subghz_read_raw_alloc() { string_init(model->preset_str); string_init(model->sample_write); string_init(model->file_name); + model->raw_send_only = raw_send_only; model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t)); return true; }); diff --git a/applications/main/subghz/views/subghz_read_raw.h b/applications/main/subghz/views/subghz_read_raw.h index 1d4bb7dc0..a4e16ca98 100644 --- a/applications/main/subghz/views/subghz_read_raw.h +++ b/applications/main/subghz/views/subghz_read_raw.h @@ -25,7 +25,7 @@ void subghz_read_raw_set_callback( SubGhzReadRAWCallback callback, void* context); -SubGhzReadRAW* subghz_read_raw_alloc(); +SubGhzReadRAW* subghz_read_raw_alloc(bool raw_send_only); void subghz_read_raw_free(SubGhzReadRAW* subghz_static); diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index df2d318ae..13d47988c 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -827,7 +827,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { void unirfremix_subghz_alloc(UniRFRemix* app) { // load subghz presets app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"), false); // load mfcodes app->environment = subghz_environment_alloc(); diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index a316a0779..b533f3853 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -14,6 +14,7 @@ #define ASSETS_DIR "assets" #define BADUSB_LAYOUTS_DIR "layouts" +#define SUBGHZ_TEMP_DIR "tmp_history" #define BROWSER_ROOT STORAGE_ANY_PATH_PREFIX #define FILE_NAME_LEN_MAX 256 #define LONG_LOAD_THRESHOLD 100 @@ -80,7 +81,8 @@ static bool browser_filter_by_name(BrowserWorker* browser, string_t name, bool i // Skip assets folders (if enabled) if(browser->skip_assets) { return ((string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)) && - ((string_cmp_str(name, BADUSB_LAYOUTS_DIR) == 0) ? (false) : (true)); + ((string_cmp_str(name, BADUSB_LAYOUTS_DIR) == 0) ? (false) : (true)) && + ((string_cmp_str(name, SUBGHZ_TEMP_DIR) == 0) ? (false) : (true)); } else { return true; }