Pārlūkot izejas kodu

BLE Spam: Fix back event deadlocks

Willy-JL 1 gadu atpakaļ
vecāks
revīzija
f6adf06956

+ 1 - 1
ble_spam/application.fam

@@ -9,7 +9,7 @@ App(
     fap_file_assets="assets",
     fap_author="@Willy-JL @ECTO-1A @Spooks4576",
     fap_weburl="https://github.com/Next-Flip/Momentum-Apps/tree/dev/ble_spam",
-    fap_version="6.2",
+    fap_version="6.3",
     fap_description="Flood BLE advertisements to cause spammy and annoying popups/notifications",
     fap_icon_assets="icons",
     fap_icon_assets_symbol="ble_spam",

+ 6 - 0
ble_spam/ble_spam.c

@@ -628,6 +628,11 @@ static void lock_timer_callback(void* _ctx) {
     furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
 }
 
+static bool custom_event_callback(void* _ctx, uint32_t event) {
+    State* state = _ctx;
+    return scene_manager_handle_custom_event(state->ctx.scene_manager, event);
+}
+
 static void tick_event_callback(void* _ctx) {
     State* state = _ctx;
     bool advertising;
@@ -668,6 +673,7 @@ int32_t ble_spam(void* p) {
     state->ctx.view_dispatcher = view_dispatcher_alloc();
     view_dispatcher_enable_queue(state->ctx.view_dispatcher);
     view_dispatcher_set_event_callback_context(state->ctx.view_dispatcher, state);
+    view_dispatcher_set_custom_event_callback(state->ctx.view_dispatcher, custom_event_callback);
     view_dispatcher_set_tick_event_callback(state->ctx.view_dispatcher, tick_event_callback, 100);
     view_dispatcher_set_navigation_event_callback(state->ctx.view_dispatcher, back_event_callback);
     state->ctx.scene_manager = scene_manager_alloc(&scene_handlers, &state->ctx);

+ 63 - 35
ble_spam/protocols/continuity.c

@@ -821,7 +821,7 @@ static void pp_model_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case pp_models_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpModelCustom);
@@ -832,14 +832,14 @@ static void pp_model_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.value = cfg->data.proximity_pair.model;
         payload->bruteforce.size = 2;
         cfg->data.proximity_pair.bruteforce_mode = ContinuityPpBruteforceModel;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     default:
         if(payload->mode != PayloadModeBruteforce ||
            cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceModel)
             payload->mode = PayloadModeValue;
         cfg->data.proximity_pair.model = pp_models[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -881,8 +881,11 @@ void scene_continuity_pp_model_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_continuity_pp_model_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_model_on_exit(void* _ctx) {
@@ -898,8 +901,7 @@ static void pp_model_custom_callback(void* _ctx) {
        cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceModel)
         payload->mode = PayloadModeValue;
     cfg->data.proximity_pair.model = (ctx->byte_store[0] << 0x08) + (ctx->byte_store[1] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_continuity_pp_model_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -918,8 +920,12 @@ void scene_continuity_pp_model_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_continuity_pp_model_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_model_custom_on_exit(void* _ctx) {
@@ -950,13 +956,13 @@ static void pp_color_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.value = cfg->data.proximity_pair.color;
         payload->bruteforce.size = 1;
         cfg->data.proximity_pair.bruteforce_mode = ContinuityPpBruteforceColor;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
     } else {
         if(payload->mode != PayloadModeBruteforce ||
            cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)
             payload->mode = PayloadModeValue;
         cfg->data.proximity_pair.color = pp_models[model_index].colors[index].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
     }
 }
 void scene_continuity_pp_color_on_enter(void* _ctx) {
@@ -1005,8 +1011,11 @@ void scene_continuity_pp_color_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_continuity_pp_color_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_color_on_exit(void* _ctx) {
@@ -1022,8 +1031,7 @@ static void pp_color_custom_callback(void* _ctx) {
        cfg->data.proximity_pair.bruteforce_mode == ContinuityPpBruteforceColor)
         payload->mode = PayloadModeValue;
     cfg->data.proximity_pair.color = (ctx->byte_store[0] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_continuity_pp_color_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -1041,8 +1049,12 @@ void scene_continuity_pp_color_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_continuity_pp_color_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_color_custom_on_exit(void* _ctx) {
@@ -1056,14 +1068,14 @@ static void pp_prefix_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         cfg->data.proximity_pair.prefix = 0x00;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case pp_prefixes_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneContinuityPpPrefixCustom);
         break;
     default:
         cfg->data.proximity_pair.prefix = pp_prefixes[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -1098,8 +1110,11 @@ void scene_continuity_pp_prefix_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_continuity_pp_prefix_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_prefix_on_exit(void* _ctx) {
@@ -1112,8 +1127,7 @@ static void pp_prefix_custom_callback(void* _ctx) {
     Payload* payload = &ctx->attack->payload;
     ContinuityCfg* cfg = &payload->cfg.continuity;
     cfg->data.proximity_pair.prefix = (ctx->byte_store[0] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_continuity_pp_prefix_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -1131,8 +1145,12 @@ void scene_continuity_pp_prefix_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_continuity_pp_prefix_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_pp_prefix_custom_on_exit(void* _ctx) {
@@ -1146,7 +1164,7 @@ static void na_action_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case na_actions_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneContinuityNaActionCustom);
@@ -1156,12 +1174,12 @@ static void na_action_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.counter = 0;
         payload->bruteforce.value = cfg->data.nearby_action.action;
         payload->bruteforce.size = 1;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     default:
         payload->mode = PayloadModeValue;
         cfg->data.nearby_action.action = na_actions[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -1201,8 +1219,11 @@ void scene_continuity_na_action_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_continuity_na_action_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_na_action_on_exit(void* _ctx) {
@@ -1216,8 +1237,7 @@ static void na_action_custom_callback(void* _ctx) {
     ContinuityCfg* cfg = &payload->cfg.continuity;
     payload->mode = PayloadModeValue;
     cfg->data.nearby_action.action = (ctx->byte_store[0] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_continuity_na_action_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -1235,8 +1255,12 @@ void scene_continuity_na_action_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_continuity_na_action_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_continuity_na_action_custom_on_exit(void* _ctx) {
@@ -1245,7 +1269,7 @@ void scene_continuity_na_action_custom_on_exit(void* _ctx) {
 
 static void na_flags_callback(void* _ctx) {
     Ctx* ctx = _ctx;
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_continuity_na_flags_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -1264,6 +1288,10 @@ void scene_continuity_na_flags_on_enter(void* _ctx) {
 }
 bool scene_continuity_na_flags_on_event(void* _ctx, SceneManagerEvent event) {
     Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     if(event.type == SceneManagerEventTypeBack) {
         ctx->byte_store[0] = 0x00;
     }

+ 30 - 18
ble_spam/protocols/easysetup.c

@@ -373,7 +373,7 @@ static void buds_model_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case buds_models_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneEasysetupBudsModelCustom);
@@ -383,12 +383,12 @@ static void buds_model_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.counter = 0;
         payload->bruteforce.value = cfg->data.buds.model;
         payload->bruteforce.size = 3;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     default:
         payload->mode = PayloadModeValue;
         cfg->data.buds.model = buds_models[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -428,8 +428,11 @@ void scene_easysetup_buds_model_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_easysetup_buds_model_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_easysetup_buds_model_on_exit(void* _ctx) {
@@ -444,8 +447,7 @@ static void buds_model_custom_callback(void* _ctx) {
     payload->mode = PayloadModeValue;
     cfg->data.buds.model =
         (ctx->byte_store[0] << 0x10) + (ctx->byte_store[1] << 0x08) + (ctx->byte_store[2] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_easysetup_buds_model_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -465,8 +467,12 @@ void scene_easysetup_buds_model_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_easysetup_buds_model_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_easysetup_buds_model_custom_on_exit(void* _ctx) {
@@ -480,7 +486,7 @@ static void watch_model_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case watch_models_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneEasysetupWatchModelCustom);
@@ -490,12 +496,12 @@ static void watch_model_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.counter = 0;
         payload->bruteforce.value = cfg->data.watch.model;
         payload->bruteforce.size = 1;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     default:
         payload->mode = PayloadModeValue;
         cfg->data.watch.model = watch_models[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -535,8 +541,11 @@ void scene_easysetup_watch_model_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_easysetup_watch_model_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_easysetup_watch_model_on_exit(void* _ctx) {
@@ -550,8 +559,7 @@ static void watch_model_custom_callback(void* _ctx) {
     EasysetupCfg* cfg = &payload->cfg.easysetup;
     payload->mode = PayloadModeValue;
     cfg->data.watch.model = (ctx->byte_store[0] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_easysetup_watch_model_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -569,8 +577,12 @@ void scene_easysetup_watch_model_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_easysetup_watch_model_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_easysetup_watch_model_custom_on_exit(void* _ctx) {

+ 15 - 9
ble_spam/protocols/fastpair.c

@@ -726,7 +726,7 @@ static void model_callback(void* _ctx, uint32_t index) {
     switch(index) {
     case 0:
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     case models_count + 1:
         scene_manager_next_scene(ctx->scene_manager, SceneFastpairModelCustom);
@@ -736,12 +736,12 @@ static void model_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.counter = 0;
         payload->bruteforce.value = cfg->model;
         payload->bruteforce.size = 3;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     default:
         payload->mode = PayloadModeValue;
         cfg->model = models[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         break;
     }
 }
@@ -780,8 +780,11 @@ void scene_fastpair_model_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_fastpair_model_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_fastpair_model_on_exit(void* _ctx) {
@@ -796,8 +799,7 @@ static void model_custom_callback(void* _ctx) {
     payload->mode = PayloadModeValue;
     cfg->model =
         (ctx->byte_store[0] << 0x10) + (ctx->byte_store[1] << 0x08) + (ctx->byte_store[2] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_fastpair_model_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -817,8 +819,12 @@ void scene_fastpair_model_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_fastpair_model_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_fastpair_model_custom_on_exit(void* _ctx) {

+ 15 - 9
ble_spam/protocols/lovespouse.c

@@ -195,7 +195,7 @@ static void mode_callback(void* _ctx, uint32_t index) {
     LovespouseCfg* cfg = &payload->cfg.lovespouse;
     if(index == 0) {
         payload->mode = PayloadModeRandom;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
     } else if(index == modes[cfg->state].count + 1U) {
         scene_manager_next_scene(ctx->scene_manager, SceneLovespouseModeCustom);
     } else if(modes[cfg->state].count + 2U) {
@@ -203,11 +203,11 @@ static void mode_callback(void* _ctx, uint32_t index) {
         payload->bruteforce.counter = 0;
         payload->bruteforce.value = cfg->mode;
         payload->bruteforce.size = 3;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
     } else {
         payload->mode = PayloadModeValue;
         cfg->mode = modes[cfg->state].modes[index - 1].value;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
     }
 }
 void scene_lovespouse_mode_on_enter(void* _ctx) {
@@ -246,8 +246,11 @@ void scene_lovespouse_mode_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewSubmenu);
 }
 bool scene_lovespouse_mode_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_lovespouse_mode_on_exit(void* _ctx) {
@@ -262,8 +265,7 @@ static void mode_custom_callback(void* _ctx) {
     payload->mode = PayloadModeValue;
     cfg->mode =
         (ctx->byte_store[0] << 0x10) + (ctx->byte_store[1] << 0x08) + (ctx->byte_store[2] << 0x00);
-    scene_manager_previous_scene(ctx->scene_manager);
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_lovespouse_mode_custom_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -283,8 +285,12 @@ void scene_lovespouse_mode_custom_on_enter(void* _ctx) {
     view_dispatcher_switch_to_view(ctx->view_dispatcher, ViewByteInput);
 }
 bool scene_lovespouse_mode_custom_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }
 void scene_lovespouse_mode_custom_on_exit(void* _ctx) {

+ 5 - 1
ble_spam/protocols/nameflood.c

@@ -142,7 +142,7 @@ static void name_callback(void* _ctx) {
     Ctx* ctx = _ctx;
     Payload* payload = &ctx->attack->payload;
     payload->mode = PayloadModeValue;
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_nameflood_name_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -162,6 +162,10 @@ void scene_nameflood_name_on_enter(void* _ctx) {
 bool scene_nameflood_name_on_event(void* _ctx, SceneManagerEvent event) {
     Ctx* ctx = _ctx;
     Payload* payload = &ctx->attack->payload;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     if(event.type == SceneManagerEventTypeBack) {
         payload->mode = PayloadModeRandom;
     }

+ 5 - 1
ble_spam/protocols/swiftpair.c

@@ -135,7 +135,7 @@ static void name_callback(void* _ctx) {
     Ctx* ctx = _ctx;
     Payload* payload = &ctx->attack->payload;
     payload->mode = PayloadModeValue;
-    scene_manager_previous_scene(ctx->scene_manager);
+    view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
 }
 void scene_swiftpair_name_on_enter(void* _ctx) {
     Ctx* ctx = _ctx;
@@ -155,6 +155,10 @@ void scene_swiftpair_name_on_enter(void* _ctx) {
 bool scene_swiftpair_name_on_event(void* _ctx, SceneManagerEvent event) {
     Ctx* ctx = _ctx;
     Payload* payload = &ctx->attack->payload;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     if(event.type == SceneManagerEventTypeBack) {
         payload->mode = PayloadModeRandom;
     }

+ 6 - 3
ble_spam/scenes/config.c

@@ -30,7 +30,7 @@ static void config_callback(void* _ctx, uint32_t index) {
         break;
     case ConfigLockKeyboard:
         ctx->lock_keyboard = true;
-        scene_manager_previous_scene(ctx->scene_manager);
+        view_dispatcher_send_custom_event(ctx->view_dispatcher, 0);
         notification_message_block(ctx->notification, &sequence_display_backlight_off);
         break;
     default:
@@ -64,8 +64,11 @@ void scene_config_on_enter(void* _ctx) {
 }
 
 bool scene_config_on_event(void* _ctx, SceneManagerEvent event) {
-    UNUSED(_ctx);
-    UNUSED(event);
+    Ctx* ctx = _ctx;
+    if(event.type == SceneManagerEventTypeCustom) {
+        scene_manager_previous_scene(ctx->scene_manager);
+        return true;
+    }
     return false;
 }