Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FL-3928] CLI rewrite #4023

Open
wants to merge 47 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
bf7fefc
feat: FuriThread stdin
portasynthinca3 Oct 31, 2024
a9d3264
Merge branch 'dev' into portasynthinca3/3927-thread-stdin
portasynthinca3 Oct 31, 2024
4c59243
ci: fix f18
portasynthinca3 Oct 31, 2024
9f2e934
Merge branch 'dev' into portasynthinca3/3927-thread-stdin
portasynthinca3 Nov 5, 2024
f1eb60b
feat: stdio callback context
portasynthinca3 Nov 7, 2024
da187fe
Merge branch 'dev' into portasynthinca3/3927-thread-stdin
portasynthinca3 Nov 7, 2024
a4a7a41
feat: FuriPipe
portasynthinca3 Nov 7, 2024
004e3a6
POTENTIALLY EXPLOSIVE pipe welding
portasynthinca3 Nov 8, 2024
920a3e9
fix: non-explosive welding
portasynthinca3 Nov 11, 2024
f792fde
Revert welding
portasynthinca3 Nov 12, 2024
1c9dbb3
docs: furi_pipe
portasynthinca3 Nov 12, 2024
bd28387
feat: pipe event loop integration
portasynthinca3 Nov 12, 2024
acf307d
update f18 sdk
portasynthinca3 Nov 12, 2024
2bcc3c4
f18
portasynthinca3 Nov 12, 2024
af7ff81
docs: make doxygen happy
portasynthinca3 Nov 12, 2024
857ad33
fix: event loop not triggering when pipe attached to stdio
portasynthinca3 Nov 13, 2024
bc9223a
fix: partial stdout in pipe
portasynthinca3 Nov 13, 2024
dac9c00
allow simultaneous in and out subscription in event loop
portasynthinca3 Nov 13, 2024
8837c8b
feat: vcp i/o
portasynthinca3 Nov 13, 2024
20ce18f
feat: cli ansi stuffs and history
portasynthinca3 Nov 14, 2024
1b31e70
feat: more line editing
portasynthinca3 Nov 15, 2024
82169a7
working but slow cli rewrite
portasynthinca3 Nov 28, 2024
fa1919c
restore previous speed after 4 days of debugging 🥲
portasynthinca3 Nov 28, 2024
bd82671
fix: cli_app_should_stop
portasynthinca3 Nov 28, 2024
34c6566
fix: cli and event_loop memory leaks
portasynthinca3 Nov 28, 2024
a346d8c
style: remove commented out code
portasynthinca3 Nov 29, 2024
c3f7825
ci: fix pvs warnings
portasynthinca3 Nov 29, 2024
b0b73c0
fix: unit tests, event_loop crash
portasynthinca3 Dec 2, 2024
8e05df6
ci: fix build
portasynthinca3 Dec 3, 2024
789e337
ci: silence pvs warning
portasynthinca3 Dec 3, 2024
2e1d236
feat: cli gpio
portasynthinca3 Dec 3, 2024
1280a8e
ci: fix formatting
portasynthinca3 Dec 3, 2024
9d34069
Fix memory leak during event loop unsubscription
gsurkov Dec 4, 2024
7a69000
Event better memory leak fix
gsurkov Dec 4, 2024
da047a3
feat: cli completions
portasynthinca3 Dec 7, 2024
824b644
Merge remote-tracking branch 'origin/dev' into portasynthinca3/3928-c…
portasynthinca3 Dec 24, 2024
c8e0a55
Merge branch 'dev' into portasynthinca3/3928-cli-threads
portasynthinca3 Dec 24, 2024
daf8ad7
merge fixups
portasynthinca3 Dec 24, 2024
58bd664
temporarily exclude speaker_debug app
portasynthinca3 Dec 24, 2024
0916aeb
pvs and unit tests fixups
portasynthinca3 Dec 24, 2024
82c1e71
feat: commands in fals
portasynthinca3 Dec 25, 2024
c88891e
move commands out of flash, code cleanup
portasynthinca3 Jan 9, 2025
1a54a00
ci: fix errors
portasynthinca3 Jan 9, 2025
c316a9f
fix: run commands in buffer when stopping session
portasynthinca3 Jan 9, 2025
c7c397b
Merge branch 'dev' into portasynthinca3/3928-cli-threads
skotopes Jan 16, 2025
a1d5239
speedup cli file transfer
portasynthinca3 Feb 4, 2025
1dce569
fix f18
portasynthinca3 Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions applications/debug/speaker_debug/speaker_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <music_worker/music_worker.h>
#include <cli/cli.h>
#include <toolbox/args.h>
#include <toolbox/pipe.h>

#define TAG "SpeakerDebug"

Expand Down Expand Up @@ -37,8 +38,8 @@ static void speaker_app_free(SpeakerDebugApp* app) {
free(app);
}

static void speaker_app_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
static void speaker_app_cli(PipeSide* pipe, FuriString* args, void* context) {
UNUSED(pipe);

SpeakerDebugApp* app = (SpeakerDebugApp*)context;
SpeakerDebugAppMessage message;
Expand Down Expand Up @@ -95,7 +96,7 @@ static void speaker_app_run(SpeakerDebugApp* app, const char* arg) {
return;
}

cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagParallelSafe, speaker_app_cli, app);
cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagDefault, speaker_app_cli, app);

SpeakerDebugAppMessage message;
FuriStatus status;
Expand Down
2 changes: 1 addition & 1 deletion applications/debug/unit_tests/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ App(
entry_point="unit_tests_on_system_start",
sources=["unit_tests.c", "test_runner.c", "unit_test_api_table.cpp"],
cdefines=["APP_UNIT_TESTS"],
requires=["system_settings", "subghz_start"],
requires=["system_settings", "cli_subghz"],
provides=["delay_test"],
resources="resources",
order=100,
Expand Down
9 changes: 5 additions & 4 deletions applications/debug/unit_tests/test_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <cli/cli.h>
#include <toolbox/path.h>
#include <toolbox/pipe.h>
#include <loader/loader.h>
#include <storage/storage.h>
#include <notification/notification_messages.h>
Expand All @@ -25,7 +26,7 @@ struct TestRunner {
NotificationApp* notification;

// Temporary used things
Cli* cli;
PipeSide* pipe;
FuriString* args;

// ELF related stuff
Expand All @@ -38,14 +39,14 @@ struct TestRunner {
int minunit_status;
};

TestRunner* test_runner_alloc(Cli* cli, FuriString* args) {
TestRunner* test_runner_alloc(PipeSide* pipe, FuriString* args) {
TestRunner* instance = malloc(sizeof(TestRunner));

instance->storage = furi_record_open(RECORD_STORAGE);
instance->loader = furi_record_open(RECORD_LOADER);
instance->notification = furi_record_open(RECORD_NOTIFICATION);

instance->cli = cli;
instance->pipe = pipe;
instance->args = args;

instance->composite_resolver = composite_api_resolver_alloc();
Expand Down Expand Up @@ -147,7 +148,7 @@ static void test_runner_run_internal(TestRunner* instance) {
}

while(true) {
if(cli_cmd_interrupt_received(instance->cli)) {
if(cli_app_should_stop(instance->pipe)) {
break;
}

Expand Down
8 changes: 4 additions & 4 deletions applications/debug/unit_tests/test_runner.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#pragma once

#include <furi.h>
#include <toolbox/pipe.h>

typedef struct TestRunner TestRunner;
typedef struct Cli Cli;

TestRunner* test_runner_alloc(Cli* cli, FuriString* args);
TestRunner* test_runner_alloc(PipeSide* pipe, FuriString* args);

void test_runner_free(TestRunner* isntance);
void test_runner_free(TestRunner* instance);

void test_runner_run(TestRunner* isntance);
void test_runner_run(TestRunner* instance);
16 changes: 9 additions & 7 deletions applications/debug/unit_tests/tests/furi/furi_stdio_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ static size_t mock_in_cb(char* buffer, size_t size, FuriWait wait, void* context
}

void test_stdin(void) {
FuriThreadStdinReadCallback in_cb = furi_thread_get_stdin_callback();
FuriThreadStdinReadCallback in_cb;
void* in_ctx;
furi_thread_get_stdin_callback(&in_cb, &in_ctx);
furi_thread_set_stdin_callback(mock_in_cb, CONTEXT_MAGIC);
char buf[256];

Expand Down Expand Up @@ -63,14 +65,14 @@ void test_stdin(void) {
fgets(buf, sizeof(buf), stdin);
mu_assert_string_eq(" World!\n", buf);

furi_thread_set_stdin_callback(in_cb, CONTEXT_MAGIC);
furi_thread_set_stdin_callback(in_cb, in_ctx);
}

// stdout

static FuriString* mock_out;
FuriThreadStdoutWriteCallback original_out_cb;

static FuriThreadStdoutWriteCallback original_out_cb;
static void* original_out_ctx;
static void mock_out_cb(const char* data, size_t size, void* context) {
furi_check(context == CONTEXT_MAGIC);
// there's no furi_string_cat_strn :(
Expand All @@ -83,15 +85,15 @@ static void assert_and_clear_mock_out(const char* expected) {
// return the original stdout callback for the duration of the check
// if the check fails, we don't want the error to end up in our buffer,
// we want to be able to see it!
furi_thread_set_stdout_callback(original_out_cb, CONTEXT_MAGIC);
furi_thread_set_stdout_callback(original_out_cb, original_out_ctx);
mu_assert_string_eq(expected, furi_string_get_cstr(mock_out));
furi_thread_set_stdout_callback(mock_out_cb, CONTEXT_MAGIC);

furi_string_reset(mock_out);
}

void test_stdout(void) {
original_out_cb = furi_thread_get_stdout_callback();
furi_thread_get_stdout_callback(&original_out_cb, &original_out_ctx);
furi_thread_set_stdout_callback(mock_out_cb, CONTEXT_MAGIC);
mock_out = furi_string_alloc();

Expand All @@ -104,5 +106,5 @@ void test_stdout(void) {
assert_and_clear_mock_out("Hello!");

furi_string_free(mock_out);
furi_thread_set_stdout_callback(original_out_cb, CONTEXT_MAGIC);
furi_thread_set_stdout_callback(original_out_cb, original_out_ctx);
}
5 changes: 0 additions & 5 deletions applications/debug/unit_tests/tests/storage/storage_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,11 +521,6 @@ MU_TEST(test_storage_data_path) {
// check that appsdata folder exists
mu_check(storage_dir_exists(storage, APPS_DATA_PATH));

// check that cli folder exists
mu_check(storage_dir_exists(storage, APPSDATA_APP_PATH("cli")));

storage_simply_remove(storage, APPSDATA_APP_PATH("cli"));

furi_record_close(RECORD_STORAGE);
}

Expand Down
8 changes: 4 additions & 4 deletions applications/debug/unit_tests/unit_tests.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#include <furi.h>
#include <cli/cli.h>
#include <toolbox/pipe.h>

#include "test_runner.h"

void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
void unit_tests_cli(PipeSide* pipe, FuriString* args, void* context) {
UNUSED(context);

TestRunner* test_runner = test_runner_alloc(cli, args);
TestRunner* test_runner = test_runner_alloc(pipe, args);
test_runner_run(test_runner);
test_runner_free(test_runner);
}

void unit_tests_on_system_start(void) {
#ifdef SRV_CLI
Cli* cli = furi_record_open(RECORD_CLI);
cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL);
cli_add_command(cli, "unit_tests", CliCommandFlagDefault, unit_tests_cli, NULL);
furi_record_close(RECORD_CLI);
#endif
}
7 changes: 1 addition & 6 deletions applications/main/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ App(
name="On start hooks",
apptype=FlipperAppType.METAPACKAGE,
provides=[
"ibutton_start",
"onewire_start",
"subghz_start",
"infrared_start",
"lfrfid_start",
"nfc_start",
"cli",
],
)
24 changes: 12 additions & 12 deletions applications/main/gpio/usb_uart_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ static void usb_uart_on_irq_rx_dma_cb(
static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
furi_hal_usb_unlock();
if(vcp_ch == 0) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_close(cli);
furi_record_close(RECORD_CLI);
CliVcp* cli_vcp = furi_record_open(RECORD_CLI_VCP);
cli_vcp_disable(cli_vcp);
furi_record_close(RECORD_CLI_VCP);
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
} else {
furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true);
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_open(cli, &cli_vcp);
furi_record_close(RECORD_CLI);
CliVcp* cli_vcp = furi_record_open(RECORD_CLI_VCP);
cli_vcp_enable(cli_vcp);
furi_record_close(RECORD_CLI_VCP);
}
furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart);
}
Expand All @@ -123,9 +123,9 @@ static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
UNUSED(usb_uart);
furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL);
if(vcp_ch != 0) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_close(cli);
furi_record_close(RECORD_CLI);
CliVcp* cli_vcp = furi_record_open(RECORD_CLI_VCP);
cli_vcp_disable(cli_vcp);
furi_record_close(RECORD_CLI_VCP);
}
}

Expand Down Expand Up @@ -308,9 +308,9 @@ static int32_t usb_uart_worker(void* context) {

furi_hal_usb_unlock();
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_open(cli, &cli_vcp);
furi_record_close(RECORD_CLI);
CliVcp* cli_vcp = furi_record_open(RECORD_CLI_VCP);
cli_vcp_enable(cli_vcp);
furi_record_close(RECORD_CLI_VCP);

return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions applications/main/ibutton/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ App(
)

App(
appid="ibutton_start",
apptype=FlipperAppType.STARTUP,
appid="cli_ikey",
targets=["f7"],
entry_point="ibutton_on_system_start",
apptype=FlipperAppType.PLUGIN,
entry_point="cli_ikey_ep",
requires=["cli"],
sources=["ibutton_cli.c"],
order=60,
)
39 changes: 14 additions & 25 deletions applications/main/ibutton/ibutton_cli.c
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
#include <furi.h>
#include <furi_hal.h>

#include <cli/cli.h>
#include <cli/cli_commands.h>
#include <toolbox/args.h>
#include <toolbox/pipe.h>

#include <ibutton/ibutton_key.h>
#include <ibutton/ibutton_worker.h>
#include <ibutton/ibutton_protocols.h>

static void ibutton_cli(Cli* cli, FuriString* args, void* context);

// app cli function
void ibutton_on_system_start(void) {
#ifdef SRV_CLI
Cli* cli = furi_record_open(RECORD_CLI);
cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli);
furi_record_close(RECORD_CLI);
#else
UNUSED(ibutton_cli);
#endif
}

static void ibutton_cli_print_usage(void) {
printf("Usage:\r\n");
printf("ikey read\r\n");
Expand Down Expand Up @@ -92,7 +80,7 @@ static void ibutton_cli_worker_read_cb(void* context) {
furi_event_flag_set(event, EVENT_FLAG_IBUTTON_COMPLETE);
}

static void ibutton_cli_read(Cli* cli) {
static void ibutton_cli_read(PipeSide* pipe) {
iButtonProtocols* protocols = ibutton_protocols_alloc();
iButtonWorker* worker = ibutton_worker_alloc(protocols);
iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
Expand All @@ -113,7 +101,7 @@ static void ibutton_cli_read(Cli* cli) {
break;
}

if(cli_cmd_interrupt_received(cli)) break;
if(cli_app_should_stop(pipe)) break;
}

ibutton_worker_stop(worker);
Expand All @@ -138,7 +126,7 @@ static void ibutton_cli_worker_write_cb(void* context, iButtonWorkerWriteResult
furi_event_flag_set(write_context->event, EVENT_FLAG_IBUTTON_COMPLETE);
}

void ibutton_cli_write(Cli* cli, FuriString* args) {
void ibutton_cli_write(PipeSide* pipe, FuriString* args) {
iButtonProtocols* protocols = ibutton_protocols_alloc();
iButtonWorker* worker = ibutton_worker_alloc(protocols);
iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
Expand Down Expand Up @@ -181,7 +169,7 @@ void ibutton_cli_write(Cli* cli, FuriString* args) {
}
}

if(cli_cmd_interrupt_received(cli)) break;
if(cli_app_should_stop(pipe)) break;
}
} while(false);

Expand All @@ -195,7 +183,7 @@ void ibutton_cli_write(Cli* cli, FuriString* args) {
furi_event_flag_free(write_context.event);
}

void ibutton_cli_emulate(Cli* cli, FuriString* args) {
void ibutton_cli_emulate(PipeSide* pipe, FuriString* args) {
iButtonProtocols* protocols = ibutton_protocols_alloc();
iButtonWorker* worker = ibutton_worker_alloc(protocols);
iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
Expand All @@ -214,7 +202,7 @@ void ibutton_cli_emulate(Cli* cli, FuriString* args) {

ibutton_worker_emulate_start(worker, key);

while(!cli_cmd_interrupt_received(cli)) {
while(!cli_app_should_stop(pipe)) {
furi_delay_ms(100);
};

Expand All @@ -228,8 +216,7 @@ void ibutton_cli_emulate(Cli* cli, FuriString* args) {
ibutton_protocols_free(protocols);
}

void ibutton_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
static void execute(PipeSide* pipe, FuriString* args, void* context) {
UNUSED(context);
FuriString* cmd;
cmd = furi_string_alloc();
Expand All @@ -241,14 +228,16 @@ void ibutton_cli(Cli* cli, FuriString* args, void* context) {
}

if(furi_string_cmp_str(cmd, "read") == 0) {
ibutton_cli_read(cli);
ibutton_cli_read(pipe);
} else if(furi_string_cmp_str(cmd, "write") == 0) {
ibutton_cli_write(cli, args);
ibutton_cli_write(pipe, args);
} else if(furi_string_cmp_str(cmd, "emulate") == 0) {
ibutton_cli_emulate(cli, args);
ibutton_cli_emulate(pipe, args);
} else {
ibutton_cli_print_usage();
}

furi_string_free(cmd);
}

CLI_COMMAND_INTERFACE(ikey, execute, CliCommandFlagDefault, 1024);
8 changes: 4 additions & 4 deletions applications/main/infrared/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ App(
)

App(
appid="infrared_start",
apptype=FlipperAppType.STARTUP,
appid="cli_ir",
targets=["f7"],
entry_point="infrared_on_system_start",
apptype=FlipperAppType.PLUGIN,
entry_point="cli_ir_ep",
requires=["cli"],
sources=[
"infrared_cli.c",
"infrared_brute_force.c",
"infrared_signal.c",
],
order=20,
)
Loading
Loading