shell: add init backend configuration

Each backend can configure separately features like colors on/off, VT100
handling and so on. This can be very handy for planned MQTT backend.
Shell will not send VT100 commands when VT100 is not enabled globally or
for particular backend.

Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
Jakub Rzeszutko 2021-09-20 14:21:57 +02:00 committed by Christopher Friedt
commit 2b5723d455
8 changed files with 252 additions and 188 deletions

View file

@ -615,31 +615,59 @@ struct shell_stats {
#endif /* CONFIG_SHELL_STATS */ #endif /* CONFIG_SHELL_STATS */
/** /**
* @internal @brief Flags for internal shell usage. * @internal @brief Flags for shell backend configuration.
*/ */
struct shell_flags { struct shell_backend_config_flags {
uint32_t insert_mode :1; /*!< Controls insert mode for text introduction.*/ uint32_t insert_mode :1; /*!< Controls insert mode for text introduction.*/
uint32_t use_colors :1; /*!< Controls colored syntax.*/
uint32_t echo :1; /*!< Controls shell echo.*/ uint32_t echo :1; /*!< Controls shell echo.*/
uint32_t obscure :1; /*!< If echo on, print asterisk instead */ uint32_t obscure :1; /*!< If echo on, print asterisk instead */
uint32_t processing :1; /*!< Shell is executing process function.*/
uint32_t tx_rdy :1;
uint32_t mode_delete :1; /*!< Operation mode of backspace key */ uint32_t mode_delete :1; /*!< Operation mode of backspace key */
uint32_t history_exit:1; /*!< Request to exit history mode */ uint32_t use_colors :1; /*!< Controls colored syntax.*/
uint32_t last_nl :8; /*!< Last received new line character */ uint32_t use_vt100 :1; /*!< Controls VT100 commands usage in shell */
uint32_t cmd_ctx :1; /*!< Shell is executing command */
uint32_t print_noinit:1; /*!< Print request from not initialized shell*/
}; };
BUILD_ASSERT((sizeof(struct shell_flags) == sizeof(uint32_t)), BUILD_ASSERT((sizeof(struct shell_backend_config_flags) == sizeof(uint32_t)),
"Structure must fit in 4 bytes");
/**
* @internal @brief Default backend configuration.
*/
#define SHELL_DEFAULT_BACKEND_CONFIG_FLAGS \
{ \
.insert_mode = 0, \
.echo = 1, \
.obscure = 0, \
.mode_delete = 1, \
.use_colors = 1, \
.use_vt100 = 1, \
};
struct shell_backend_ctx_flags {
uint32_t processing :1; /*!< Shell is executing process function.*/
uint32_t tx_rdy :1;
uint32_t history_exit :1; /*!< Request to exit history mode */
uint32_t last_nl :8; /*!< Last received new line character */
uint32_t cmd_ctx :1; /*!< Shell is executing command */
uint32_t print_noinit :1; /*!< Print request from not initialized shell*/
};
BUILD_ASSERT((sizeof(struct shell_backend_ctx_flags) == sizeof(uint32_t)),
"Structure must fit in 4 bytes"); "Structure must fit in 4 bytes");
/** /**
* @internal @brief Union for internal shell usage. * @internal @brief Union for internal shell usage.
*/ */
union shell_internal { union shell_backend_cfg {
uint32_t value; uint32_t value;
struct shell_flags flags; struct shell_backend_config_flags flags;
};
/**
* @internal @brief Union for internal shell usage.
*/
union shell_backend_ctx {
uint32_t value;
struct shell_backend_ctx_flags flags;
}; };
enum shell_signal { enum shell_signal {
@ -695,7 +723,8 @@ struct shell_ctx {
/*!< Printf buffer size.*/ /*!< Printf buffer size.*/
char printf_buff[CONFIG_SHELL_PRINTF_BUFF_SIZE]; char printf_buff[CONFIG_SHELL_PRINTF_BUFF_SIZE];
volatile union shell_internal internal; /*!< Internal shell data.*/ volatile union shell_backend_cfg cfg;
volatile union shell_backend_ctx ctx;
struct k_poll_signal signals[SHELL_SIGNALS]; struct k_poll_signal signals[SHELL_SIGNALS];
@ -796,7 +825,8 @@ extern void z_shell_print_stream(const void *user_ctx, const char *data,
* *
* @param[in] shell Pointer to shell instance. * @param[in] shell Pointer to shell instance.
* @param[in] transport_config Transport configuration during initialization. * @param[in] transport_config Transport configuration during initialization.
* @param[in] use_colors Enables colored prints. * @param[in] cfg_flags Initial backend configuration flags.
* Shell will copy this data.
* @param[in] log_backend If true, the console will be used as logger * @param[in] log_backend If true, the console will be used as logger
* backend. * backend.
* @param[in] init_log_level Default severity level for the logger. * @param[in] init_log_level Default severity level for the logger.
@ -804,7 +834,8 @@ extern void z_shell_print_stream(const void *user_ctx, const char *data,
* @return Standard error code. * @return Standard error code.
*/ */
int shell_init(const struct shell *shell, const void *transport_config, int shell_init(const struct shell *shell, const void *transport_config,
bool use_colors, bool log_backend, uint32_t init_log_level); struct shell_backend_config_flags cfg_flags,
bool log_backend, uint32_t init_log_level);
/** /**
* @brief Uninitializes the transport layer and the internal shell state. * @brief Uninitializes the transport layer and the internal shell state.

View file

@ -16,7 +16,9 @@ void shell_init_from_work(struct k_work *work)
(CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > LOG_LEVEL_DBG) ? (CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > LOG_LEVEL_DBG) ?
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL; CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL;
shell_init(shell_backend_uart_get_ptr(), dev, true, log_backend, level); shell_init(shell_backend_uart_get_ptr(), dev,
shell_backend_uart_get_ptr()->ctx->cfg.flags,
log_backend, level);
} }
static void shell_reinit_trigger(void) static void shell_reinit_trigger(void)

View file

@ -1176,51 +1176,58 @@ static void shell_log_process(const struct shell *shell)
} while (processed && !signaled); } while (processed && !signaled);
} }
static int instance_init(const struct shell *shell, const void *p_config, static int instance_init(const struct shell *sh,
bool use_colors) const void *transport_config,
struct shell_backend_config_flags cfg_flags)
{ {
__ASSERT_NO_MSG((shell->shell_flag == SHELL_FLAG_CRLF_DEFAULT) || __ASSERT_NO_MSG((sh->shell_flag == SHELL_FLAG_CRLF_DEFAULT) ||
(shell->shell_flag == SHELL_FLAG_OLF_CRLF)); (sh->shell_flag == SHELL_FLAG_OLF_CRLF));
memset(shell->ctx, 0, sizeof(*shell->ctx)); memset(sh->ctx, 0, sizeof(*sh->ctx));
shell->ctx->prompt = shell->default_prompt; sh->ctx->prompt = sh->default_prompt;
if (CONFIG_SHELL_CMD_ROOT[0]) { if (CONFIG_SHELL_CMD_ROOT[0]) {
shell->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT); sh->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT);
} }
history_init(shell); history_init(sh);
k_mutex_init(&shell->ctx->wr_mtx); k_mutex_init(&sh->ctx->wr_mtx);
for (int i = 0; i < SHELL_SIGNALS; i++) { for (int i = 0; i < SHELL_SIGNALS; i++) {
k_poll_signal_init(&shell->ctx->signals[i]); k_poll_signal_init(&sh->ctx->signals[i]);
k_poll_event_init(&shell->ctx->events[i], k_poll_event_init(&sh->ctx->events[i],
K_POLL_TYPE_SIGNAL, K_POLL_TYPE_SIGNAL,
K_POLL_MODE_NOTIFY_ONLY, K_POLL_MODE_NOTIFY_ONLY,
&shell->ctx->signals[i]); &sh->ctx->signals[i]);
} }
if (IS_ENABLED(CONFIG_SHELL_STATS)) { if (IS_ENABLED(CONFIG_SHELL_STATS)) {
shell->stats->log_lost_cnt = 0; sh->stats->log_lost_cnt = 0;
} }
z_flag_tx_rdy_set(shell, true); z_flag_tx_rdy_set(sh, true);
z_flag_echo_set(shell, IS_ENABLED(CONFIG_SHELL_ECHO_STATUS));
z_flag_obscure_set(shell, IS_ENABLED(CONFIG_SHELL_START_OBSCURED));
z_flag_mode_delete_set(shell,
IS_ENABLED(CONFIG_SHELL_BACKSPACE_MODE_DELETE));
shell->ctx->vt100_ctx.cons.terminal_wid =
CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH;
shell->ctx->vt100_ctx.cons.terminal_hei =
CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT;
shell->ctx->vt100_ctx.cons.name_len = z_shell_strlen(shell->ctx->prompt);
z_flag_use_colors_set(shell, IS_ENABLED(CONFIG_SHELL_VT100_COLORS) && use_colors);
int ret = shell->iface->api->init(shell->iface, p_config, sh->ctx->vt100_ctx.cons.terminal_wid =
transport_evt_handler, CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH;
(void *)shell); sh->ctx->vt100_ctx.cons.terminal_hei =
CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT;
sh->ctx->vt100_ctx.cons.name_len = z_shell_strlen(sh->ctx->prompt);
/* Configure backend according to enabled shell features and backend
* specific settings.
*/
cfg_flags.obscure &= IS_ENABLED(CONFIG_SHELL_START_OBSCURED);
cfg_flags.use_colors &= IS_ENABLED(CONFIG_SHELL_VT100_COLORS);
cfg_flags.use_vt100 &= IS_ENABLED(CONFIG_SHELL_VT100_COMMANDS);
cfg_flags.echo &= IS_ENABLED(CONFIG_SHELL_ECHO_STATUS);
cfg_flags.mode_delete &= IS_ENABLED(CONFIG_SHELL_BACKSPACE_MODE_DELETE);
sh->ctx->cfg.flags = cfg_flags;
int ret = sh->iface->api->init(sh->iface, transport_config,
transport_evt_handler,
(void *)sh);
if (ret == 0) { if (ret == 0) {
state_set(shell, SHELL_STATE_INITIALIZED); state_set(sh, SHELL_STATE_INITIALIZED);
} }
return ret; return ret;
@ -1339,7 +1346,8 @@ void shell_thread(void *shell_handle, void *arg_log_backend,
} }
int shell_init(const struct shell *shell, const void *transport_config, int shell_init(const struct shell *shell, const void *transport_config,
bool use_colors, bool log_backend, uint32_t init_log_level) struct shell_backend_config_flags cfg_flags,
bool log_backend, uint32_t init_log_level)
{ {
__ASSERT_NO_MSG(shell); __ASSERT_NO_MSG(shell);
__ASSERT_NO_MSG(shell->ctx && shell->iface && shell->default_prompt); __ASSERT_NO_MSG(shell->ctx && shell->iface && shell->default_prompt);
@ -1348,7 +1356,7 @@ int shell_init(const struct shell *shell, const void *transport_config,
return -EALREADY; return -EALREADY;
} }
int err = instance_init(shell, transport_config, use_colors); int err = instance_init(shell, transport_config, cfg_flags);
if (err != 0) { if (err != 0) {
return err; return err;
@ -1458,33 +1466,33 @@ void shell_process(const struct shell *shell)
/* This function mustn't be used from shell context to avoid deadlock. /* This function mustn't be used from shell context to avoid deadlock.
* However it can be used in shell command handlers. * However it can be used in shell command handlers.
*/ */
void shell_vfprintf(const struct shell *shell, enum shell_vt100_color color, void shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
const char *fmt, va_list args) const char *fmt, va_list args)
{ {
__ASSERT_NO_MSG(shell); __ASSERT_NO_MSG(sh);
__ASSERT(!k_is_in_isr(), "Thread context required."); __ASSERT(!k_is_in_isr(), "Thread context required.");
__ASSERT_NO_MSG(shell->ctx); __ASSERT_NO_MSG(sh->ctx);
__ASSERT_NO_MSG((shell->ctx->internal.flags.cmd_ctx == 1) || __ASSERT_NO_MSG(z_flag_cmd_ctx_get(sh) ||
(k_current_get() != shell->ctx->tid)); (k_current_get() != sh->ctx->tid));
__ASSERT_NO_MSG(shell->fprintf_ctx); __ASSERT_NO_MSG(sh->fprintf_ctx);
__ASSERT_NO_MSG(fmt); __ASSERT_NO_MSG(fmt);
/* Sending a message to a non-active shell leads to a dead lock. */ /* Sending a message to a non-active shell leads to a dead lock. */
if (state_get(shell) != SHELL_STATE_ACTIVE) { if (state_get(sh) != SHELL_STATE_ACTIVE) {
z_flag_print_noinit_set(shell, true); z_flag_print_noinit_set(sh, true);
return; return;
} }
k_mutex_lock(&shell->ctx->wr_mtx, K_FOREVER); k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
if (!z_flag_cmd_ctx_get(shell) && !shell->ctx->bypass) { if (!z_flag_cmd_ctx_get(sh) && !sh->ctx->bypass) {
z_shell_cmd_line_erase(shell); z_shell_cmd_line_erase(sh);
} }
z_shell_vfprintf(shell, color, fmt, args); z_shell_vfprintf(sh, color, fmt, args);
if (!z_flag_cmd_ctx_get(shell) && !shell->ctx->bypass) { if (!z_flag_cmd_ctx_get(sh) && !sh->ctx->bypass) {
z_shell_print_prompt_and_cmd(shell); z_shell_print_prompt_and_cmd(sh);
} }
z_transport_buffer_flush(shell); z_transport_buffer_flush(sh);
k_mutex_unlock(&shell->ctx->wr_mtx); k_mutex_unlock(&sh->ctx->wr_mtx);
} }
/* This function mustn't be used from shell context to avoid deadlock. /* This function mustn't be used from shell context to avoid deadlock.
@ -1575,7 +1583,7 @@ void shell_help(const struct shell *shell)
k_mutex_unlock(&shell->ctx->wr_mtx); k_mutex_unlock(&shell->ctx->wr_mtx);
} }
int shell_execute_cmd(const struct shell *shell, const char *cmd) int shell_execute_cmd(const struct shell *sh, const char *cmd)
{ {
uint16_t cmd_len = z_shell_strlen(cmd); uint16_t cmd_len = z_shell_strlen(cmd);
int ret_val; int ret_val;
@ -1588,27 +1596,26 @@ int shell_execute_cmd(const struct shell *shell, const char *cmd)
return -ENOMEM; return -ENOMEM;
} }
if (shell == NULL) { if (sh == NULL) {
#if defined(CONFIG_SHELL_BACKEND_DUMMY) #if defined(CONFIG_SHELL_BACKEND_DUMMY)
shell = shell_backend_dummy_get_ptr(); sh = shell_backend_dummy_get_ptr();
#else #else
return -EINVAL; return -EINVAL;
#endif #endif
} }
__ASSERT(shell->ctx->internal.flags.cmd_ctx == 0, __ASSERT(!z_flag_cmd_ctx_get(sh), "Function cannot be called"
"Function cannot be called" " from command context");
" from command context");
strcpy(shell->ctx->cmd_buff, cmd); strcpy(sh->ctx->cmd_buff, cmd);
shell->ctx->cmd_buff_len = cmd_len; sh->ctx->cmd_buff_len = cmd_len;
shell->ctx->cmd_buff_pos = cmd_len; sh->ctx->cmd_buff_pos = cmd_len;
k_mutex_lock(&shell->ctx->wr_mtx, K_FOREVER); k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
ret_val = execute(shell); ret_val = execute(sh);
k_mutex_unlock(&shell->ctx->wr_mtx); k_mutex_unlock(&sh->ctx->wr_mtx);
cmd_buffer_clear(shell); cmd_buffer_clear(sh);
return ret_val; return ret_val;
} }

View file

@ -101,7 +101,9 @@ const struct shell_transport_api shell_dummy_transport_api = {
static int enable_shell_dummy(const struct device *arg) static int enable_shell_dummy(const struct device *arg)
{ {
ARG_UNUSED(arg); ARG_UNUSED(arg);
shell_init(&shell_dummy, NULL, true, true, LOG_LEVEL_INF); static const struct shell_backend_config_flags cfg_flags =
SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
shell_init(&shell_dummy, NULL, cfg_flags, true, LOG_LEVEL_INF);
return 0; return 0;
} }
SYS_INIT(enable_shell_dummy, POST_KERNEL, 0); SYS_INIT(enable_shell_dummy, POST_KERNEL, 0);

View file

@ -28,43 +28,16 @@ static inline void z_shell_raw_fprintf(const struct shell_fprintf *const ctx,
/* Macro to send VT100 command. */ /* Macro to send VT100 command. */
#define Z_SHELL_VT100_CMD(_shell_, ...) \ #define Z_SHELL_VT100_CMD(_shell_, ...) \
do { \ do { \
if (!IS_ENABLED(CONFIG_SHELL_VT100_COMMANDS)) \ if (!IS_ENABLED(CONFIG_SHELL_VT100_COMMANDS) || \
!z_flag_use_vt100_get(_shell_)) \
break; \ break; \
z_shell_raw_fprintf(_shell_->fprintf_ctx, __VA_ARGS__); \ z_shell_raw_fprintf(_shell_->fprintf_ctx, __VA_ARGS__); \
} while (0) } while (0)
/* Function sends VT100 command to clear the screen from cursor position to #define Z_SHELL_SET_FLAG_ATOMIC(_shell_, _type_, _flag_, _val_, _ret_) \
* end of the screen.
*/
static inline void z_clear_eos(const struct shell *shell)
{
Z_SHELL_VT100_CMD(shell, SHELL_VT100_CLEAREOS);
}
/* Function sends VT100 command to save cursor position. */
static inline void z_cursor_save(const struct shell *shell)
{
Z_SHELL_VT100_CMD(shell, SHELL_VT100_SAVECURSOR);
}
/* Function sends VT100 command to restore saved cursor position. */
static inline void z_cursor_restore(const struct shell *shell)
{
Z_SHELL_VT100_CMD(shell, SHELL_VT100_RESTORECURSOR);
}
/* Function forcing new line - cannot be replaced with function
* cursor_down_move.
*/
static inline void z_cursor_next_line_move(const struct shell *shell)
{
z_shell_raw_fprintf(shell->fprintf_ctx, "\n");
}
#define Z_SHELL_SET_FLAG_ATOMIC(_shell_, _flag_, _val_, _ret_) \
do { \ do { \
union shell_internal _internal_; \ union shell_backend_##_type_ _internal_; \
atomic_t *_dst_ = (atomic_t *)&(_shell_)->ctx->internal.value; \ atomic_t *_dst_ = (atomic_t *)&(_shell_)->ctx->_type_.value; \
_internal_.value = 0U; \ _internal_.value = 0U; \
_internal_.flags._flag_ = 1U; \ _internal_.flags._flag_ = 1U; \
if (_val_) { \ if (_val_) { \
@ -77,166 +50,208 @@ static inline void z_cursor_next_line_move(const struct shell *shell)
_ret_ = (_internal_.flags._flag_ != 0); \ _ret_ = (_internal_.flags._flag_ != 0); \
} while (0) } while (0)
static inline bool z_flag_insert_mode_get(const struct shell *shell) static inline bool z_flag_insert_mode_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.insert_mode == 1; return sh->ctx->cfg.flags.insert_mode == 1;
} }
static inline bool z_flag_insert_mode_set(const struct shell *shell, bool val) static inline bool z_flag_insert_mode_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, insert_mode, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, insert_mode, val, ret);
return ret; return ret;
} }
static inline bool z_flag_use_colors_get(const struct shell *shell) static inline bool z_flag_use_colors_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.use_colors == 1; return sh->ctx->cfg.flags.use_colors == 1;
} }
static inline bool z_flag_use_colors_set(const struct shell *shell, bool val) static inline bool z_flag_use_colors_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, use_colors, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, use_colors, val, ret);
return ret; return ret;
} }
static inline bool z_flag_echo_get(const struct shell *shell) static inline bool z_flag_use_vt100_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.echo == 1; return sh->ctx->cfg.flags.use_vt100 == 1;
} }
static inline bool z_flag_echo_set(const struct shell *shell, bool val) static inline bool z_flag_use_vt100_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, echo, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, use_vt100, val, ret);
return ret; return ret;
} }
static inline bool z_flag_obscure_get(const struct shell *shell) static inline bool z_flag_echo_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.obscure == 1; return sh->ctx->cfg.flags.echo == 1;
} }
static inline bool z_flag_obscure_set(const struct shell *shell, bool val) static inline bool z_flag_echo_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, obscure, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, echo, val, ret);
return ret; return ret;
} }
static inline bool z_flag_processing_get(const struct shell *shell) static inline bool z_flag_obscure_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.processing == 1; return sh->ctx->cfg.flags.obscure == 1;
} }
static inline bool z_flag_processing_set(const struct shell *shell, bool val) static inline bool z_flag_obscure_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, processing, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, obscure, val, ret);
return ret; return ret;
} }
static inline bool z_flag_tx_rdy_get(const struct shell *shell) static inline bool z_flag_processing_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.tx_rdy == 1; return sh->ctx->ctx.flags.processing == 1;
} }
static inline bool z_flag_tx_rdy_set(const struct shell *shell, bool val) static inline bool z_flag_processing_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, tx_rdy, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, ctx, processing, val, ret);
return ret; return ret;
} }
static inline bool z_flag_mode_delete_get(const struct shell *shell) static inline bool z_flag_tx_rdy_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.mode_delete == 1; return sh->ctx->ctx.flags.tx_rdy == 1;
} }
static inline bool z_flag_mode_delete_set(const struct shell *shell, bool val) static inline bool z_flag_tx_rdy_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, mode_delete, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, ctx, tx_rdy, val, ret);
return ret; return ret;
} }
static inline bool z_flag_history_exit_get(const struct shell *shell) static inline bool z_flag_mode_delete_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.history_exit == 1; return sh->ctx->cfg.flags.mode_delete == 1;
} }
static inline bool z_flag_history_exit_set(const struct shell *shell, bool val) static inline bool z_flag_mode_delete_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, history_exit, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, cfg, mode_delete, val, ret);
return ret; return ret;
} }
static inline bool z_flag_cmd_ctx_get(const struct shell *shell) static inline bool z_flag_history_exit_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.cmd_ctx == 1; return sh->ctx->ctx.flags.history_exit == 1;
} }
static inline bool z_flag_cmd_ctx_set(const struct shell *shell, bool val) static inline bool z_flag_history_exit_set(const struct shell *sh, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, cmd_ctx, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, ctx, history_exit, val, ret);
return ret; return ret;
} }
static inline uint8_t z_flag_last_nl_get(const struct shell *shell) static inline bool z_flag_cmd_ctx_get(const struct shell *sh)
{ {
return shell->ctx->internal.flags.last_nl; return sh->ctx->ctx.flags.cmd_ctx == 1;
} }
static inline void z_flag_last_nl_set(const struct shell *shell, uint8_t val) static inline bool z_flag_cmd_ctx_set(const struct shell *sh, bool val)
{
shell->ctx->internal.flags.last_nl = val;
}
static inline bool z_flag_print_noinit_get(const struct shell *shell)
{
return shell->ctx->internal.flags.print_noinit == 1;
}
static inline bool z_flag_print_noinit_set(const struct shell *shell, bool val)
{ {
bool ret; bool ret;
Z_SHELL_SET_FLAG_ATOMIC(shell, print_noinit, val, ret); Z_SHELL_SET_FLAG_ATOMIC(sh, ctx, cmd_ctx, val, ret);
return ret; return ret;
} }
void z_shell_op_cursor_vert_move(const struct shell *shell, int32_t delta); static inline uint8_t z_flag_last_nl_get(const struct shell *sh)
void z_shell_op_cursor_horiz_move(const struct shell *shell, int32_t delta); {
return sh->ctx->ctx.flags.last_nl;
}
void z_shell_op_cond_next_line(const struct shell *shell); static inline void z_flag_last_nl_set(const struct shell *sh, uint8_t val)
{
sh->ctx->ctx.flags.last_nl = val;
}
static inline bool z_flag_print_noinit_get(const struct shell *sh)
{
return sh->ctx->ctx.flags.print_noinit == 1;
}
static inline bool z_flag_print_noinit_set(const struct shell *sh, bool val)
{
bool ret;
Z_SHELL_SET_FLAG_ATOMIC(sh, ctx, print_noinit, val, ret);
return ret;
}
/* Function sends VT100 command to clear the screen from cursor position to
* end of the screen.
*/
static inline void z_clear_eos(const struct shell *sh)
{
Z_SHELL_VT100_CMD(sh, SHELL_VT100_CLEAREOS);
}
/* Function sends VT100 command to save cursor position. */
static inline void z_cursor_save(const struct shell *sh)
{
Z_SHELL_VT100_CMD(sh, SHELL_VT100_SAVECURSOR);
}
/* Function sends VT100 command to restore saved cursor position. */
static inline void z_cursor_restore(const struct shell *sh)
{
Z_SHELL_VT100_CMD(sh, SHELL_VT100_RESTORECURSOR);
}
/* Function forcing new line - cannot be replaced with function
* cursor_down_move.
*/
static inline void z_cursor_next_line_move(const struct shell *sh)
{
z_shell_raw_fprintf(sh->fprintf_ctx, "\n");
}
void z_shell_op_cursor_vert_move(const struct shell *sh, int32_t delta);
void z_shell_op_cursor_horiz_move(const struct shell *sh, int32_t delta);
void z_shell_op_cond_next_line(const struct shell *sh);
/* Function will move cursor back to position == cmd_buff_pos. Example usage is /* Function will move cursor back to position == cmd_buff_pos. Example usage is
* when cursor needs to be moved back after printing some text. This function * when cursor needs to be moved back after printing some text. This function
* cannot be used to move cursor to new location by manual change of * cannot be used to move cursor to new location by manual change of
* cmd_buff_pos. * cmd_buff_pos.
*/ */
void z_shell_op_cursor_position_synchronize(const struct shell *shell); void z_shell_op_cursor_position_synchronize(const struct shell *sh);
void z_shell_op_cursor_move(const struct shell *shell, int16_t val); void z_shell_op_cursor_move(const struct shell *sh, int16_t val);
void z_shell_op_left_arrow(const struct shell *shell); void z_shell_op_left_arrow(const struct shell *sh);
void z_shell_op_right_arrow(const struct shell *shell); void z_shell_op_right_arrow(const struct shell *sh);
/* Moves cursor by defined number of words left (val negative) or right. */ /* Moves cursor by defined number of words left (val negative) or right. */
void z_shell_op_cursor_word_move(const struct shell *shell, int16_t val); void z_shell_op_cursor_word_move(const struct shell *sh, int16_t val);
/* /*
* Removes the "word" to the left of the cursor: * Removes the "word" to the left of the cursor:
@ -244,45 +259,45 @@ void z_shell_op_cursor_word_move(const struct shell *shell, int16_t val);
* - remove the non-spaces (word) until a space is found or a beginning of * - remove the non-spaces (word) until a space is found or a beginning of
* buffer * buffer
*/ */
void z_shell_op_word_remove(const struct shell *shell); void z_shell_op_word_remove(const struct shell *sh);
/* Function moves cursor to begin of command position, just after console /* Function moves cursor to begin of command position, just after console
* name. * name.
*/ */
void z_shell_op_cursor_home_move(const struct shell *shell); void z_shell_op_cursor_home_move(const struct shell *sh);
/* Function moves cursor to end of command. */ /* Function moves cursor to end of command. */
void z_shell_op_cursor_end_move(const struct shell *shell); void z_shell_op_cursor_end_move(const struct shell *sh);
void z_shell_op_char_insert(const struct shell *shell, char data); void z_shell_op_char_insert(const struct shell *sh, char data);
void z_shell_op_char_backspace(const struct shell *shell); void z_shell_op_char_backspace(const struct shell *sh);
void z_shell_op_char_delete(const struct shell *shell); void z_shell_op_char_delete(const struct shell *sh);
void z_shell_op_delete_from_cursor(const struct shell *shell); void z_shell_op_delete_from_cursor(const struct shell *sh);
void z_shell_op_completion_insert(const struct shell *shell, void z_shell_op_completion_insert(const struct shell *sh,
const char *compl, const char *compl,
uint16_t compl_len); uint16_t compl_len);
bool z_shell_cursor_in_empty_line(const struct shell *shell); bool z_shell_cursor_in_empty_line(const struct shell *sh);
void z_shell_cmd_line_erase(const struct shell *shell); void z_shell_cmd_line_erase(const struct shell *sh);
/** /**
* @brief Print command buffer. * @brief Print command buffer.
* *
* @param shell Shell instance. * @param shell Shell instance.
*/ */
void z_shell_print_cmd(const struct shell *shell); void z_shell_print_cmd(const struct shell *sh);
/** /**
* @brief Print prompt followed by command buffer. * @brief Print prompt followed by command buffer.
* *
* @param shell Shell instance. * @param shell Shell instance.
*/ */
void z_shell_print_prompt_and_cmd(const struct shell *shell); void z_shell_print_prompt_and_cmd(const struct shell *sh);
/* Function sends data stream to the shell instance. Each time before the /* Function sends data stream to the shell instance. Each time before the
* shell_write function is called, it must be ensured that IO buffer of fprintf * shell_write function is called, it must be ensured that IO buffer of fprintf
@ -292,7 +307,7 @@ void z_shell_print_prompt_and_cmd(const struct shell *shell);
* This function can be only used by shell module, it shall not be called * This function can be only used by shell module, it shall not be called
* directly. * directly.
*/ */
void z_shell_write(const struct shell *shell, const void *data, size_t length); void z_shell_write(const struct shell *sh, const void *data, size_t length);
/** /**
* @internal @brief This function shall not be used directly, it is required by * @internal @brief This function shall not be used directly, it is required by
@ -305,25 +320,25 @@ void z_shell_write(const struct shell *shell, const void *data, size_t length);
void z_shell_print_stream(const void *user_ctx, const char *data, size_t len); void z_shell_print_stream(const void *user_ctx, const char *data, size_t len);
/** @internal @brief Function for setting font color */ /** @internal @brief Function for setting font color */
void z_shell_vt100_color_set(const struct shell *shell, void z_shell_vt100_color_set(const struct shell *sh,
enum shell_vt100_color color); enum shell_vt100_color color);
static inline void z_shell_vt100_colors_store(const struct shell *shell, static inline void z_shell_vt100_colors_store(const struct shell *sh,
struct shell_vt100_colors *color) struct shell_vt100_colors *color)
{ {
memcpy(color, &shell->ctx->vt100_ctx.col, sizeof(*color)); memcpy(color, &sh->ctx->vt100_ctx.col, sizeof(*color));
} }
void z_shell_vt100_colors_restore(const struct shell *shell, void z_shell_vt100_colors_restore(const struct shell *sh,
const struct shell_vt100_colors *color); const struct shell_vt100_colors *color);
/* This function can be called only within shell thread but not from command /* This function can be called only within shell thread but not from command
* handlers. * handlers.
*/ */
void z_shell_fprintf(const struct shell *shell, enum shell_vt100_color color, void z_shell_fprintf(const struct shell *sh, enum shell_vt100_color color,
const char *fmt, ...); const char *fmt, ...);
void z_shell_vfprintf(const struct shell *shell, enum shell_vt100_color color, void z_shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
const char *fmt, va_list args); const char *fmt, va_list args);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -113,8 +113,10 @@ static int enable_shell_rtt(const struct device *arg)
bool log_backend = CONFIG_SHELL_RTT_INIT_LOG_LEVEL > 0; bool log_backend = CONFIG_SHELL_RTT_INIT_LOG_LEVEL > 0;
uint32_t level = (CONFIG_SHELL_RTT_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ? uint32_t level = (CONFIG_SHELL_RTT_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ?
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_RTT_INIT_LOG_LEVEL; CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_RTT_INIT_LOG_LEVEL;
static const struct shell_backend_config_flags cfg_flags =
SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
shell_init(&shell_rtt, NULL, true, log_backend, level); shell_init(&shell_rtt, NULL, cfg_flags, log_backend, level);
return 0; return 0;
} }

View file

@ -495,8 +495,10 @@ static int enable_shell_telnet(const struct device *arg)
bool log_backend = CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > 0; bool log_backend = CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > 0;
uint32_t level = (CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ? uint32_t level = (CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ?
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_TELNET_INIT_LOG_LEVEL; CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_TELNET_INIT_LOG_LEVEL;
static const struct shell_backend_config_flags cfg_flags =
SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
return shell_init(&shell_telnet, NULL, true, log_backend, level); return shell_init(&shell_telnet, NULL, cfg_flags, log_backend, level);
} }
SYS_INIT(enable_shell_telnet, APPLICATION, 0); SYS_INIT(enable_shell_telnet, APPLICATION, 0);

View file

@ -319,6 +319,8 @@ static int enable_shell_uart(const struct device *arg)
uint32_t level = uint32_t level =
(CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > LOG_LEVEL_DBG) ? (CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL > LOG_LEVEL_DBG) ?
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL; CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_BACKEND_SERIAL_LOG_LEVEL;
static const struct shell_backend_config_flags cfg_flags =
SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
if (!device_is_ready(dev)) { if (!device_is_ready(dev)) {
return -ENODEV; return -ENODEV;
@ -328,10 +330,11 @@ static int enable_shell_uart(const struct device *arg)
smp_shell_init(); smp_shell_init();
} }
shell_init(&shell_uart, dev, true, log_backend, level); shell_init(&shell_uart, dev, cfg_flags, log_backend, level);
return 0; return 0;
} }
SYS_INIT(enable_shell_uart, POST_KERNEL, SYS_INIT(enable_shell_uart, POST_KERNEL,
CONFIG_SHELL_BACKEND_SERIAL_INIT_PRIORITY); CONFIG_SHELL_BACKEND_SERIAL_INIT_PRIORITY);