Ray 3 лет назад
Родитель
Сommit
93c32ce8cb
7 измененных файлов с 188 добавлено и 80 удалено
  1. 1 0
      .gitignore
  2. 56 14
      cli_control.c
  3. 1 1
      cli_control.h
  4. 10 4
      cligui_main.c
  5. 2 54
      cligui_main_i.h
  6. 0 7
      events.h
  7. 118 0
      internal_defs.h

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+.vscode

+ 56 - 14
cli_control.c

@@ -4,11 +4,21 @@
 #include <cli/cli_i.h>
 #include <cli/cli_vcp.h>
 #include "cligui_main_i.h"
+#include <FreeRTOS.h>
 
 volatile bool gotCallbackSet = 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);
+}
 static size_t real_rx_handler(uint8_t* buffer, size_t size, uint32_t timeout) {
     size_t rx_cnt = 0;
     while(size > 0) {
@@ -22,34 +32,46 @@ static size_t real_rx_handler(uint8_t* buffer, size_t size, uint32_t timeout) {
     }
     return rx_cnt;
 }
-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);
-    furi_stream_buffer_send(tx_stream, buffer, size, FuriWaitForever);
+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 void session_init(void) {}
-static void session_deinit(void) {}
-static bool session_connected(void) {return true;}
+static void session_init(void) {
+}
+static void session_deinit(void) {
+}
+static bool session_connected(void) {
+    return true;
+}
 static CliSession session;
 void latch_tx_handler() {
     Cli* global_cli = furi_record_open(RECORD_CLI);
+
+    CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
+    cliThread = help_command->context;
+
     furi_thread_set_stdout_callback(tx_handler_stdout);
+    if(cliThread != NULL) {
+        ((FuriThread_internal*)cliThread)->output.write_callback = &tx_handler_stdout;
+    }
+
     rx_stream = furi_stream_buffer_alloc(128, 1);
     tx_stream = furi_stream_buffer_alloc(128, 1);
 
     session.tx = &tx_handler;
     session.rx = &real_rx_handler;
-    session.tx_stdout  = &tx_handler_stdout;
+    session.tx_stdout = &tx_handler_stdout;
     session.init = &session_init;
     session.deinit = &session_deinit;
     session.is_connected = &session_connected;
     cli_session_close(global_cli);
     cli_session_open(global_cli, &session);
-    // furi_stream_buffer_send(rx_stream, "help\r\n", 6, FuriWaitForever);
     // Unlock loader-lock
     Loader* loader = furi_record_open(RECORD_LOADER);
     Loader_internal* loader_i = (Loader_internal*)loader;
@@ -57,11 +79,31 @@ void latch_tx_handler() {
     furi_record_close(RECORD_CLI);
     furi_record_close(RECORD_LOADER);
 }
-void unlatch_tx_handler() {
+void unlatch_tx_handler(bool persist) {
     Cli* global_cli = furi_record_open(RECORD_CLI);
-    cli_session_close(global_cli);
+    // Stash cliThread if not null
+    if(cliThread != NULL) {
+        CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
+        help_command->context = cliThread;
+    }
+    // Switch to new session
+    if(persist) {
+        // Use dummy debug firmware function as is_connected
+        cli_vcp.is_connected = &furi_hal_version_do_i_belong_here;
+    } else {
+        // Send CTRL-C
+        char eot = 0x03;
+        furi_stream_buffer_send(rx_stream, &eot, 1, FuriWaitForever);
+    }
     cli_session_open(global_cli, &cli_vcp);
+    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);
-    furi_record_close(RECORD_CLI);
 }

+ 1 - 1
cli_control.h

@@ -3,6 +3,6 @@
 #include <furi.h>
 #include <furi_hal.h>
 extern void latch_tx_handler();
-extern void unlatch_tx_handler();
+extern void unlatch_tx_handler(bool persist);
 extern FuriStreamBuffer* tx_stream;
 extern FuriStreamBuffer* rx_stream;

+ 10 - 4
cligui_main.c

@@ -1,6 +1,5 @@
 #include "cligui_main_i.h"
 #include "cli_control.h"
-#include "events.h"
 #include "text_input.h"
 #include "console_output.h"
 
@@ -35,7 +34,7 @@ static void cligui_tick_event_cb(void* context) {
         if (furi_string_get_char(app->text_box_store, idx) == '\n') {
             idx++;
             break;
-        } 
+        }
         idx--;
     }
     text_input_set_header_text(app->text_input, furi_string_get_cstr(app->text_box_store) + idx);
@@ -43,9 +42,15 @@ static void cligui_tick_event_cb(void* context) {
 }
 
 ViewPortInputCallback prev_input_callback;
+volatile bool persistent_exit = false;
 static void input_callback_wrapper(InputEvent* event, void* context) {
     CliguiApp* app = context;
     if(event->type == InputTypeLong && event->key == InputKeyBack) {
+        persistent_exit = false;
+        view_dispatcher_stop(app->view_dispatcher);
+    }
+    if(event->type == InputTypeLong && event->key == InputKeyOk) {
+        persistent_exit = true;
         view_dispatcher_stop(app->view_dispatcher);
     }
     if(app->data->state == ViewTextInput) {
@@ -88,6 +93,7 @@ int32_t cligui_main(void* p) {
         cligui->view_dispatcher, ViewConsoleOutput, text_box_get_view(cligui->text_box));
     cligui->text_box_store = furi_string_alloc();
     furi_string_reserve(cligui->text_box_store, TEXT_BOX_STORE_SIZE);
+    furi_string_set_char(cligui->text_box_store, 0, 0);
     text_box_set_text(cligui->text_box, furi_string_get_cstr(cligui->text_box_store));
     text_box_set_focus(cligui->text_box, TextBoxFocusEnd);
 
@@ -107,8 +113,6 @@ int32_t cligui_main(void* p) {
 
     view_dispatcher_run(cligui->view_dispatcher);
 
-    unlatch_tx_handler();
-
     view_dispatcher_remove_view(cligui->view_dispatcher, ViewConsoleOutput);
     view_dispatcher_remove_view(cligui->view_dispatcher, ViewTextInput);
     text_box_free(cligui->text_box);
@@ -116,6 +120,8 @@ int32_t cligui_main(void* p) {
     text_input_free(cligui->text_input);
     view_dispatcher_free(cligui->view_dispatcher);
 
+    unlatch_tx_handler(persistent_exit);
+
     furi_record_close(RECORD_GUI);
 
     free(cligui->data);

+ 2 - 54
cligui_main_i.h

@@ -2,6 +2,7 @@
 
 #include <furi.h>
 #include <furi_hal.h>
+#include <furi_hal_version.h>
 #include <furi_hal_usb_cdc.h>
 #include <furi_hal_usb.h>
 #include <gui/gui.h>
@@ -10,64 +11,11 @@
 #include <gui/modules/text_input.h>
 #include <m-dict.h>
 #include <loader/loader.h>
-
-DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)
+#include "internal_defs.h"
 
 #define TEXT_BOX_STORE_SIZE (4096)
 #define TEXT_INPUT_STORE_SIZE (512)
 
-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;
-    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 {
-    FuriThreadId loader_thread;
-
-    const void* application;
-    FuriThread* application_thread;
-    char* application_arguments;
-
-    void* cli;
-    void* gui;
-
-    void* view_dispatcher;
-    void* primary_menu;
-    void* plugins_menu;
-    void* debug_menu;
-    void* settings_menu;
-
-    volatile uint8_t lock_count;
-
-    void* pubsub;
-} Loader_internal;
-
 typedef enum {
     ViewTextInput,
     ViewConsoleOutput,

+ 0 - 7
events.h

@@ -1,7 +0,0 @@
-#pragma once
-
-typedef enum {
-    RefreshConsoleOutput = 0,
-    StartConsole,
-    StartKeyboard,
-} CliguiCustomEvent;

+ 118 - 0
internal_defs.h

@@ -0,0 +1,118 @@
+#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>
+
+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;
+    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 {
+    FuriThreadId loader_thread;
+
+    const void* application;
+    FuriThread* application_thread;
+    char* application_arguments;
+
+    void* cli;
+    void* gui;
+
+    void* view_dispatcher;
+    void* primary_menu;
+    void* plugins_menu;
+    void* debug_menu;
+    void* settings_menu;
+
+    volatile uint8_t lock_count;
+
+    void* pubsub;
+} Loader_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;