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

Decouple apps to allow smaller builds. Loader deadlock fix and refactoring. (#929)

* Lib: always include rfal
* Gui: remove screen_stream
* Input: decouple from Cli
* Loader: decouple from Cli
* Desktop: ignore missing favorite app, decouple from Archive
* Make: make Notification a Gui dependency
* Make: embed debugging information into elfs
* Loader: hide Plugins submenu when plugins ga arimasen
* Applications: update on start hook usage
* Loader: fix dead lock on menu rebuild with open rpc, new cli command.

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Anna Prosvetova 4 лет назад
Родитель
Сommit
46a25c295c

+ 20 - 22
applications/applications.c

@@ -48,16 +48,16 @@ extern int32_t music_player_app(void* p);
 extern int32_t snake_game_app(void* p);
 extern int32_t snake_game_app(void* p);
 
 
 // On system start hooks declaration
 // On system start hooks declaration
-extern void bt_cli_init();
-extern void crypto_cli_init();
-extern void ibutton_cli_init();
-extern void irda_cli_init();
-extern void lfrfid_cli_init();
-extern void nfc_cli_init();
-extern void storage_cli_init();
-extern void subghz_cli_init();
-extern void power_cli_init();
-extern void unit_tests_cli_init();
+extern void bt_on_system_start();
+extern void crypto_on_system_start();
+extern void ibutton_on_system_start();
+extern void irda_on_system_start();
+extern void lfrfid_on_system_start();
+extern void nfc_on_system_start();
+extern void storage_on_system_start();
+extern void subghz_on_system_start();
+extern void power_on_system_start();
+extern void unit_tests_on_system_start();
 
 
 // Settings
 // Settings
 extern int32_t notification_settings_app(void* p);
 extern int32_t notification_settings_app(void* p);
@@ -166,44 +166,42 @@ const size_t FLIPPER_APPS_COUNT = sizeof(FLIPPER_APPS) / sizeof(FlipperApplicati
 
 
 // On system start hooks
 // On system start hooks
 const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = {
 const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = {
-#ifdef SRV_CLI
-    crypto_cli_init,
-#endif
+    crypto_on_system_start,
 
 
 #ifdef APP_IRDA
 #ifdef APP_IRDA
-    irda_cli_init,
+    irda_on_system_start,
 #endif
 #endif
 
 
 #ifdef APP_NFC
 #ifdef APP_NFC
-    nfc_cli_init,
+    nfc_on_system_start,
 #endif
 #endif
 
 
 #ifdef APP_SUBGHZ
 #ifdef APP_SUBGHZ
-    subghz_cli_init,
+    subghz_on_system_start,
 #endif
 #endif
 
 
 #ifdef APP_LF_RFID
 #ifdef APP_LF_RFID
-    lfrfid_cli_init,
+    lfrfid_on_system_start,
 #endif
 #endif
 
 
 #ifdef APP_IBUTTON
 #ifdef APP_IBUTTON
-    ibutton_cli_init,
+    ibutton_on_system_start,
 #endif
 #endif
 
 
 #ifdef SRV_BT
 #ifdef SRV_BT
-    bt_cli_init,
+    bt_on_system_start,
 #endif
 #endif
 
 
 #ifdef SRV_POWER
 #ifdef SRV_POWER
-    power_cli_init,
+    power_on_system_start,
 #endif
 #endif
 
 
 #ifdef SRV_STORAGE
 #ifdef SRV_STORAGE
-    storage_cli_init,
+    storage_on_system_start,
 #endif
 #endif
 
 
 #ifdef APP_UNIT_TESTS
 #ifdef APP_UNIT_TESTS
-    unit_tests_cli_init,
+    unit_tests_on_system_start,
 #endif
 #endif
 };
 };
 
 

+ 1 - 0
applications/applications.mk

@@ -298,6 +298,7 @@ SRV_GUI	?= 0
 ifeq ($(SRV_GUI), 1)
 ifeq ($(SRV_GUI), 1)
 CFLAGS		+= -DSRV_GUI
 CFLAGS		+= -DSRV_GUI
 SRV_INPUT	= 1
 SRV_INPUT	= 1
+SRV_NOTIFICATION = 1
 endif
 endif
 
 
 
 

+ 3 - 1
applications/bt/bt_cli.c

@@ -3,7 +3,8 @@
 #include <furi-hal.h>
 #include <furi-hal.h>
 #include "bt_settings.h"
 #include "bt_settings.h"
 
 
-void bt_cli_init() {
+void bt_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
 
 
     cli_add_command(cli, "bt_info", CliCommandFlagDefault, bt_cli_command_info, NULL);
     cli_add_command(cli, "bt_info", CliCommandFlagDefault, bt_cli_command_info, NULL);
@@ -13,6 +14,7 @@ void bt_cli_init() {
     cli_add_command(cli, "bt_rx_pt", CliCommandFlagDefault, bt_cli_command_packet_rx, NULL);
     cli_add_command(cli, "bt_rx_pt", CliCommandFlagDefault, bt_cli_command_packet_rx, NULL);
 
 
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }
 
 
 void bt_cli_command_info(Cli* cli, string_t args, void* context) {
 void bt_cli_command_info(Cli* cli, string_t args, void* context) {

+ 1 - 1
applications/bt/bt_cli.h

@@ -2,7 +2,7 @@
 
 
 #include <cli/cli.h>
 #include <cli/cli.h>
 
 
-void bt_cli_init();
+void bt_on_system_start();
 
 
 void bt_cli_command_info(Cli* cli, string_t args, void* context);
 void bt_cli_command_info(Cli* cli, string_t args, void* context);
 
 

+ 3 - 1
applications/crypto/crypto_cli.c

@@ -312,8 +312,10 @@ void crypto_cli(Cli* cli, string_t args, void* context) {
     string_clear(cmd);
     string_clear(cmd);
 }
 }
 
 
-void crypto_cli_init() {
+void crypto_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
     cli_add_command(cli, "crypto", CliCommandFlagDefault, crypto_cli, NULL);
     cli_add_command(cli, "crypto", CliCommandFlagDefault, crypto_cli, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 7 - 1
applications/desktop/scenes/desktop_scene_main.c

@@ -83,13 +83,19 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
             break;
             break;
 
 
         case DesktopMainEventOpenArchive:
         case DesktopMainEventOpenArchive:
+#ifdef APP_ARCHIVE
             desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
             desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
+#endif
             consumed = true;
             consumed = true;
             break;
             break;
 
 
         case DesktopMainEventOpenFavorite:
         case DesktopMainEventOpenFavorite:
             LOAD_DESKTOP_SETTINGS(&desktop->settings);
             LOAD_DESKTOP_SETTINGS(&desktop->settings);
-            desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]);
+            if(desktop->settings.favorite) {
+                desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]);
+            } else {
+                FURI_LOG_E("DesktopSrv", "Can't find favorite application");
+            }
             consumed = true;
             consumed = true;
             break;
             break;
 
 

+ 4 - 41
applications/gui/gui.c

@@ -254,43 +254,6 @@ void gui_unlock(Gui* gui) {
     furi_check(osMutexRelease(gui->mutex) == osOK);
     furi_check(osMutexRelease(gui->mutex) == osOK);
 }
 }
 
 
-void gui_cli_screen_stream_callback(uint8_t* data, size_t size, void* context) {
-    furi_assert(data);
-    furi_assert(size == 1024);
-    furi_assert(context);
-
-    Gui* gui = context;
-    const uint8_t magic[] = {0xF0, 0xE1, 0xD2, 0xC3};
-    cli_write(gui->cli, magic, sizeof(magic));
-    cli_write(gui->cli, data, size);
-}
-
-void gui_cli_screen_stream(Cli* cli, string_t args, void* context) {
-    furi_assert(context);
-    Gui* gui = context;
-    gui_set_framebuffer_callback(gui, gui_cli_screen_stream_callback, gui);
-    gui_redraw(gui);
-
-    // Wait for control events
-    while(true) {
-        char c = cli_getc(gui->cli);
-        if(c == CliSymbolAsciiEsc) {
-            c = cli_getc(gui->cli);
-            if(c == 'i') {
-                InputEvent input_event;
-                input_event.key = cli_getc(gui->cli);
-                input_event.type = cli_getc(gui->cli);
-                osMessageQueuePut(gui->input_queue, &input_event, 0, osWaitForever);
-                osThreadFlagsSet(gui->thread, GUI_THREAD_FLAG_INPUT);
-            }
-        } else {
-            break;
-        }
-    }
-
-    gui_set_framebuffer_callback(gui, NULL, NULL);
-}
-
 void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) {
 void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) {
     furi_assert(gui);
     furi_assert(gui);
     furi_assert(view_port);
     furi_assert(view_port);
@@ -401,6 +364,10 @@ void gui_set_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, vo
     gui->canvas_callback = callback;
     gui->canvas_callback = callback;
     gui->canvas_callback_context = context;
     gui->canvas_callback_context = context;
     gui_unlock(gui);
     gui_unlock(gui);
+
+    if(callback != NULL) {
+        gui_redraw(gui);
+    }
 }
 }
 
 
 Gui* gui_alloc() {
 Gui* gui_alloc() {
@@ -421,10 +388,6 @@ Gui* gui_alloc() {
     gui->input_events = furi_record_open("input_events");
     gui->input_events = furi_record_open("input_events");
     furi_check(gui->input_events);
     furi_check(gui->input_events);
     furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui);
     furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui);
-    // Cli
-    gui->cli = furi_record_open("cli");
-    cli_add_command(
-        gui->cli, "screen_stream", CliCommandFlagParallelSafe, gui_cli_screen_stream, gui);
 
 
     return gui;
     return gui;
 }
 }

+ 0 - 8
applications/gui/gui_i.h

@@ -11,7 +11,6 @@
 #include <m-array.h>
 #include <m-array.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
-#include <cli/cli.h>
 #include "canvas.h"
 #include "canvas.h"
 #include "canvas_i.h"
 #include "canvas_i.h"
 #include "view_port.h"
 #include "view_port.h"
@@ -60,9 +59,6 @@ struct Gui {
     FuriPubSub* input_events;
     FuriPubSub* input_events;
     uint8_t ongoing_input;
     uint8_t ongoing_input;
     ViewPort* ongoing_input_view_port;
     ViewPort* ongoing_input_view_port;
-
-    // Cli
-    Cli* cli;
 };
 };
 
 
 ViewPort* gui_view_port_find_enabled(ViewPortArray_t array);
 ViewPort* gui_view_port_find_enabled(ViewPortArray_t array);
@@ -78,7 +74,3 @@ void gui_input_events_callback(const void* value, void* ctx);
 void gui_lock(Gui* gui);
 void gui_lock(Gui* gui);
 
 
 void gui_unlock(Gui* gui);
 void gui_unlock(Gui* gui);
-
-void gui_cli_screen_stream_callback(uint8_t* data, size_t size, void* context);
-
-void gui_cli_screen_stream(Cli* cli, string_t args, void* context);

+ 4 - 2
applications/ibutton/ibutton-cli.cpp

@@ -13,11 +13,13 @@ void ibutton_cli(Cli* cli, string_t args, void* context);
 void onewire_cli(Cli* cli, string_t args, void* context);
 void onewire_cli(Cli* cli, string_t args, void* context);
 
 
 // app cli function
 // app cli function
-extern "C" void ibutton_cli_init() {
+extern "C" void ibutton_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
     Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
     cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli);
     cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli);
     cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli);
     cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }
 
 
 void ibutton_cli_print_usage() {
 void ibutton_cli_print_usage() {
@@ -284,4 +286,4 @@ void onewire_cli(Cli* cli, string_t args, void* context) {
     }
     }
 
 
     string_clear(cmd);
     string_clear(cmd);
-}
+}

+ 4 - 0
applications/input/input.c

@@ -40,6 +40,7 @@ void input_isr(void* _ctx) {
     osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR);
     osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR);
 }
 }
 
 
+#ifdef SRV_CLI
 void input_cli_send(Cli* cli, string_t args, void* context) {
 void input_cli_send(Cli* cli, string_t args, void* context) {
     InputEvent event;
     InputEvent event;
 
 
@@ -122,6 +123,7 @@ static void input_cli_dump(Cli* cli, string_t args, void* context) {
     furi_pubsub_unsubscribe(input->event_pubsub, input_subscription);
     furi_pubsub_unsubscribe(input->event_pubsub, input_subscription);
     osMessageQueueDelete(input_queue);
     osMessageQueueDelete(input_queue);
 }
 }
+#endif
 
 
 const char* input_get_key_name(InputKey key) {
 const char* input_get_key_name(InputKey key) {
     for(size_t i = 0; i < input_pins_count; i++) {
     for(size_t i = 0; i < input_pins_count; i++) {
@@ -154,6 +156,7 @@ int32_t input_srv() {
     input->event_pubsub = furi_pubsub_alloc();
     input->event_pubsub = furi_pubsub_alloc();
     furi_record_create("input_events", input->event_pubsub);
     furi_record_create("input_events", input->event_pubsub);
 
 
+#ifdef SRV_CLI
     input->cli = furi_record_open("cli");
     input->cli = furi_record_open("cli");
     if(input->cli) {
     if(input->cli) {
         cli_add_command(
         cli_add_command(
@@ -161,6 +164,7 @@ int32_t input_srv() {
         cli_add_command(
         cli_add_command(
             input->cli, "input_dump", CliCommandFlagParallelSafe, input_cli_dump, NULL);
             input->cli, "input_dump", CliCommandFlagParallelSafe, input_cli_dump, NULL);
     }
     }
+#endif
 
 
     input->pin_states = furi_alloc(input_pins_count * sizeof(InputPinState));
     input->pin_states = furi_alloc(input_pins_count * sizeof(InputPinState));
 
 

+ 5 - 3
applications/irda/cli/irda-cli.cpp

@@ -47,7 +47,7 @@ static void signal_received_callback(void* context, IrdaWorkerSignal* received_s
     }
     }
 }
 }
 
 
-static void irda_cli_start_ir_rx(Cli* cli, string_t args, void* context) {
+void irda_cli_start_ir_rx(Cli* cli, string_t args, void* context) {
     if(furi_hal_irda_is_busy()) {
     if(furi_hal_irda_is_busy()) {
         printf("IRDA is busy. Exit.");
         printf("IRDA is busy. Exit.");
         return;
         return;
@@ -170,7 +170,7 @@ static bool parse_signal_raw(
     return (parsed == 2) && (*timings_cnt > 0);
     return (parsed == 2) && (*timings_cnt > 0);
 }
 }
 
 
-static void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) {
+void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) {
     if(furi_hal_irda_is_busy()) {
     if(furi_hal_irda_is_busy()) {
         printf("IRDA is busy. Exit.");
         printf("IRDA is busy. Exit.");
         return;
         return;
@@ -195,9 +195,11 @@ static void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) {
     free(timings);
     free(timings);
 }
 }
 
 
-extern "C" void irda_cli_init() {
+extern "C" void irda_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = (Cli*)furi_record_open("cli");
     Cli* cli = (Cli*)furi_record_open("cli");
     cli_add_command(cli, "ir_rx", CliCommandFlagDefault, irda_cli_start_ir_rx, NULL);
     cli_add_command(cli, "ir_rx", CliCommandFlagDefault, irda_cli_start_ir_rx, NULL);
     cli_add_command(cli, "ir_tx", CliCommandFlagDefault, irda_cli_start_ir_tx, NULL);
     cli_add_command(cli, "ir_tx", CliCommandFlagDefault, irda_cli_start_ir_tx, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 3 - 1
applications/lfrfid/lfrfid-cli.cpp

@@ -10,10 +10,12 @@
 void lfrfid_cli(Cli* cli, string_t args, void* context);
 void lfrfid_cli(Cli* cli, string_t args, void* context);
 
 
 // app cli function
 // app cli function
-extern "C" void lfrfid_cli_init() {
+extern "C" void lfrfid_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
     Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
     cli_add_command(cli, "rfid", CliCommandFlagDefault, lfrfid_cli, NULL);
     cli_add_command(cli, "rfid", CliCommandFlagDefault, lfrfid_cli, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }
 
 
 void lfrfid_cli_print_usage() {
 void lfrfid_cli_print_usage() {

+ 119 - 37
applications/loader/loader.c

@@ -23,7 +23,7 @@ static void loader_menu_callback(void* _ctx, uint32_t index) {
     furi_hal_power_insomnia_enter();
     furi_hal_power_insomnia_enter();
     loader_instance->current_app = flipper_app;
     loader_instance->current_app = flipper_app;
 
 
-    FURI_LOG_I(TAG, "Starting furi application: %s", loader_instance->current_app->name);
+    FURI_LOG_I(TAG, "Starting: %s", loader_instance->current_app->name);
     furi_thread_set_name(loader_instance->thread, flipper_app->name);
     furi_thread_set_name(loader_instance->thread, flipper_app->name);
     furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size);
     furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size);
     furi_thread_set_context(loader_instance->thread, NULL);
     furi_thread_set_context(loader_instance->thread, NULL);
@@ -36,25 +36,115 @@ static void loader_submenu_callback(void* context, uint32_t index) {
     view_dispatcher_switch_to_view(loader_instance->view_dispatcher, view_id);
     view_dispatcher_switch_to_view(loader_instance->view_dispatcher, view_id);
 }
 }
 
 
-static void loader_cli_callback(Cli* cli, string_t args, void* _ctx) {
-    furi_assert(_ctx);
-    const FlipperApplication* flipper_app = (FlipperApplication*)_ctx;
-    furi_assert(flipper_app->app);
-    furi_assert(flipper_app->name);
+static void loader_cli_print_usage() {
+    printf("Usage:\r\n");
+    printf("loader <cmd> <args>\r\n");
+    printf("Cmd list:\r\n");
+    printf("\tlist\t - List available applications\r\n");
+    printf("\topen <Application Name:string>\t - Open application by name\r\n");
+}
 
 
-    if(furi_thread_get_state(loader_instance->thread) != FuriThreadStateStopped) {
+const FlipperApplication* loader_find_application_by_name(string_t name) {
+    const FlipperApplication* application = NULL;
+
+    for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
+        if(string_cmp_str(name, FLIPPER_APPS[i].name) == 0) {
+            application = &FLIPPER_APPS[i];
+        }
+    }
+
+    for(size_t i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
+        if(string_cmp_str(name, FLIPPER_APPS[i].name) == 0) {
+            application = &FLIPPER_APPS[i];
+        }
+    }
+
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
+            if(string_cmp_str(name, FLIPPER_APPS[i].name) == 0) {
+                application = &FLIPPER_APPS[i];
+            }
+        }
+    }
+
+    return application;
+}
+
+void loader_cli_open(Cli* cli, string_t args, Loader* instance) {
+    string_strim(args);
+
+    if(string_size(args) == 0) {
+        printf("No application provided\r\n");
+        return;
+    }
+
+    const FlipperApplication* application = loader_find_application_by_name(args);
+    if(!application) {
+        printf("%s doesn't exists\r\n", string_get_cstr(args));
+        return;
+    }
+
+    if(furi_thread_get_state(instance->thread) != FuriThreadStateStopped) {
         printf("Can't start, furi application is running");
         printf("Can't start, furi application is running");
         return;
         return;
     }
     }
 
 
-    loader_instance->lock_semaphore++;
+    instance->lock_semaphore++;
     furi_hal_power_insomnia_enter();
     furi_hal_power_insomnia_enter();
-    loader_instance->current_app = flipper_app;
-    printf("Starting furi application %s", loader_instance->current_app->name);
-    furi_thread_set_name(loader_instance->thread, flipper_app->name);
-    furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size);
-    furi_thread_set_callback(loader_instance->thread, flipper_app->app);
-    furi_thread_start(loader_instance->thread);
+    instance->current_app = application;
+    printf("Starting: %s\r\n", instance->current_app->name);
+    furi_thread_set_name(instance->thread, application->name);
+    furi_thread_set_stack_size(instance->thread, application->stack_size);
+    furi_thread_set_callback(instance->thread, application->app);
+    furi_thread_start(instance->thread);
+}
+
+void loader_cli_list(Cli* cli, string_t args, Loader* instance) {
+    printf("Applications:\r\n");
+    for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
+        printf("\t%s\r\n", FLIPPER_APPS[i].name);
+    }
+
+    printf("Plugins:\r\n");
+    for(size_t i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
+        printf("\t%s\r\n", FLIPPER_PLUGINS[i].name);
+    }
+
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        printf("Debug:\r\n");
+        for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
+            printf("\t%s\r\n", FLIPPER_DEBUG_APPS[i].name);
+        }
+    }
+}
+
+void loader_cli(Cli* cli, string_t args, void* _ctx) {
+    furi_assert(_ctx);
+    Loader* instance = _ctx;
+
+    string_t cmd;
+    string_init(cmd);
+
+    do {
+        if(!args_read_string_and_trim(args, cmd)) {
+            loader_cli_print_usage();
+            break;
+        }
+
+        if(string_cmp_str(cmd, "list") == 0) {
+            loader_cli_list(cli, args, instance);
+            break;
+        }
+
+        if(string_cmp_str(cmd, "open") == 0) {
+            loader_cli_open(cli, args, instance);
+            break;
+        }
+
+        loader_cli_print_usage();
+    } while(false);
+
+    string_clear(cmd);
 }
 }
 
 
 LoaderStatus loader_start(Loader* instance, const char* name, const char* args) {
 LoaderStatus loader_start(Loader* instance, const char* name, const char* args) {
@@ -187,7 +277,10 @@ static Loader* loader_alloc() {
 
 
     instance->mutex = osMutexNew(NULL);
     instance->mutex = osMutexNew(NULL);
 
 
+#ifdef SRV_CLI
     instance->cli = furi_record_open("cli");
     instance->cli = furi_record_open("cli");
+    cli_add_command(instance->cli, "loader", CliCommandFlagDefault, loader_cli, instance);
+#endif
 
 
     instance->loader_thread = osThreadGetId();
     instance->loader_thread = osThreadGetId();
 
 
@@ -235,7 +328,9 @@ static Loader* loader_alloc() {
 static void loader_free(Loader* instance) {
 static void loader_free(Loader* instance) {
     furi_assert(instance);
     furi_assert(instance);
 
 
-    furi_record_close("cli");
+    if(instance->cli) {
+        furi_record_close("cli");
+    }
 
 
     osMutexDelete(instance->mutex);
     osMutexDelete(instance->mutex);
 
 
@@ -259,23 +354,10 @@ static void loader_free(Loader* instance) {
     instance = NULL;
     instance = NULL;
 }
 }
 
 
-static void loader_add_cli_command(FlipperApplication* app) {
-    string_t cli_name;
-    string_init_printf(cli_name, "app_%s", app->name);
-    cli_add_command(
-        loader_instance->cli,
-        string_get_cstr(cli_name),
-        CliCommandFlagDefault,
-        loader_cli_callback,
-        app);
-    string_clear(cli_name);
-}
-
 static void loader_build_menu() {
 static void loader_build_menu() {
     FURI_LOG_I(TAG, "Building main menu");
     FURI_LOG_I(TAG, "Building main menu");
     size_t i;
     size_t i;
     for(i = 0; i < FLIPPER_APPS_COUNT; i++) {
     for(i = 0; i < FLIPPER_APPS_COUNT; i++) {
-        loader_add_cli_command((FlipperApplication*)&FLIPPER_APPS[i]);
         menu_add_item(
         menu_add_item(
             loader_instance->primary_menu,
             loader_instance->primary_menu,
             FLIPPER_APPS[i].name,
             FLIPPER_APPS[i].name,
@@ -284,13 +366,15 @@ static void loader_build_menu() {
             loader_menu_callback,
             loader_menu_callback,
             (void*)&FLIPPER_APPS[i]);
             (void*)&FLIPPER_APPS[i]);
     }
     }
-    menu_add_item(
-        loader_instance->primary_menu,
-        "Plugins",
-        &A_Plugins_14,
-        i++,
-        loader_submenu_callback,
-        (void*)LoaderMenuViewPlugins);
+    if(FLIPPER_PLUGINS_COUNT != 0) {
+        menu_add_item(
+            loader_instance->primary_menu,
+            "Plugins",
+            &A_Plugins_14,
+            i++,
+            loader_submenu_callback,
+            (void*)LoaderMenuViewPlugins);
+    }
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
         menu_add_item(
         menu_add_item(
             loader_instance->primary_menu,
             loader_instance->primary_menu,
@@ -313,7 +397,6 @@ static void loader_build_submenu() {
     FURI_LOG_I(TAG, "Building plugins menu");
     FURI_LOG_I(TAG, "Building plugins menu");
     size_t i;
     size_t i;
     for(i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
     for(i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
-        loader_add_cli_command((FlipperApplication*)&FLIPPER_PLUGINS[i]);
         submenu_add_item(
         submenu_add_item(
             loader_instance->plugins_menu,
             loader_instance->plugins_menu,
             FLIPPER_PLUGINS[i].name,
             FLIPPER_PLUGINS[i].name,
@@ -324,7 +407,6 @@ static void loader_build_submenu() {
 
 
     FURI_LOG_I(TAG, "Building debug menu");
     FURI_LOG_I(TAG, "Building debug menu");
     for(i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
     for(i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
-        loader_add_cli_command((FlipperApplication*)&FLIPPER_DEBUG_APPS[i]);
         submenu_add_item(
         submenu_add_item(
             loader_instance->debug_menu,
             loader_instance->debug_menu,
             FLIPPER_DEBUG_APPS[i].name,
             FLIPPER_DEBUG_APPS[i].name,

+ 1 - 0
applications/loader/loader_i.h

@@ -3,6 +3,7 @@
 #include <furi.h>
 #include <furi.h>
 #include <furi-hal.h>
 #include <furi-hal.h>
 #include <cli/cli.h>
 #include <cli/cli.h>
+#include <lib/toolbox/args.h>
 
 
 #include <gui/view_dispatcher.h>
 #include <gui/view_dispatcher.h>
 
 

+ 3 - 1
applications/nfc/nfc_cli.c

@@ -3,11 +3,13 @@
 #include <furi.h>
 #include <furi.h>
 #include <furi-hal.h>
 #include <furi-hal.h>
 
 
-void nfc_cli_init() {
+void nfc_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
     cli_add_command(cli, "nfc_detect", CliCommandFlagDefault, nfc_cli_detect, NULL);
     cli_add_command(cli, "nfc_detect", CliCommandFlagDefault, nfc_cli_detect, NULL);
     cli_add_command(cli, "nfc_emulate", CliCommandFlagDefault, nfc_cli_emulate, NULL);
     cli_add_command(cli, "nfc_emulate", CliCommandFlagDefault, nfc_cli_emulate, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }
 
 
 void nfc_cli_detect(Cli* cli, string_t args, void* context) {
 void nfc_cli_detect(Cli* cli, string_t args, void* context) {

+ 1 - 1
applications/nfc/nfc_cli.h

@@ -2,7 +2,7 @@
 
 
 #include <cli/cli.h>
 #include <cli/cli.h>
 
 
-void nfc_cli_init();
+void nfc_on_system_start();
 
 
 void nfc_cli_detect(Cli* cli, string_t args, void* context);
 void nfc_cli_detect(Cli* cli, string_t args, void* context);
 
 

+ 3 - 1
applications/power/power_cli.c

@@ -42,7 +42,8 @@ void power_cli_ext(Cli* cli, string_t args, void* context) {
     }
     }
 }
 }
 
 
-void power_cli_init() {
+void power_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
 
 
     cli_add_command(cli, "poweroff", CliCommandFlagParallelSafe, power_cli_poweroff, NULL);
     cli_add_command(cli, "poweroff", CliCommandFlagParallelSafe, power_cli_poweroff, NULL);
@@ -53,4 +54,5 @@ void power_cli_init() {
     cli_add_command(cli, "power_ext", CliCommandFlagParallelSafe, power_cli_ext, NULL);
     cli_add_command(cli, "power_ext", CliCommandFlagParallelSafe, power_cli_ext, NULL);
 
 
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 1 - 1
applications/power/power_cli.h

@@ -1,3 +1,3 @@
 #pragma once
 #pragma once
 
 
-void power_cli_init();
+void power_on_system_start();

+ 5 - 3
applications/storage/storage-cli.c

@@ -432,7 +432,7 @@ static void storage_cli_md5(Cli* cli, string_t path) {
     furi_record_close("storage");
     furi_record_close("storage");
 }
 }
 
 
-static void storage_cli(Cli* cli, string_t args, void* context) {
+void storage_cli(Cli* cli, string_t args, void* context) {
     string_t cmd;
     string_t cmd;
     string_t path;
     string_t path;
     string_init(cmd);
     string_init(cmd);
@@ -521,7 +521,7 @@ static void storage_cli(Cli* cli, string_t args, void* context) {
     string_clear(cmd);
     string_clear(cmd);
 }
 }
 
 
-static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) {
+void storage_cli_factory_reset(Cli* cli, string_t args, void* context) {
     printf("All data will be lost. Are you sure (y/n)?\r\n");
     printf("All data will be lost. Are you sure (y/n)?\r\n");
     char c = cli_getc(cli);
     char c = cli_getc(cli);
     if(c == 'y' || c == 'Y') {
     if(c == 'y' || c == 'Y') {
@@ -533,10 +533,12 @@ static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) {
     }
     }
 }
 }
 
 
-void storage_cli_init() {
+void storage_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
     cli_add_command(cli, "storage", CliCommandFlagDefault, storage_cli, NULL);
     cli_add_command(cli, "storage", CliCommandFlagDefault, storage_cli, NULL);
     cli_add_command(
     cli_add_command(
         cli, "factory_reset", CliCommandFlagParallelSafe, storage_cli_factory_reset, NULL);
         cli, "factory_reset", CliCommandFlagParallelSafe, storage_cli_factory_reset, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 8 - 6
applications/subghz/subghz_cli.c

@@ -17,7 +17,7 @@
 #define SUBGHZ_FREQUENCY_RANGE_STR \
 #define SUBGHZ_FREQUENCY_RANGE_STR \
     "299999755...348000000 or 386999938...464000000 or 778999847...928000000"
     "299999755...348000000 or 386999938...464000000 or 778999847...928000000"
 
 
-static void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
+void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
     uint32_t frequency = 433920000;
     uint32_t frequency = 433920000;
 
 
     if(string_size(args)) {
     if(string_size(args)) {
@@ -60,7 +60,7 @@ static void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context
     furi_hal_power_suppress_charge_exit();
     furi_hal_power_suppress_charge_exit();
 }
 }
 
 
-static void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
+void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
     uint32_t frequency = 433920000;
     uint32_t frequency = 433920000;
 
 
     if(string_size(args)) {
     if(string_size(args)) {
@@ -100,7 +100,7 @@ static void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context
     furi_hal_subghz_sleep();
     furi_hal_subghz_sleep();
 }
 }
 
 
-static void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
+void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
     uint32_t frequency = 433920000;
     uint32_t frequency = 433920000;
     uint32_t key = 0x0074BADE;
     uint32_t key = 0x0074BADE;
     uint32_t repeat = 10;
     uint32_t repeat = 10;
@@ -191,7 +191,7 @@ static void subghz_cli_command_rx_text_callback(string_t text, void* context) {
     printf("%s", string_get_cstr(text));
     printf("%s", string_get_cstr(text));
 }
 }
 
 
-static void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
+void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     uint32_t frequency = 433920000;
     uint32_t frequency = 433920000;
 
 
     if(string_size(args)) {
     if(string_size(args)) {
@@ -530,7 +530,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) {
     printf("\r\nExit chat\r\n");
     printf("\r\nExit chat\r\n");
 }
 }
 
 
-static void subghz_cli_command(Cli* cli, string_t args, void* context) {
+void subghz_cli_command(Cli* cli, string_t args, void* context) {
     string_t cmd;
     string_t cmd;
     string_init(cmd);
     string_init(cmd);
 
 
@@ -561,7 +561,8 @@ static void subghz_cli_command(Cli* cli, string_t args, void* context) {
     string_clear(cmd);
     string_clear(cmd);
 }
 }
 
 
-void subghz_cli_init() {
+void subghz_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
 
 
     cli_add_command(
     cli_add_command(
@@ -573,4 +574,5 @@ void subghz_cli_init() {
     cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL);
     cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL);
 
 
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 1 - 1
applications/subghz/subghz_cli.h

@@ -2,4 +2,4 @@
 
 
 #include <cli/cli.h>
 #include <cli/cli.h>
 
 
-void subghz_cli_init();
+void subghz_on_system_start();

+ 3 - 1
applications/tests/test_index.c

@@ -78,10 +78,12 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) {
     furi_record_close("loader");
     furi_record_close("loader");
 }
 }
 
 
-void unit_tests_cli_init() {
+void unit_tests_on_system_start() {
+#ifdef SRV_CLI
     Cli* cli = furi_record_open("cli");
     Cli* cli = furi_record_open("cli");
 
 
     // We need to launch apps from tests, so we cannot lock loader
     // We need to launch apps from tests, so we cannot lock loader
     cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL);
     cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL);
     furi_record_close("cli");
     furi_record_close("cli");
+#endif
 }
 }

+ 0 - 2
lib/lib.mk

@@ -41,7 +41,6 @@ CFLAGS			+= -I$(LITTLEFS_DIR) -DLFS_CONFIG=lfs_config.h
 C_SOURCES		+= $(LITTLEFS_DIR)/lfs.c
 C_SOURCES		+= $(LITTLEFS_DIR)/lfs.c
 C_SOURCES		+= $(LITTLEFS_DIR)/lfs_util.c
 C_SOURCES		+= $(LITTLEFS_DIR)/lfs_util.c
 
 
-ifeq ($(APP_NFC), 1)
 ST25RFAL002_DIR	= $(LIB_DIR)/ST25RFAL002
 ST25RFAL002_DIR	= $(LIB_DIR)/ST25RFAL002
 CFLAGS			+= -I$(ST25RFAL002_DIR)
 CFLAGS			+= -I$(ST25RFAL002_DIR)
 CFLAGS			+= -I$(ST25RFAL002_DIR)/include
 CFLAGS			+= -I$(ST25RFAL002_DIR)/include
@@ -52,7 +51,6 @@ C_SOURCES		+= $(wildcard $(ST25RFAL002_DIR)/source/st25r3916/*.c)
 
 
 CFLAGS			+= -I$(LIB_DIR)/nfc_protocols
 CFLAGS			+= -I$(LIB_DIR)/nfc_protocols
 C_SOURCES		+= $(wildcard $(LIB_DIR)/nfc_protocols/*.c)
 C_SOURCES		+= $(wildcard $(LIB_DIR)/nfc_protocols/*.c)
-endif
 
 
 # callback connector (C to CPP) library
 # callback connector (C to CPP) library
 CFLAGS			+= -I$(LIB_DIR)/callback-connector
 CFLAGS			+= -I$(LIB_DIR)/callback-connector

+ 2 - 2
make/toolchain.mk

@@ -20,9 +20,9 @@ COMPACT ?= 0
 ifeq ($(DEBUG), 1)
 ifeq ($(DEBUG), 1)
 CFLAGS += -DFURI_DEBUG -DNDEBUG -Og -g
 CFLAGS += -DFURI_DEBUG -DNDEBUG -Og -g
 else ifeq ($(COMPACT), 1)
 else ifeq ($(COMPACT), 1)
-CFLAGS += -DFURI_NDEBUG -DNDEBUG -Os
+CFLAGS += -DFURI_NDEBUG -DNDEBUG -Os -g
 else
 else
-CFLAGS += -DFURI_NDEBUG -DNDEBUG -Og
+CFLAGS += -DFURI_NDEBUG -DNDEBUG -Og -g
 endif
 endif
 
 
 CFLAGS		+= -fdata-sections -ffunction-sections -fno-math-errno -fstack-usage -MMD -MP -MF"$(@:%.o=%.d)"
 CFLAGS		+= -fdata-sections -ffunction-sections -fno-math-errno -fstack-usage -MMD -MP -MF"$(@:%.o=%.d)"