MX 1 год назад
Родитель
Сommit
0528529130

+ 102 - 57
apps_broken_by_last_refactors/cli_bridge/cli_control.c

@@ -1,104 +1,149 @@
 #include "cli_control.h"
 
+#include <FreeRTOS.h>
 #include <cli/cli.h>
 #include <cli/cli_i.h>
 #include <cli/cli_vcp.h>
-#include "cligui_main_i.h"
-#include <FreeRTOS.h>
+#include <loader/loader.h>
+#include <loader/loader_i.h>
 
-volatile bool gotCallbackSet = false;
+FuriStreamBuffer* cli_tx_stream = NULL;
+FuriStreamBuffer* cli_rx_stream = NULL;
+
+static volatile bool restore_tx_stdout = false;
 
-FuriStreamBuffer* tx_stream;
-FuriStreamBuffer* rx_stream;
-static FuriThread* volatile cliThread = NULL;
-static void tx_handler_stdout(const char* buffer, size_t size) {
-    furi_stream_buffer_send(tx_stream, buffer, size, FuriWaitForever);
-}
 static void tx_handler(const uint8_t* buffer, size_t size) {
-    furi_thread_set_stdout_callback(tx_handler_stdout);
-    cliThread = furi_thread_get_current();
-    furi_stream_buffer_send(tx_stream, buffer, size, FuriWaitForever);
+    furi_stream_buffer_send(cli_tx_stream, buffer, size, FuriWaitForever);
 }
+
+static void tx_handler_stdout(const char* buffer, size_t size) {
+    tx_handler((const uint8_t*)buffer, size);
+}
+
 static size_t real_rx_handler(uint8_t* buffer, size_t size, uint32_t timeout) {
     size_t rx_cnt = 0;
     while(size > 0) {
         size_t batch_size = size;
         if(batch_size > 128) batch_size = 128;
-        size_t len = furi_stream_buffer_receive(rx_stream, buffer, batch_size, timeout);
+        size_t len = furi_stream_buffer_receive(cli_rx_stream, buffer, batch_size, timeout);
         if(len == 0) break;
         size -= len;
         buffer += len;
         rx_cnt += len;
     }
+    if(restore_tx_stdout) {
+        furi_thread_set_stdout_callback(cli_vcp.tx_stdout);
+    } else {
+        furi_thread_set_stdout_callback(tx_handler_stdout);
+    }
     return rx_cnt;
 }
 
-static CliCommand_internal* getInternalCliCommand(Cli* cli, const char* name) {
-    FuriString* target_command = furi_string_alloc();
-    furi_string_set_str(target_command, name);
-    CliCommand_internal* command =
-        CliCommandTree_internal_get(((Cli_internal*)cli)->commands, target_command);
-    furi_string_free(target_command);
-    return command;
-}
+static CliSession* session;
 
 static void session_init(void) {
 }
 static void session_deinit(void) {
+    free(session);
+    session = NULL;
 }
+
 static bool session_connected(void) {
     return true;
 }
-static CliSession session;
-void latch_tx_handler() {
+
+void clicontrol_hijack(size_t tx_size, size_t rx_size) {
+    if(cli_rx_stream != NULL && cli_tx_stream != NULL) {
+        return;
+    }
+
     Cli* global_cli = furi_record_open(RECORD_CLI);
 
-    CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
-    cliThread = help_command->context;
+    cli_rx_stream = furi_stream_buffer_alloc(rx_size, 1);
+    cli_tx_stream = furi_stream_buffer_alloc(tx_size, 1);
 
-    furi_thread_set_stdout_callback(tx_handler_stdout);
-    if(cliThread != NULL) {
-        ((FuriThread_internal*)cliThread)->output.write_callback = &tx_handler_stdout;
-    }
+    session = (CliSession*)malloc(sizeof(CliSession));
+    session->tx = &tx_handler;
+    session->rx = &real_rx_handler;
+    session->tx_stdout = &tx_handler_stdout;
+    session->init = &session_init;
+    session->deinit = &session_deinit;
+    session->is_connected = &session_connected;
 
-    rx_stream = furi_stream_buffer_alloc(128, 1);
-    tx_stream = furi_stream_buffer_alloc(128, 1);
+    CliCommandTree_it_t cmd_iterator;
+    for(CliCommandTree_it(cmd_iterator, global_cli->commands); !CliCommandTree_end_p(cmd_iterator);
+        CliCommandTree_next(cmd_iterator)) {
+        CliCommand* t = CliCommandTree_cref(cmd_iterator)->value_ptr;
+        // Move CliCommandFlagParallelSafe to another bit
+        t->flags ^=
+            ((t->flags & (CliCommandFlagParallelSafe << 8)) ^
+             ((t->flags & CliCommandFlagParallelSafe) << 8));
+        // Set parallel safe
+        t->flags |= CliCommandFlagParallelSafe;
+    }
 
-    session.tx = &tx_handler;
-    session.rx = &real_rx_handler;
-    session.tx_stdout = &tx_handler_stdout;
-    session.init = &session_init;
-    session.deinit = &session_deinit;
-    session.is_connected = &session_connected;
+    // Session switcharooney
+    FuriThreadStdoutWriteCallback prev_stdout = furi_thread_get_stdout_callback();
     cli_session_close(global_cli);
-    cli_session_open(global_cli, &session);
+    restore_tx_stdout = false;
+    cli_session_open(global_cli, session);
+    furi_thread_set_stdout_callback(prev_stdout);
+
     furi_record_close(RECORD_CLI);
 }
-void unlatch_tx_handler(bool persist) {
-    Cli* global_cli = furi_record_open(RECORD_CLI);
-    // Stash cliThread if not null
-    if(cliThread != NULL) {
-        CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
-        help_command->context = cliThread;
+
+void clicontrol_unhijack(bool persist) {
+    if(cli_rx_stream == NULL && cli_tx_stream == NULL) {
+        return;
+    }
+
+    // Consume remaining tx data
+    if(furi_stream_buffer_bytes_available(cli_tx_stream) > 0) {
+        char sink = 0;
+        while(!furi_stream_buffer_is_empty(cli_tx_stream)) {
+            furi_stream_buffer_receive(cli_tx_stream, &sink, 1, FuriWaitForever);
+        }
     }
-    // Switch to new session
+
+    Cli* global_cli = furi_record_open(RECORD_CLI);
+
     if(persist) {
-        // Use dummy debug firmware function as is_connected
+        // Don't trigger a terminal reset as the session switches
         cli_vcp.is_connected = &furi_hal_version_do_i_belong_here;
     } else {
-        // Send CTRL-C
+        // Send CTRL-C a few times
         char eot = 0x03;
-        furi_stream_buffer_send(rx_stream, &eot, 1, FuriWaitForever);
+        furi_stream_buffer_send(cli_rx_stream, &eot, 1, FuriWaitForever);
+        furi_stream_buffer_send(cli_rx_stream, &eot, 1, FuriWaitForever);
+        furi_stream_buffer_send(cli_rx_stream, &eot, 1, FuriWaitForever);
     }
+
+    // Restore command flags
+    CliCommandTree_it_t cmd_iterator;
+    for(CliCommandTree_it(cmd_iterator, global_cli->commands); !CliCommandTree_end_p(cmd_iterator);
+        CliCommandTree_next(cmd_iterator)) {
+        CliCommand* t = CliCommandTree_cref(cmd_iterator)->value_ptr;
+        t->flags ^=
+            (((t->flags & CliCommandFlagParallelSafe) >> 8) ^
+             ((t->flags & (CliCommandFlagParallelSafe << 8)) >> 8));
+    }
+
+    restore_tx_stdout = true; // Ready for next rx call
+
+    // Session switcharooney again
+    FuriThreadStdoutWriteCallback prev_stdout = furi_thread_get_stdout_callback();
+    cli_session_close(global_cli);
     cli_session_open(global_cli, &cli_vcp);
+    furi_thread_set_stdout_callback(prev_stdout);
     furi_record_close(RECORD_CLI);
-    // Unblock waiting rx handler
-    furi_stream_buffer_send(rx_stream, "_", 1, FuriWaitForever);
-    // Reconfigure stdout_callback to cli_vcp
-    if(cliThread != NULL) {
-        ((FuriThread_internal*)cliThread)->output.write_callback = cli_vcp.tx_stdout;
-    }
-    // At this point, all cli_vcp functions should be back.
-    furi_stream_buffer_free(rx_stream);
-    furi_stream_buffer_free(tx_stream);
+
+    // Unblock waiting rx handler, restore old cli_vcp.tx_stdout
+    furi_stream_buffer_send(cli_rx_stream, "_", 1, FuriWaitForever);
+
+    // At this point, all cli_vcp functions should be restored.
+
+    furi_stream_buffer_free(cli_rx_stream);
+    furi_stream_buffer_free(cli_tx_stream);
+    cli_rx_stream = NULL;
+    cli_tx_stream = NULL;
 }

+ 4 - 4
apps_broken_by_last_refactors/cli_bridge/cli_control.h

@@ -2,7 +2,7 @@
 
 #include <furi.h>
 #include <furi_hal.h>
-extern void latch_tx_handler();
-extern void unlatch_tx_handler(bool persist);
-extern FuriStreamBuffer* tx_stream;
-extern FuriStreamBuffer* rx_stream;
+extern void clicontrol_hijack(size_t tx_size, size_t rx_size);
+extern void clicontrol_unhijack(bool persist);
+extern FuriStreamBuffer* cli_tx_stream;
+extern FuriStreamBuffer* cli_rx_stream;

+ 12 - 27
apps_broken_by_last_refactors/cli_bridge/cligui_main.c

@@ -2,7 +2,6 @@
 #include "cli_control.h"
 #include "text_input.h"
 #include "console_output.h"
-#include <loader/loader_i.h>
 
 static bool cligui_custom_event_cb(void* context, uint32_t event) {
     UNUSED(event);
@@ -42,9 +41,9 @@ static void cligui_tick_event_cb(void* context) {
     UNUSED(app);
 }
 
-ViewPortInputCallback prev_input_callback;
 volatile bool persistent_exit = false;
-static void input_callback_wrapper(InputEvent* event, void* context) {
+static void input_callback(const void* event_ptr, void* context) {
+    InputEvent* event = (InputEvent*)event_ptr;
     CliguiApp* app = context;
     if(event->type == InputTypeLong && event->key == InputKeyBack) {
         persistent_exit = false;
@@ -61,34 +60,22 @@ static void input_callback_wrapper(InputEvent* event, void* context) {
     } else {
         console_output_input_handler(app, event);
     }
-    prev_input_callback(event, app->view_dispatcher);
 }
 
 int32_t cligui_main(void* p) {
     UNUSED(p);
-
-    // Unlock loader-lock and save app thread
-    FuriThread* temp_save_appthr;
-    Loader* loader = furi_record_open(RECORD_LOADER);
-    temp_save_appthr = loader->app.thread;
-    loader->app.thread = NULL;
-    furi_record_close(RECORD_LOADER);
-
     CliguiApp* cligui = malloc(sizeof(CliguiApp));
     cligui->data = malloc(sizeof(CliguiData));
 
-    latch_tx_handler();
-    cligui->data->streams.app_tx = rx_stream;
-    cligui->data->streams.app_rx = tx_stream;
+    clicontrol_hijack(512, 512);
+    cligui->data->streams.app_tx = cli_rx_stream;
+    cligui->data->streams.app_rx = cli_tx_stream;
 
     cligui->gui = furi_record_open(RECORD_GUI);
     cligui->view_dispatcher = view_dispatcher_alloc();
-    cligui->view_dispatcher_i = (ViewDispatcher_internal*)(cligui->view_dispatcher);
-    prev_input_callback =
-        ((ViewPort_internal*)cligui->view_dispatcher_i->view_port)->input_callback;
-    view_port_input_callback_set(
-        cligui->view_dispatcher_i->view_port, input_callback_wrapper, cligui);
-    view_dispatcher_enable_queue(cligui->view_dispatcher);
+    FuriPubSub* input_events = furi_record_open(RECORD_INPUT_EVENTS);
+    FuriPubSubSubscription* input_events_sub =
+        furi_pubsub_subscribe(input_events, input_callback, (void*)cligui);
     view_dispatcher_set_event_callback_context(cligui->view_dispatcher, cligui);
     view_dispatcher_set_custom_event_callback(cligui->view_dispatcher, cligui_custom_event_cb);
     view_dispatcher_set_navigation_event_callback(cligui->view_dispatcher, cligui_back_event_cb);
@@ -131,17 +118,15 @@ int32_t cligui_main(void* p) {
     text_input_free(cligui->text_input);
     view_dispatcher_free(cligui->view_dispatcher);
 
-    unlatch_tx_handler(persistent_exit);
+    clicontrol_unhijack(persistent_exit);
+
+    furi_pubsub_unsubscribe(input_events, input_events_sub);
 
     furi_record_close(RECORD_GUI);
+    furi_record_close(RECORD_INPUT_EVENTS);
 
     free(cligui->data);
     free(cligui);
 
-    // We restoring previous app thread here, we love kostily and velosipedy, bydlo kod forever!
-    loader = furi_record_open(RECORD_LOADER);
-    loader->app.thread = temp_save_appthr;
-    furi_record_close(RECORD_LOADER);
-
     return 0;
 }

+ 2 - 4
apps_broken_by_last_refactors/cli_bridge/cligui_main_i.h

@@ -11,9 +11,8 @@
 #include <gui/modules/text_input.h>
 #include <m-dict.h>
 #include <loader/loader.h>
-#include "internal_defs.h"
 
-#define TEXT_BOX_STORE_SIZE (4096)
+#define TEXT_BOX_STORE_SIZE   (4096)
 #define TEXT_INPUT_STORE_SIZE (512)
 
 typedef enum {
@@ -37,5 +36,4 @@ typedef struct {
     char text_input_store[TEXT_INPUT_STORE_SIZE + 1];
     TextInput* text_input;
     ViewDispatcher* view_dispatcher;
-    ViewDispatcher_internal* view_dispatcher_i;
-} CliguiApp;
+} CliguiApp;

+ 1 - 1
apps_broken_by_last_refactors/cli_bridge/console_output.c

@@ -9,4 +9,4 @@ void console_output_input_handler(CliguiApp* app, InputEvent* event) {
         char eot = 0x03;
         furi_stream_buffer_send(app->data->streams.app_tx, &eot, 1, FuriWaitForever);
     }
-}
+}

+ 0 - 101
apps_broken_by_last_refactors/cli_bridge/internal_defs.h

@@ -1,101 +0,0 @@
-#pragma once
-#include <furi.h>
-#include <furi_hal.h>
-#include <m-dict.h>
-#include <m-bptree.h>
-#include <m-array.h>
-#include <cli/cli.h>
-#include <gui/gui.h>
-#include <gui/view_dispatcher.h>
-#include <gui/modules/menu.h>
-#include <gui/modules/submenu.h>
-
-typedef struct {
-    FuriThreadStdoutWriteCallback write_callback;
-    FuriString* buffer;
-} FuriThreadStdout_internal;
-
-typedef struct {
-    bool is_service;
-    FuriThreadState state;
-    int32_t ret;
-
-    FuriThreadCallback callback;
-    void* context;
-
-    FuriThreadStateCallback state_callback;
-    void* state_context;
-
-    char* name;
-    configSTACK_DEPTH_TYPE stack_size;
-    FuriThreadPriority priority;
-
-    TaskHandle_t task_handle;
-    bool heap_trace_enabled;
-    size_t heap_size;
-
-    FuriThreadStdout_internal output;
-} FuriThread_internal;
-
-DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)
-typedef struct {
-    FuriMessageQueue* queue;
-    Gui* gui;
-    ViewPort* view_port;
-    ViewDict_t views;
-
-    View* current_view;
-
-    View* ongoing_input_view;
-    uint8_t ongoing_input;
-
-    ViewDispatcherCustomEventCallback custom_event_callback;
-    ViewDispatcherNavigationEventCallback navigation_event_callback;
-    ViewDispatcherTickEventCallback tick_event_callback;
-    uint32_t tick_period;
-    void* event_context;
-} ViewDispatcher_internal;
-
-typedef struct {
-    Gui* gui;
-    FuriMutex* mutex;
-    bool is_enabled;
-    ViewPortOrientation orientation;
-
-    uint8_t width;
-    uint8_t height;
-
-    ViewPortDrawCallback draw_callback;
-    void* draw_callback_context;
-
-    ViewPortInputCallback input_callback;
-    void* input_callback_context;
-} ViewPort_internal;
-
-typedef struct {
-    CliCallback callback;
-    void* context;
-    uint32_t flags;
-} CliCommand_internal;
-
-#define CLI_COMMANDS_TREE_RANK 4
-BPTREE_DEF2(
-    CliCommandTree_internal,
-    CLI_COMMANDS_TREE_RANK,
-    FuriString*,
-    FURI_STRING_OPLIST,
-    CliCommand_internal,
-    M_POD_OPLIST)
-
-#define M_OPL_CliCommandTree_internal_t() BPTREE_OPLIST(CliCommandTree_internal, M_POD_OPLIST)
-
-typedef struct {
-    CliCommandTree_internal_t commands;
-    void* mutex;
-    void* idle_sem;
-    void* last_line;
-    void* line;
-    void* session;
-
-    size_t cursor_position;
-} Cli_internal;

+ 1 - 1
apps_broken_by_last_refactors/cli_bridge/text_input.c

@@ -31,4 +31,4 @@ void text_input_input_handler(CliguiApp* app, InputEvent* event) {
         view_dispatcher_switch_to_view(app->view_dispatcher, ViewConsoleOutput);
         app->data->state = ViewConsoleOutput;
     }
-}
+}