diff --git a/scenes/protopirate_scene_emulate.c b/scenes/protopirate_scene_emulate.c index 4114266..bc3f351 100644 --- a/scenes/protopirate_scene_emulate.c +++ b/scenes/protopirate_scene_emulate.c @@ -19,6 +19,7 @@ typedef struct { SubGhzTransmitter* transmitter; bool is_transmitting; bool flag_stop_called; + Storage* storage; } EmulateContext; static EmulateContext* emulate_context = NULL; @@ -77,6 +78,11 @@ static void emulate_context_free(void) { emulate_context->protocol_name = NULL; } + if(emulate_context->storage) { + furi_record_close(RECORD_STORAGE); + emulate_context->storage = NULL; + } + free(emulate_context); emulate_context = NULL; } @@ -372,33 +378,46 @@ void protopirate_scene_emulate_on_enter(void* context) { // Load the file if(app->loaded_file_path) { // Open storage once and keep track of it - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - if(!flipper_format_file_open_existing(ff, furi_string_get_cstr(app->loaded_file_path))) { - FURI_LOG_E( - TAG, "Failed to open file: %s", furi_string_get_cstr(app->loaded_file_path)); - flipper_format_free(ff); - furi_record_close(RECORD_STORAGE); + emulate_context->storage = furi_record_open(RECORD_STORAGE); + if(!emulate_context->storage) { + FURI_LOG_E(TAG, "Failed to open storage"); emulate_context_free(); notification_message(app->notifications, &sequence_error); scene_manager_previous_scene(app->scene_manager); return; } - emulate_context->flipper_format = ff; + emulate_context->flipper_format = flipper_format_file_alloc(emulate_context->storage); + if(!emulate_context->flipper_format) { + FURI_LOG_E(TAG, "Failed to allocate FlipperFormat"); + emulate_context_free(); + notification_message(app->notifications, &sequence_error); + scene_manager_previous_scene(app->scene_manager); + return; + } + + if(!flipper_format_file_open_existing( + emulate_context->flipper_format, furi_string_get_cstr(app->loaded_file_path))) { + FURI_LOG_E( + TAG, "Failed to open file: %s", furi_string_get_cstr(app->loaded_file_path)); + emulate_context_free(); + notification_message(app->notifications, &sequence_error); + scene_manager_previous_scene(app->scene_manager); + return; + } // Read frequency and preset from the saved file uint32_t frequency = 433920000; FuriString* preset_str = furi_string_alloc(); - flipper_format_rewind(ff); - if(!flipper_format_read_uint32(ff, "Frequency", &frequency, 1)) { + flipper_format_rewind(emulate_context->flipper_format); + if(!flipper_format_read_uint32( + emulate_context->flipper_format, "Frequency", &frequency, 1)) { FURI_LOG_W(TAG, "Failed to read frequency, using default 433.92MHz"); } - flipper_format_rewind(ff); - if(!flipper_format_read_string(ff, "Preset", preset_str)) { + flipper_format_rewind(emulate_context->flipper_format); + if(!flipper_format_read_string(emulate_context->flipper_format, "Preset", preset_str)) { FURI_LOG_W(TAG, "Failed to read preset, using AM650"); furi_string_set(preset_str, "AM650"); } @@ -415,29 +434,32 @@ void protopirate_scene_emulate_on_enter(void* context) { furi_string_free(preset_str); // Read protocol name - flipper_format_rewind(ff); - if(!flipper_format_read_string(ff, "Protocol", emulate_context->protocol_name)) { + flipper_format_rewind(emulate_context->flipper_format); + if(!flipper_format_read_string( + emulate_context->flipper_format, "Protocol", emulate_context->protocol_name)) { FURI_LOG_E(TAG, "Failed to read protocol name"); furi_string_set(emulate_context->protocol_name, "Unknown"); } // Read serial - flipper_format_rewind(ff); - if(!flipper_format_read_uint32(ff, "Serial", &emulate_context->serial, 1)) { + flipper_format_rewind(emulate_context->flipper_format); + if(!flipper_format_read_uint32( + emulate_context->flipper_format, "Serial", &emulate_context->serial, 1)) { FURI_LOG_W(TAG, "Failed to read serial"); emulate_context->serial = 0; } // Read original button - flipper_format_rewind(ff); + flipper_format_rewind(emulate_context->flipper_format); uint32_t btn_temp = 0; - if(flipper_format_read_uint32(ff, "Btn", &btn_temp, 1)) { + if(flipper_format_read_uint32(emulate_context->flipper_format, "Btn", &btn_temp, 1)) { emulate_context->original_button = (uint8_t)btn_temp; } // Read counter - flipper_format_rewind(ff); - if(flipper_format_read_uint32(ff, "Cnt", &emulate_context->original_counter, 1)) { + flipper_format_rewind(emulate_context->flipper_format); + if(flipper_format_read_uint32( + emulate_context->flipper_format, "Cnt", &emulate_context->original_counter, 1)) { emulate_context->current_counter = emulate_context->original_counter; } @@ -475,9 +497,9 @@ void protopirate_scene_emulate_on_enter(void* context) { FURI_LOG_I(TAG, "Transmitter allocated successfully"); // Deserialize for transmission - flipper_format_rewind(ff); - SubGhzProtocolStatus status = - subghz_transmitter_deserialize(emulate_context->transmitter, ff); + flipper_format_rewind(emulate_context->flipper_format); + SubGhzProtocolStatus status = subghz_transmitter_deserialize( + emulate_context->transmitter, emulate_context->flipper_format); if(status != SubGhzProtocolStatusOk) { FURI_LOG_E(TAG, "Failed to deserialize transmitter, status: %d", status); @@ -723,9 +745,6 @@ void protopirate_scene_emulate_on_exit(void* context) { // Free emulate context and all its resources emulate_context_free(); - // Close storage record that was opened in on_enter - furi_record_close(RECORD_STORAGE); - // Delete temp file if we were using one protopirate_storage_delete_temp(); diff --git a/scenes/protopirate_scene_receiver.c b/scenes/protopirate_scene_receiver.c index be989ca..75b0cfb 100644 --- a/scenes/protopirate_scene_receiver.c +++ b/scenes/protopirate_scene_receiver.c @@ -10,10 +10,27 @@ void protopirate_scene_receiver_view_callback(ProtoPirateCustomEvent event, void* context); static void protopirate_scene_receiver_update_statusbar(void* context) { + furi_check(context); ProtoPirateApp* app = context; + FuriString* frequency_str = furi_string_alloc(); + if(!frequency_str) { + FURI_LOG_E(TAG, "frequency_str allocation failed"); + return; + } FuriString* modulation_str = furi_string_alloc(); + if(!modulation_str) { + FURI_LOG_E(TAG, "modulation_str allocation failed"); + furi_string_free(frequency_str); + return; + } FuriString* history_stat_str = furi_string_alloc(); + if(!history_stat_str) { + FURI_LOG_E(TAG, "history_stat_str allocation failed"); + furi_string_free(frequency_str); + furi_string_free(modulation_str); + return; + } protopirate_get_frequency_modulation(app, frequency_str, modulation_str); @@ -30,12 +47,6 @@ static void protopirate_scene_receiver_update_statusbar(void* context) { "%u/%u", protopirate_history_get_item(app->txrx->history), PROTOPIRATE_DISPLAY_HISTORY_MAX); - } else { - furi_string_printf( - history_stat_str, - "%u/%u", - protopirate_history_get_item(app->txrx->history), - PROTOPIRATE_DISPLAY_HISTORY_MAX); } // Pass actual external radio status @@ -56,12 +67,18 @@ static void protopirate_scene_receiver_callback( SubGhzProtocolDecoderBase* decoder_base, void* context) { UNUSED(receiver); + furi_check(decoder_base); furi_check(context); ProtoPirateApp* app = context; FURI_LOG_I(TAG, "=== SIGNAL DECODED ==="); FuriString* str_buff = furi_string_alloc(); + if(!str_buff) { + FURI_LOG_E(TAG, "str_buff allocation failed"); + return; + } + subghz_protocol_decoder_base_get_string(decoder_base, str_buff); FURI_LOG_I(TAG, "%s", furi_string_get_cstr(str_buff)); @@ -75,6 +92,11 @@ static void protopirate_scene_receiver_callback( protopirate_history_get_item(app->txrx->history)); FuriString* item_name = furi_string_alloc(); + if(!item_name) { + FURI_LOG_E(TAG, "item_name allocation failed"); + return; + } + protopirate_history_get_text_item_menu( app->txrx->history, item_name, protopirate_history_get_item(app->txrx->history) - 1); @@ -94,6 +116,12 @@ static void protopirate_scene_receiver_callback( if(ff) { FuriString* protocol = furi_string_alloc(); + if(!protocol) { + FURI_LOG_E(TAG, "protocol allocation failed"); + furi_string_free(str_buff); + return; + } + flipper_format_rewind(ff); if(!flipper_format_read_string(ff, "Protocol", protocol)) { furi_string_set_str(protocol, "Unknown"); @@ -104,6 +132,13 @@ static void protopirate_scene_receiver_callback( furi_string_replace_all(protocol, " ", "_"); FuriString* saved_path = furi_string_alloc(); + if(!protocol) { + FURI_LOG_E(TAG, "saved_path allocation failed"); + furi_string_free(protocol); + furi_string_free(str_buff); + return; + } + if(protopirate_storage_save_capture( ff, furi_string_get_cstr(protocol), saved_path)) { FURI_LOG_I(TAG, "Auto-saved: %s", furi_string_get_cstr(saved_path)); @@ -133,6 +168,7 @@ static void protopirate_scene_receiver_callback( } void protopirate_scene_receiver_on_enter(void* context) { + furi_check(context); ProtoPirateApp* app = context; FURI_LOG_I(TAG, "=== ENTERING RECEIVER SCENE ==="); @@ -141,7 +177,8 @@ void protopirate_scene_receiver_on_enter(void* context) { #ifndef REMOVE_LOGS bool is_external = app->txrx->radio_device ? radio_device_loader_is_external(app->txrx->radio_device) : false; - const char* device_name = subghz_devices_get_name(app->txrx->radio_device); + const char* device_name = + app->txrx->radio_device ? subghz_devices_get_name(app->txrx->radio_device) : NULL; FURI_LOG_I(TAG, "Radio device: %s", device_name ? device_name : "NULL"); FURI_LOG_I(TAG, "Is External: %s", is_external ? "YES" : "NO"); FURI_LOG_I(TAG, "Frequency: %lu Hz", app->txrx->preset->frequency); @@ -221,6 +258,7 @@ void protopirate_scene_receiver_on_enter(void* context) { } bool protopirate_scene_receiver_on_event(void* context, SceneManagerEvent event) { + furi_check(context); ProtoPirateApp* app = context; bool consumed = false; @@ -273,7 +311,8 @@ bool protopirate_scene_receiver_on_event(void* context, SceneManagerEvent event) } // Update RSSI from the correct radio device (only if initialized) - if(app->radio_initialized && app->txrx->txrx_state == ProtoPirateTxRxStateRx) { + if(app->radio_initialized && app->txrx->txrx_state == ProtoPirateTxRxStateRx && + app->txrx->radio_device) { float rssi = subghz_devices_get_rssi(app->txrx->radio_device); protopirate_view_receiver_set_rssi(app->protopirate_receiver, rssi); @@ -300,6 +339,7 @@ bool protopirate_scene_receiver_on_event(void* context, SceneManagerEvent event) } void protopirate_scene_receiver_on_exit(void* context) { + furi_check(context); ProtoPirateApp* app = context; FURI_LOG_I(TAG, "=== EXITING RECEIVER SCENE ==="); diff --git a/scenes/protopirate_scene_receiver_info.c b/scenes/protopirate_scene_receiver_info.c index 5732e70..7fecabe 100644 --- a/scenes/protopirate_scene_receiver_info.c +++ b/scenes/protopirate_scene_receiver_info.c @@ -29,6 +29,9 @@ void protopirate_scene_receiver_info_on_enter(void* context) { furi_check(context); ProtoPirateApp* app = context; + // Always reset per-enter to avoid stale static state + is_emu_off = false; + widget_reset(app->widget); FuriString* text; diff --git a/scenes/protopirate_scene_saved_info.c b/scenes/protopirate_scene_saved_info.c index 1dc1c61..6097737 100644 --- a/scenes/protopirate_scene_saved_info.c +++ b/scenes/protopirate_scene_saved_info.c @@ -28,12 +28,15 @@ static void protopirate_scene_saved_info_widget_callback( notification_message(app->notifications, &sequence_semi_success); view_dispatcher_send_custom_event( app->view_dispatcher, ProtoPirateCustomEventSavedInfoDelete); + break; default: + break; } } } void protopirate_scene_saved_info_on_enter(void* context) { + furi_check(context); ProtoPirateApp* app = context; Storage* storage = NULL; FlipperFormat* ff = NULL; @@ -104,7 +107,9 @@ void protopirate_scene_saved_info_on_enter(void* context) { FURI_LOG_I(TAG, "File opened, reading..."); // Read fields - uint32_t temp_data; + uint32_t temp_data = 0; + // reset is_emu_off state before loading + is_emu_off = false; flipper_format_rewind(ff); if(flipper_format_read_string(ff, "Protocol", temp_str)) { @@ -116,8 +121,6 @@ void protopirate_scene_saved_info_on_enter(void* context) { is_emu_off = true; } else if(furi_string_cmp_str(temp_str, "Kia V6") == 0) { is_emu_off = true; - } else { - is_emu_off = false; } flipper_format_rewind(ff); diff --git a/scenes/protopirate_scene_sub_decode.c b/scenes/protopirate_scene_sub_decode.c index 911adb4..bcc15f3 100644 --- a/scenes/protopirate_scene_sub_decode.c +++ b/scenes/protopirate_scene_sub_decode.c @@ -378,8 +378,10 @@ static void close_file_handles(SubDecodeContext* ctx) { flipper_format_free(ctx->ff); ctx->ff = NULL; } - furi_record_close(RECORD_STORAGE); - //ctx->storage = NULL; + if(ctx->storage) { + furi_record_close(RECORD_STORAGE); + ctx->storage = NULL; + } } // Receiver view callback for history navigation @@ -425,6 +427,8 @@ void protopirate_scene_sub_decode_on_enter(void* context) { app->txrx->history = protopirate_history_alloc(); if(!app->txrx->history) { FURI_LOG_E(TAG, "Failed to allocate history!"); + free(g_decode_ctx); + g_decode_ctx = NULL; return; } } @@ -714,7 +718,16 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even FURI_LOG_I(TAG, "StartingWorker: Reading file metadata"); Storage* storage = furi_record_open(RECORD_STORAGE); + if(!storage) { + FURI_LOG_E(TAG, "Failed to open storage"); + break; + } FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + if(!fff_data_file) { + FURI_LOG_E(TAG, "Failed to allocate FlipperFormat"); + break; + } + FuriString* temp_str = furi_string_alloc(); bool setup_ok = false; @@ -803,9 +816,11 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even setup_ok = true; } while(false); - flipper_format_free(fff_data_file); + if(fff_data_file) flipper_format_free(fff_data_file); + + if(storage) furi_record_close(RECORD_STORAGE); + furi_string_free(temp_str); - furi_record_close(RECORD_STORAGE); if(!setup_ok) { furi_string_set(ctx->result, "Failed to read file metadata"); diff --git a/scenes/protopirate_scene_timing_tuner.c b/scenes/protopirate_scene_timing_tuner.c index 432dc4a..87c6265 100644 --- a/scenes/protopirate_scene_timing_tuner.c +++ b/scenes/protopirate_scene_timing_tuner.c @@ -607,11 +607,18 @@ static void timing_tuner_pair_callback(void* context, bool level, uint32_t durat } void protopirate_scene_timing_tuner_on_enter(void* context) { + furi_check(context); ProtoPirateApp* app = context; FURI_LOG_I(TAG, "Entering Timing Tuner"); g_timing_ctx = malloc(sizeof(TimingTunerContext)); + if(!g_timing_ctx) { + FURI_LOG_E(TAG, "Failed to allocate timing tuner context"); + notification_message(app->notifications, &sequence_error); + scene_manager_previous_scene(app->scene_manager); + return; + } memset(g_timing_ctx, 0, sizeof(TimingTunerContext)); g_timing_ctx->is_receiving = false; g_timing_ctx->has_match = false; @@ -673,8 +680,9 @@ bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent ev } } else if(event.type == SceneManagerEventTypeTick) { if(g_timing_ctx && g_timing_ctx->is_receiving && !g_timing_ctx->has_match) { - g_timing_ctx->rssi = subghz_devices_get_rssi(app->txrx->radio_device); - + if(app->txrx->radio_device) { + g_timing_ctx->rssi = subghz_devices_get_rssi(app->txrx->radio_device); + } // Blink the light like the SubGHZ app notification_message(app->notifications, &sequence_blink_cyan_10); }