Просмотр исходного кода

[FL-2728] Fix Null Pointer Dereference errors in IR #1583

Co-authored-by: あく <alleteam@gmail.com>
Georgii Surkov 3 лет назад
Родитель
Сommit
1655366ef4

+ 20 - 1
applications/infrared/infrared.c

@@ -295,6 +295,13 @@ bool infrared_rename_current_remote(Infrared* infrared, const char* name) {
 }
 }
 
 
 void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
 void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
+    if(infrared->app_state.is_transmitting) {
+        FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already active");
+        return;
+    } else {
+        infrared->app_state.is_transmitting = true;
+    }
+
     if(infrared_signal_is_raw(signal)) {
     if(infrared_signal_is_raw(signal)) {
         InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
         InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
         infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
         infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
@@ -304,8 +311,11 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
     }
     }
 
 
     DOLPHIN_DEED(DolphinDeedIrSend);
     DOLPHIN_DEED(DolphinDeedIrSend);
-    infrared_worker_tx_start(infrared->worker);
     infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
     infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
+
+    infrared_worker_tx_set_get_signal_callback(
+        infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
+    infrared_worker_tx_start(infrared->worker);
 }
 }
 
 
 void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
 void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) {
@@ -324,7 +334,16 @@ void infrared_tx_start_received(Infrared* infrared) {
 }
 }
 
 
 void infrared_tx_stop(Infrared* infrared) {
 void infrared_tx_stop(Infrared* infrared) {
+    if(!infrared->app_state.is_transmitting) {
+        FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already stopped");
+        return;
+    } else {
+        infrared->app_state.is_transmitting = false;
+    }
+
     infrared_worker_tx_stop(infrared->worker);
     infrared_worker_tx_stop(infrared->worker);
+    infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
+
     infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
     infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
 }
 }
 
 

+ 2 - 0
applications/infrared/infrared_i.h

@@ -43,6 +43,7 @@
 #define INFRARED_APP_EXTENSION ".ir"
 #define INFRARED_APP_EXTENSION ".ir"
 
 
 #define INFRARED_DEFAULT_REMOTE_NAME "Remote"
 #define INFRARED_DEFAULT_REMOTE_NAME "Remote"
+#define INFRARED_LOG_TAG "InfraredApp"
 
 
 typedef enum {
 typedef enum {
     InfraredButtonIndexNone = -1,
     InfraredButtonIndexNone = -1,
@@ -63,6 +64,7 @@ typedef enum {
 typedef struct {
 typedef struct {
     bool is_learning_new_remote;
     bool is_learning_new_remote;
     bool is_debug_enabled;
     bool is_debug_enabled;
+    bool is_transmitting;
     InfraredEditTarget edit_target : 8;
     InfraredEditTarget edit_target : 8;
     InfraredEditMode edit_mode : 8;
     InfraredEditMode edit_mode : 8;
     int32_t current_button_index;
     int32_t current_button_index;

+ 8 - 35
applications/infrared/scenes/infrared_scene_learn_success.c

@@ -2,11 +2,6 @@
 
 
 #include <dolphin/dolphin.h>
 #include <dolphin/dolphin.h>
 
 
-typedef enum {
-    InfraredSceneLearnSuccessStateIdle = 0,
-    InfraredSceneLearnSuccessStateSending = 1,
-} InfraredSceneLearnSuccessState;
-
 static void
 static void
     infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
     infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
     Infrared* infrared = context;
     Infrared* infrared = context;
@@ -21,9 +16,6 @@ void infrared_scene_learn_success_on_enter(void* context) {
     DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
     DOLPHIN_DEED(DolphinDeedIrLearnSuccess);
     infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
     infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
 
 
-    infrared_worker_tx_set_get_signal_callback(
-        infrared->worker, infrared_worker_tx_get_signal_steady_callback, context);
-
     if(infrared_signal_is_raw(signal)) {
     if(infrared_signal_is_raw(signal)) {
         InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
         InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
         dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter);
         dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter);
@@ -63,57 +55,42 @@ void infrared_scene_learn_success_on_enter(void* context) {
     dialog_ex_set_context(dialog_ex, context);
     dialog_ex_set_context(dialog_ex, context);
     dialog_ex_enable_extended_events(dialog_ex);
     dialog_ex_enable_extended_events(dialog_ex);
 
 
-    scene_manager_set_scene_state(
-        infrared->scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
     view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
     view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
 }
 }
 
 
 bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
 bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
     Infrared* infrared = context;
     Infrared* infrared = context;
     SceneManager* scene_manager = infrared->scene_manager;
     SceneManager* scene_manager = infrared->scene_manager;
-    uint32_t scene_state = scene_manager_get_scene_state(scene_manager, InfraredSceneLearnSuccess);
+    const bool is_transmitter_idle = !infrared->app_state.is_transmitting;
     bool consumed = false;
     bool consumed = false;
 
 
     if(event.type == SceneManagerEventTypeTick) {
     if(event.type == SceneManagerEventTypeTick) {
-        if(scene_state == InfraredSceneLearnSuccessStateIdle) {
+        if(is_transmitter_idle) {
             infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
             infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
         }
         }
         consumed = true;
         consumed = true;
     } else if(event.type == SceneManagerEventTypeBack) {
     } else if(event.type == SceneManagerEventTypeBack) {
-        if(scene_state == InfraredSceneLearnSuccessStateIdle) {
+        if(is_transmitter_idle) {
             scene_manager_next_scene(scene_manager, InfraredSceneAskBack);
             scene_manager_next_scene(scene_manager, InfraredSceneAskBack);
         }
         }
         consumed = true;
         consumed = true;
     } else if(event.type == SceneManagerEventTypeCustom) {
     } else if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == DialogExResultLeft) {
         if(event.event == DialogExResultLeft) {
-            if(scene_state == InfraredSceneLearnSuccessStateIdle) {
+            if(is_transmitter_idle) {
                 scene_manager_next_scene(scene_manager, InfraredSceneAskRetry);
                 scene_manager_next_scene(scene_manager, InfraredSceneAskRetry);
             }
             }
             consumed = true;
             consumed = true;
         } else if(event.event == DialogExResultRight) {
         } else if(event.event == DialogExResultRight) {
-            if(scene_state == InfraredSceneLearnSuccessStateIdle) {
+            if(is_transmitter_idle) {
                 scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName);
                 scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName);
             }
             }
             consumed = true;
             consumed = true;
         } else if(event.event == DialogExPressCenter) {
         } else if(event.event == DialogExPressCenter) {
-            if(scene_state == InfraredSceneLearnSuccessStateIdle) {
-                scene_manager_set_scene_state(
-                    scene_manager,
-                    InfraredSceneLearnSuccess,
-                    InfraredSceneLearnSuccessStateSending);
-                infrared_tx_start_received(infrared);
-                infrared_play_notification_message(
-                    infrared, InfraredNotificationMessageBlinkStartSend);
-            }
+            infrared_tx_start_received(infrared);
             consumed = true;
             consumed = true;
         } else if(event.event == DialogExReleaseCenter) {
         } else if(event.event == DialogExReleaseCenter) {
-            if(scene_state == InfraredSceneLearnSuccessStateSending) {
-                scene_manager_set_scene_state(
-                    scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle);
-                infrared_tx_stop(infrared);
-                infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
-                infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
-            }
+            infrared_tx_stop(infrared);
+            infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
             consumed = true;
             consumed = true;
         }
         }
     }
     }
@@ -123,9 +100,5 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even
 
 
 void infrared_scene_learn_success_on_exit(void* context) {
 void infrared_scene_learn_success_on_exit(void* context) {
     Infrared* infrared = context;
     Infrared* infrared = context;
-    InfraredWorker* worker = infrared->worker;
     dialog_ex_reset(infrared->dialog_ex);
     dialog_ex_reset(infrared->dialog_ex);
-    infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
-    infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff);
-    infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL);
 }
 }

+ 21 - 16
applications/infrared/scenes/infrared_scene_remote.c

@@ -31,9 +31,6 @@ void infrared_scene_remote_on_enter(void* context) {
     ButtonMenu* button_menu = infrared->button_menu;
     ButtonMenu* button_menu = infrared->button_menu;
     SceneManager* scene_manager = infrared->scene_manager;
     SceneManager* scene_manager = infrared->scene_manager;
 
 
-    infrared_worker_tx_set_get_signal_callback(
-        infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
-
     size_t button_count = infrared_remote_get_button_count(remote);
     size_t button_count = infrared_remote_get_button_count(remote);
     for(size_t i = 0; i < button_count; ++i) {
     for(size_t i = 0; i < button_count; ++i) {
         InfraredRemoteButton* button = infrared_remote_get_button(remote, i);
         InfraredRemoteButton* button = infrared_remote_get_button(remote, i);
@@ -73,12 +70,17 @@ void infrared_scene_remote_on_enter(void* context) {
 bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
 bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
     Infrared* infrared = context;
     Infrared* infrared = context;
     SceneManager* scene_manager = infrared->scene_manager;
     SceneManager* scene_manager = infrared->scene_manager;
+    const bool is_transmitter_idle = !infrared->app_state.is_transmitting;
     bool consumed = false;
     bool consumed = false;
 
 
     if(event.type == SceneManagerEventTypeBack) {
     if(event.type == SceneManagerEventTypeBack) {
-        const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
-        consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
-            scene_manager, possible_scenes, COUNT_OF(possible_scenes));
+        if(is_transmitter_idle) {
+            const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
+            consumed = scene_manager_search_and_switch_to_previous_scene_one_of(
+                scene_manager, possible_scenes, COUNT_OF(possible_scenes));
+        } else {
+            consumed = true;
+        }
     } else if(event.type == SceneManagerEventTypeCustom) {
     } else if(event.type == SceneManagerEventTypeCustom) {
         const uint16_t custom_type = infrared_custom_event_get_type(event.event);
         const uint16_t custom_type = infrared_custom_event_get_type(event.event);
         const int16_t button_index = infrared_custom_event_get_value(event.event);
         const int16_t button_index = infrared_custom_event_get_value(event.event);
@@ -92,14 +94,19 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
             consumed = true;
             consumed = true;
         } else if(custom_type == InfraredCustomEventTypeMenuSelected) {
         } else if(custom_type == InfraredCustomEventTypeMenuSelected) {
             furi_assert(button_index < 0);
             furi_assert(button_index < 0);
-            scene_manager_set_scene_state(
-                scene_manager, InfraredSceneRemote, (unsigned)button_index);
-            if(button_index == ButtonIndexPlus) {
-                infrared->app_state.is_learning_new_remote = false;
-                scene_manager_next_scene(scene_manager, InfraredSceneLearn);
-                consumed = true;
-            } else if(button_index == ButtonIndexEdit) {
-                scene_manager_next_scene(scene_manager, InfraredSceneEdit);
+            if(is_transmitter_idle) {
+                scene_manager_set_scene_state(
+                    scene_manager, InfraredSceneRemote, (unsigned)button_index);
+                if(button_index == ButtonIndexPlus) {
+                    infrared->app_state.is_learning_new_remote = false;
+                    scene_manager_next_scene(scene_manager, InfraredSceneLearn);
+                    consumed = true;
+                } else if(button_index == ButtonIndexEdit) {
+                    scene_manager_next_scene(scene_manager, InfraredSceneEdit);
+                    consumed = true;
+                }
+
+            } else {
                 consumed = true;
                 consumed = true;
             }
             }
         }
         }
@@ -110,7 +117,5 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) {
 
 
 void infrared_scene_remote_on_exit(void* context) {
 void infrared_scene_remote_on_exit(void* context) {
     Infrared* infrared = context;
     Infrared* infrared = context;
-    infrared_tx_stop(infrared);
-    infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL);
     button_menu_reset(infrared->button_menu);
     button_menu_reset(infrared->button_menu);
 }
 }

+ 0 - 2
applications/infrared/scenes/infrared_scene_rpc.c

@@ -44,8 +44,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) {
             if(arg && (state == InfraredRpcStateIdle)) {
             if(arg && (state == InfraredRpcStateIdle)) {
                 string_set_str(infrared->file_path, arg);
                 string_set_str(infrared->file_path, arg);
                 result = infrared_remote_load(infrared->remote, infrared->file_path);
                 result = infrared_remote_load(infrared->remote, infrared->file_path);
-                infrared_worker_tx_set_get_signal_callback(
-                    infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared);
                 if(result) {
                 if(result) {
                     scene_manager_set_scene_state(
                     scene_manager_set_scene_state(
                         infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);
                         infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded);