From cfc64ddc7667504c41198cf5698c686fee42a8ef Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Wed, 8 Oct 2025 13:49:04 +0200 Subject: [PATCH 1/2] shell: Add user data argument to shell_set_bypass Allow passing some context to the shell bypass callback function by providing a void pointer user data argument. Signed-off-by: Pieter De Gendt --- drivers/can/can_shell.c | 8 +++++--- drivers/flash/flash_shell.c | 6 ++++-- include/zephyr/shell/shell.h | 9 +++++++-- samples/subsys/shell/shell_module/src/main.c | 6 ++++-- subsys/net/lib/shell/ping.c | 7 ++++--- .../net/lib/tls_credentials/tls_credentials_shell.c | 11 +++++++---- subsys/shell/modules/devmem_service.c | 6 ++++-- subsys/shell/shell.c | 6 ++++-- 8 files changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index eb257f027efe4..982a790c6ce29 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -74,11 +74,13 @@ static bool can_device_check(const struct device *dev) } #ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY -static void can_shell_dummy_bypass_cb(const struct shell *sh, uint8_t *data, size_t len) +static void can_shell_dummy_bypass_cb(const struct shell *sh, uint8_t *data, size_t len, + void *user_data) { ARG_UNUSED(sh); ARG_UNUSED(data); ARG_UNUSED(len); + ARG_UNUSED(user_data); } #endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ @@ -90,7 +92,7 @@ static void can_shell_print_frame(const struct shell *sh, const struct device *d #ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY /* Bypass the shell to avoid breaking up the line containing the frame */ - shell_set_bypass(sh, can_shell_dummy_bypass_cb); + shell_set_bypass(sh, can_shell_dummy_bypass_cb, NULL); #endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ #ifdef CONFIG_CAN_RX_TIMESTAMP @@ -132,7 +134,7 @@ static void can_shell_print_frame(const struct shell *sh, const struct device *d shell_fprintf_normal(sh, "\n"); #ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY - shell_set_bypass(sh, NULL); + shell_set_bypass(sh, NULL, NULL); #endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ } diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index 4770a87a33c72..b5d3da86baec5 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -617,17 +617,19 @@ static int set_bypass(const struct shell *sh, shell_bypass_cb_t bypass) shell_print(sh, "Loading..."); } - shell_set_bypass(sh, bypass); + shell_set_bypass(sh, bypass, NULL); return 0; } -static void bypass_cb(const struct shell *sh, uint8_t *recv, size_t len) +static void bypass_cb(const struct shell *sh, uint8_t *recv, size_t len, void *user_data) { uint32_t left_to_read = flash_load_total - flash_load_written - flash_load_boff; uint32_t to_copy = MIN(len, left_to_read); uint32_t copied = 0; + ARG_UNUSED(user_data); + while (copied < to_copy) { uint32_t buf_copy = MIN(to_copy, flash_load_buf_size - flash_load_boff); diff --git a/include/zephyr/shell/shell.h b/include/zephyr/shell/shell.h index 1084c929f75ce..7274b650180c6 100644 --- a/include/zephyr/shell/shell.h +++ b/include/zephyr/shell/shell.h @@ -789,7 +789,8 @@ typedef void (*shell_uninit_cb_t)(const struct shell *sh, int res); */ typedef void (*shell_bypass_cb_t)(const struct shell *sh, uint8_t *data, - size_t len); + size_t len, + void *user_data); struct shell_transport; @@ -990,6 +991,9 @@ struct shell_ctx { /** When bypass is set, all incoming data is passed to the callback. */ shell_bypass_cb_t bypass; + /** When bypass is set, this user data pointer is passed to the callback. */ + void *bypass_user_data; + /*!< Logging level for a backend. */ uint32_t log_level; @@ -1364,8 +1368,9 @@ int shell_set_root_cmd(const char *cmd); * * @param[in] sh Pointer to the shell instance. * @param[in] bypass Bypass callback or null to disable. + * @param[in] user_data Bypass callback user data. */ -void shell_set_bypass(const struct shell *sh, shell_bypass_cb_t bypass); +void shell_set_bypass(const struct shell *sh, shell_bypass_cb_t bypass, void *user_data); /** @brief Get shell readiness to execute commands. * diff --git a/samples/subsys/shell/shell_module/src/main.c b/samples/subsys/shell/shell_module/src/main.c index 97297b11e10b7..4df37646026c7 100644 --- a/samples/subsys/shell/shell_module/src/main.c +++ b/samples/subsys/shell/shell_module/src/main.c @@ -255,7 +255,7 @@ static int set_bypass(const struct shell *sh, shell_bypass_cb_t bypass) in_use = true; } - shell_set_bypass(sh, bypass); + shell_set_bypass(sh, bypass, NULL); return 0; } @@ -263,11 +263,13 @@ static int set_bypass(const struct shell *sh, shell_bypass_cb_t bypass) #define CHAR_1 0x18 #define CHAR_2 0x11 -static void bypass_cb(const struct shell *sh, uint8_t *data, size_t len) +static void bypass_cb(const struct shell *sh, uint8_t *data, size_t len, void *user_data) { static uint8_t tail; bool escape = false; + ARG_UNUSED(user_data); + /* Check if escape criteria is met. */ if (tail == CHAR_1 && data[0] == CHAR_2) { escape = true; diff --git a/subsys/net/lib/shell/ping.c b/subsys/net/lib/shell/ping.c index 97271664136ec..308953db6be43 100644 --- a/subsys/net/lib/shell/ping.c +++ b/subsys/net/lib/shell/ping.c @@ -231,7 +231,7 @@ static int parse_arg(size_t *i, size_t argc, char *argv[]) static void ping_cleanup(struct ping_context *ctx) { (void)net_icmp_cleanup_ctx(&ctx->icmp); - shell_set_bypass(ctx->sh, NULL); + shell_set_bypass(ctx->sh, NULL, NULL); } static void ping_done(struct ping_context *ctx) @@ -286,9 +286,10 @@ static void ping_work(struct k_work *work) #define ASCII_CTRL_C 0x03 -static void ping_bypass(const struct shell *sh, uint8_t *data, size_t len) +static void ping_bypass(const struct shell *sh, uint8_t *data, size_t len, void *user_data) { ARG_UNUSED(sh); + ARG_UNUSED(user_data); for (size_t i = 0; i < len; i++) { if (data[i] == ASCII_CTRL_C) { @@ -481,7 +482,7 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[]) PR("PING %s\n", host); - shell_set_bypass(sh, ping_bypass); + shell_set_bypass(sh, ping_bypass, NULL); k_work_reschedule(&ping_ctx.work, K_NO_WAIT); return 0; diff --git a/subsys/net/lib/tls_credentials/tls_credentials_shell.c b/subsys/net/lib/tls_credentials/tls_credentials_shell.c index fe27565fbb7dd..9736715d477a9 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_shell.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_shell.c @@ -517,12 +517,15 @@ static int tls_cred_cmd_add(const struct shell *sh, size_t argc, char *argv[]) #define ASCII_CTRL_C 0x03 -static void tls_cred_cmd_load_bypass(const struct shell *sh, uint8_t *data, size_t len) +static void tls_cred_cmd_load_bypass(const struct shell *sh, uint8_t *data, size_t len, + void *user_data) { bool terminate = false; int res; size_t write_len = len; + ARG_UNUSED(user_data); + for (size_t i = 0; i < len; i++) { if (data[i] == ASCII_CTRL_C) { write_len = i; @@ -533,7 +536,7 @@ static void tls_cred_cmd_load_bypass(const struct shell *sh, uint8_t *data, size res = cred_buf_write(data, write_len); if (res == -ENOMEM) { - shell_set_bypass(sh, NULL); + shell_set_bypass(sh, NULL, NULL); shell_fprintf(sh, SHELL_ERROR, "Not enough room in credential buffer for " "provided data. Increase " "CONFIG_TLS_CREDENTIALS_SHELL_CRED_BUF_SIZE.\n"); @@ -542,7 +545,7 @@ static void tls_cred_cmd_load_bypass(const struct shell *sh, uint8_t *data, size } if (terminate) { - shell_set_bypass(sh, NULL); + shell_set_bypass(sh, NULL, NULL); shell_fprintf(sh, SHELL_NORMAL, "Stored %d bytes.\n", cred_written); } } @@ -561,7 +564,7 @@ static int tls_cred_cmd_buf_load(const struct shell *sh, size_t argc, char *argv shell_clear_cred_buf(sh); shell_fprintf(sh, SHELL_NORMAL, "Input credential, finish with CTRL+C.\n"); - shell_set_bypass(sh, tls_cred_cmd_load_bypass); + shell_set_bypass(sh, tls_cred_cmd_load_bypass, NULL); return 0; } diff --git a/subsys/shell/modules/devmem_service.c b/subsys/shell/modules/devmem_service.c index 1e4932ae10039..786642a3367a3 100644 --- a/subsys/shell/modules/devmem_service.c +++ b/subsys/shell/modules/devmem_service.c @@ -175,17 +175,19 @@ static int set_bypass(const struct shell *sh, shell_bypass_cb_t bypass) in_use = true; } - shell_set_bypass(sh, bypass); + shell_set_bypass(sh, bypass, NULL); return 0; } -static void bypass_cb(const struct shell *sh, uint8_t *recv, size_t len) +static void bypass_cb(const struct shell *sh, uint8_t *recv, size_t len, void *user_data) { bool escape = false; static uint8_t tail; uint8_t byte; + ARG_UNUSED(user_data); + for (size_t i = 0; i < len; i++) { if (tail == CHAR_CAN && recv[i] == CHAR_DC1) { escape = true; diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index c073489973fa1..a331464ba09d1 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -987,6 +987,7 @@ static void state_collect(const struct shell *sh) while (true) { shell_bypass_cb_t bypass = sh->ctx->bypass; + void *bypass_user_data = sh->ctx->bypass_user_data; if (bypass) { #if defined(CONFIG_SHELL_BACKEND_RTT) && defined(CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN) @@ -1006,7 +1007,7 @@ static void state_collect(const struct shell *sh) * to the bypass function. */ z_shell_unlock(sh); - bypass(sh, buf, count); + bypass(sh, buf, count, bypass_user_data); /* After returning, we're back in the shell context — re-acquire * the shell mutex on the shell thread. */ @@ -1816,11 +1817,12 @@ int shell_mode_delete_set(const struct shell *sh, bool val) return (int)z_flag_mode_delete_set(sh, val); } -void shell_set_bypass(const struct shell *sh, shell_bypass_cb_t bypass) +void shell_set_bypass(const struct shell *sh, shell_bypass_cb_t bypass, void *user_data) { __ASSERT_NO_MSG(sh); sh->ctx->bypass = bypass; + sh->ctx->bypass_user_data = user_data; if (bypass == NULL) { cmd_buffer_clear(sh); From b30515ad010255bc78d0757c4d474470e953adb8 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Mon, 1 Dec 2025 15:59:12 +0100 Subject: [PATCH 2/2] doc: releases: migration: 4.4: Add shell_set_bypass update Add an entry for the shell API change for shell_set_bypass. Signed-off-by: Pieter De Gendt --- doc/releases/migration-guide-4.4.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/releases/migration-guide-4.4.rst b/doc/releases/migration-guide-4.4.rst index de87176adc6e1..e6f0f5dc69808 100644 --- a/doc/releases/migration-guide-4.4.rst +++ b/doc/releases/migration-guide-4.4.rst @@ -96,6 +96,12 @@ STM32 * ``CONFIG_POWER_SUPPLY_EXTERNAL_SOURCE`` +Shell +===== + +* The :c:func:`shell_set_bypass` now requires a user data pointer to be passed. And accordingly the + :c:type:`shell_bypass_cb_t` now has a user data argument. (:github:`100311`) + .. zephyr-keep-sorted-stop Bluetooth