diff --git a/include/shell/shell.h b/include/shell/shell.h index e86cffac6e5..125e2ef043c 100644 --- a/include/shell/shell.h +++ b/include/shell/shell.h @@ -613,8 +613,8 @@ struct shell_flags { uint32_t tx_rdy :1; uint32_t mode_delete :1; /*!< Operation mode of backspace key */ uint32_t history_exit:1; /*!< Request to exit history mode */ - uint32_t cmd_ctx :1; /*!< Shell is executing command */ 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*/ }; @@ -1036,29 +1036,68 @@ int shell_execute_cmd(const struct shell *shell, const char *cmd); int shell_set_root_cmd(const char *cmd); /** - * @brief Allow application to control whether terminal output uses colored - * syntax. + * @brief Allow application to control text insert mode. + * Value is modified atomically and the previous value is returned. * * @param[in] shell Pointer to the shell instance. - * @param[in] use_colors Color mode. + * @param[in] val Insert mode. * - * @retval 0 if set. + * @retval 0 or 1: previous value * @retval -EINVAL if shell is NULL. */ -int shell_use_colors_set(const struct shell *shell, bool use_colors); +int shell_insert_mode_set(const struct shell *shell, bool val); + +/** + * @brief Allow application to control whether terminal output uses colored + * syntax. + * Value is modified atomically and the previous value is returned. + * + * @param[in] shell Pointer to the shell instance. + * @param[in] val Color mode. + * + * @retval 0 or 1: previous value + * @retval -EINVAL if shell is NULL. + */ +int shell_use_colors_set(const struct shell *shell, bool val); + +/** + * @brief Allow application to control whether user input is echoed back. + * Value is modified atomically and the previous value is returned. + * + * @param[in] shell Pointer to the shell instance. + * @param[in] val Echo mode. + * + * @retval 0 or 1: previous value + * @retval -EINVAL if shell is NULL. + */ +int shell_echo_set(const struct shell *shell, bool val); /** * @brief Allow application to control whether user input is obscured with * asterisks -- useful for implementing passwords. + * Value is modified atomically and the previous value is returned. * * @param[in] shell Pointer to the shell instance. * @param[in] obscure Obscure mode. * - * @retval 0 if set. + * @retval 0 or 1: previous value. * @retval -EINVAL if shell is NULL. */ int shell_obscure_set(const struct shell *shell, bool obscure); +/** + * @brief Allow application to control whether the delete key backspaces or + * deletes. + * Value is modified atomically and the previous value is returned. + * + * @param[in] shell Pointer to the shell instance. + * @param[in] val Delete mode. + * + * @retval 0 or 1: previous value + * @retval -EINVAL if shell is NULL. + */ +int shell_mode_delete_set(const struct shell *shell, bool val); + /** * @} */ diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index 7703856fb4d..e9c8786bdbd 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -1377,13 +1377,8 @@ void shell_process(const struct shell *shell) __ASSERT_NO_MSG(shell); __ASSERT_NO_MSG(shell->ctx); - union shell_internal internal; - - internal.value = 0U; - internal.flags.processing = 1U; - - (void)atomic_or((atomic_t *)&shell->ctx->internal.value, - internal.value); + /* atomically set the processing flag */ + z_flag_processing_set(shell, true); switch (shell->ctx->state) { case SHELL_STATE_UNINITIALIZED: @@ -1398,10 +1393,8 @@ void shell_process(const struct shell *shell) break; } - internal.value = 0xFFFFFFFF; - internal.flags.processing = 0U; - (void)atomic_and((atomic_t *)&shell->ctx->internal.value, - internal.value); + /* atomically clear the processing flag */ + z_flag_processing_set(shell, false); } /* This function mustn't be used from shell context to avoid deadlock. @@ -1560,26 +1553,49 @@ int shell_execute_cmd(const struct shell *shell, const char *cmd) return ret_val; } -int shell_use_colors_set(const struct shell *shell, bool use_colors) +int shell_insert_mode_set(const struct shell *shell, bool val) { if (shell == NULL) { return -EINVAL; } - z_flag_use_colors_set(shell, use_colors); - - return 0; + return (int)z_flag_insert_mode_set(shell, val); } -int shell_obscure_set(const struct shell *shell, bool obscure) +int shell_use_colors_set(const struct shell *shell, bool val) { if (shell == NULL) { return -EINVAL; } - z_flag_obscure_set(shell, obscure); + return (int)z_flag_use_colors_set(shell, val); +} - return 0; +int shell_echo_set(const struct shell *shell, bool val) +{ + if (shell == NULL) { + return -EINVAL; + } + + return (int)z_flag_echo_set(shell, val); +} + +int shell_obscure_set(const struct shell *shell, bool val) +{ + if (shell == NULL) { + return -EINVAL; + } + + return (int)z_flag_obscure_set(shell, val); +} + +int shell_mode_delete_set(const struct shell *shell, bool val) +{ + if (shell == NULL) { + return -EINVAL; + } + + return (int)z_flag_mode_delete_set(shell, val); } static int cmd_help(const struct shell *shell, size_t argc, char **argv) diff --git a/subsys/shell/shell_ops.h b/subsys/shell/shell_ops.h index 8750fc6d8a1..042e139f6ca 100644 --- a/subsys/shell/shell_ops.h +++ b/subsys/shell/shell_ops.h @@ -60,14 +60,33 @@ 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 { \ + union shell_internal _internal_; \ + atomic_t *_dst_ = (atomic_t *)&(_shell_)->ctx->internal.value; \ + _internal_.value = 0U; \ + _internal_.flags._flag_ = 1U; \ + if (_val_) { \ + _internal_.value = atomic_or(_dst_, \ + _internal_.value); \ + } else { \ + _internal_.value = atomic_and(_dst_, \ + ~_internal_.value); \ + } \ + _ret_ = (_internal_.flags._flag_ != 0); \ + } while (0) + static inline bool z_flag_insert_mode_get(const struct shell *shell) { return shell->ctx->internal.flags.insert_mode == 1; } -static inline void z_flag_insert_mode_set(const struct shell *shell, bool val) +static inline bool z_flag_insert_mode_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.insert_mode = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, insert_mode, val, ret); + return ret; } static inline bool z_flag_use_colors_get(const struct shell *shell) @@ -75,9 +94,12 @@ static inline bool z_flag_use_colors_get(const struct shell *shell) return shell->ctx->internal.flags.use_colors == 1; } -static inline void z_flag_use_colors_set(const struct shell *shell, bool val) +static inline bool z_flag_use_colors_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.use_colors = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, use_colors, val, ret); + return ret; } static inline bool z_flag_echo_get(const struct shell *shell) @@ -85,9 +107,12 @@ static inline bool z_flag_echo_get(const struct shell *shell) return shell->ctx->internal.flags.echo == 1; } -static inline void z_flag_echo_set(const struct shell *shell, bool val) +static inline bool z_flag_echo_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.echo = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, echo, val, ret); + return ret; } static inline bool z_flag_obscure_get(const struct shell *shell) @@ -95,9 +120,12 @@ static inline bool z_flag_obscure_get(const struct shell *shell) return shell->ctx->internal.flags.obscure == 1; } -static inline void z_flag_obscure_set(const struct shell *shell, bool val) +static inline bool z_flag_obscure_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.obscure = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, obscure, val, ret); + return ret; } static inline bool z_flag_processing_get(const struct shell *shell) @@ -105,14 +133,25 @@ static inline bool z_flag_processing_get(const struct shell *shell) return shell->ctx->internal.flags.processing == 1; } +static inline bool z_flag_processing_set(const struct shell *shell, bool val) +{ + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, processing, val, ret); + return ret; +} + static inline bool z_flag_tx_rdy_get(const struct shell *shell) { return shell->ctx->internal.flags.tx_rdy == 1; } -static inline void z_flag_tx_rdy_set(const struct shell *shell, bool val) +static inline bool z_flag_tx_rdy_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.tx_rdy = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, tx_rdy, val, ret); + return ret; } static inline bool z_flag_mode_delete_get(const struct shell *shell) @@ -120,9 +159,12 @@ static inline bool z_flag_mode_delete_get(const struct shell *shell) return shell->ctx->internal.flags.mode_delete == 1; } -static inline void z_flag_mode_delete_set(const struct shell *shell, bool val) +static inline bool z_flag_mode_delete_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.mode_delete = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, mode_delete, val, ret); + return ret; } static inline bool z_flag_history_exit_get(const struct shell *shell) @@ -130,9 +172,12 @@ static inline bool z_flag_history_exit_get(const struct shell *shell) return shell->ctx->internal.flags.history_exit == 1; } -static inline void z_flag_history_exit_set(const struct shell *shell, bool val) +static inline bool z_flag_history_exit_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.history_exit = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, history_exit, val, ret); + return ret; } static inline bool z_flag_cmd_ctx_get(const struct shell *shell) @@ -140,9 +185,12 @@ static inline bool z_flag_cmd_ctx_get(const struct shell *shell) return shell->ctx->internal.flags.cmd_ctx == 1; } -static inline void z_flag_cmd_ctx_set(const struct shell *shell, bool val) +static inline bool z_flag_cmd_ctx_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.cmd_ctx = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, cmd_ctx, val, ret); + return ret; } static inline uint8_t z_flag_last_nl_get(const struct shell *shell) @@ -160,9 +208,12 @@ static inline bool z_flag_print_noinit_get(const struct shell *shell) return shell->ctx->internal.flags.print_noinit == 1; } -static inline void z_flag_print_noinit_set(const struct shell *shell, bool val) +static inline bool z_flag_print_noinit_set(const struct shell *shell, bool val) { - shell->ctx->internal.flags.print_noinit = val ? 1 : 0; + bool ret; + + Z_SHELL_SET_FLAG_ATOMIC(shell, print_noinit, val, ret); + return ret; } void z_shell_op_cursor_vert_move(const struct shell *shell, int32_t delta);