Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions doc/releases/migration-guide-4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,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`)

Stepper
=======

Expand Down
8 changes: 5 additions & 3 deletions drivers/can/can_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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
Expand Down Expand Up @@ -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 */
}

Expand Down
6 changes: 4 additions & 2 deletions drivers/flash/flash_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 7 additions & 2 deletions include/zephyr/shell/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test that uses shell_set_bypass? Even a build-only test can potentially catch future API changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test.


/** @brief Get shell readiness to execute commands.
*
Expand Down
6 changes: 4 additions & 2 deletions samples/subsys/shell/shell_module/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,19 +255,21 @@ 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;
}

#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;
Expand Down
7 changes: 4 additions & 3 deletions subsys/net/lib/shell/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 7 additions & 4 deletions subsys/net/lib/tls_credentials/tls_credentials_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");
Expand All @@ -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);
}
}
Expand All @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions subsys/shell/modules/devmem_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions subsys/shell/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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);
Expand Down
28 changes: 28 additions & 0 deletions tests/subsys/shell/shell/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*
*/

#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>

Expand Down Expand Up @@ -344,6 +345,33 @@ ZTEST(sh, test_shell_fprintf)
"Expected string to contain '%s', got '%s'", expect, buf);
}

static void test_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);
}

ZTEST(sh, test_shell_set_bypass)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
uint8_t user_data;

zassert_not_null(sh, "Failed to get shell backend");

shell_set_bypass(sh, test_bypass_cb, &user_data);

zassert_equal_ptr(sh->ctx->bypass, test_bypass_cb, "Bypass callback not stored");
zassert_equal_ptr(sh->ctx->bypass_user_data, &user_data, "User data pointer not stored");

shell_set_bypass(sh, NULL, NULL);

zassert_is_null(sh->ctx->bypass, "Bypass callback not cleared");
zassert_is_null(sh->ctx->bypass_user_data, "User data pointer not cleared");
}

#define RAW_ARG "aaa \"\" bbb"
#define CMD_MAND_1_OPT_RAW_NAME cmd_mand_1_opt_raw

Expand Down