|
@@ -4,11 +4,21 @@
|
|
|
#include <cli/cli_i.h>
|
|
#include <cli/cli_i.h>
|
|
|
#include <cli/cli_vcp.h>
|
|
#include <cli/cli_vcp.h>
|
|
|
#include "cligui_main_i.h"
|
|
#include "cligui_main_i.h"
|
|
|
|
|
+#include <FreeRTOS.h>
|
|
|
|
|
|
|
|
volatile bool gotCallbackSet = false;
|
|
volatile bool gotCallbackSet = false;
|
|
|
|
|
|
|
|
FuriStreamBuffer* tx_stream;
|
|
FuriStreamBuffer* tx_stream;
|
|
|
FuriStreamBuffer* rx_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) {
|
|
static size_t real_rx_handler(uint8_t* buffer, size_t size, uint32_t timeout) {
|
|
|
size_t rx_cnt = 0;
|
|
size_t rx_cnt = 0;
|
|
|
while(size > 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;
|
|
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;
|
|
static CliSession session;
|
|
|
void latch_tx_handler() {
|
|
void latch_tx_handler() {
|
|
|
Cli* global_cli = furi_record_open(RECORD_CLI);
|
|
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);
|
|
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);
|
|
rx_stream = furi_stream_buffer_alloc(128, 1);
|
|
|
tx_stream = furi_stream_buffer_alloc(128, 1);
|
|
tx_stream = furi_stream_buffer_alloc(128, 1);
|
|
|
|
|
|
|
|
session.tx = &tx_handler;
|
|
session.tx = &tx_handler;
|
|
|
session.rx = &real_rx_handler;
|
|
session.rx = &real_rx_handler;
|
|
|
- session.tx_stdout = &tx_handler_stdout;
|
|
|
|
|
|
|
+ session.tx_stdout = &tx_handler_stdout;
|
|
|
session.init = &session_init;
|
|
session.init = &session_init;
|
|
|
session.deinit = &session_deinit;
|
|
session.deinit = &session_deinit;
|
|
|
session.is_connected = &session_connected;
|
|
session.is_connected = &session_connected;
|
|
|
cli_session_close(global_cli);
|
|
cli_session_close(global_cli);
|
|
|
cli_session_open(global_cli, &session);
|
|
cli_session_open(global_cli, &session);
|
|
|
- // furi_stream_buffer_send(rx_stream, "help\r\n", 6, FuriWaitForever);
|
|
|
|
|
// Unlock loader-lock
|
|
// Unlock loader-lock
|
|
|
Loader* loader = furi_record_open(RECORD_LOADER);
|
|
Loader* loader = furi_record_open(RECORD_LOADER);
|
|
|
Loader_internal* loader_i = (Loader_internal*)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_CLI);
|
|
|
furi_record_close(RECORD_LOADER);
|
|
furi_record_close(RECORD_LOADER);
|
|
|
}
|
|
}
|
|
|
-void unlatch_tx_handler() {
|
|
|
|
|
|
|
+void unlatch_tx_handler(bool persist) {
|
|
|
Cli* global_cli = furi_record_open(RECORD_CLI);
|
|
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);
|
|
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(rx_stream);
|
|
|
furi_stream_buffer_free(tx_stream);
|
|
furi_stream_buffer_free(tx_stream);
|
|
|
- furi_record_close(RECORD_CLI);
|
|
|
|
|
}
|
|
}
|