| /* |
| * Copyright (c) 2018 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef SHELL_H__ |
| #define SHELL_H__ |
| |
| #include <zephyr.h> |
| #include <shell/shell_types.h> |
| #include <shell/shell_history.h> |
| #include <shell/shell_fprintf.h> |
| #include <shell/shell_log_backend.h> |
| #include <logging/log_instance.h> |
| #include <logging/log.h> |
| #include <sys/util.h> |
| |
| #if defined CONFIG_SHELL_GETOPT |
| #include <shell/shell_getopt.h> |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #ifndef CONFIG_SHELL_CMD_BUFF_SIZE |
| #define CONFIG_SHELL_CMD_BUFF_SIZE 0 |
| #endif |
| |
| #ifndef CONFIG_SHELL_PRINTF_BUFF_SIZE |
| #define CONFIG_SHELL_PRINTF_BUFF_SIZE 0 |
| #endif |
| |
| #ifndef CONFIG_SHELL_HISTORY_BUFFER |
| #define CONFIG_SHELL_HISTORY_BUFFER 0 |
| #endif |
| |
| #define Z_SHELL_CMD_ROOT_LVL (0u) |
| |
| #define SHELL_HEXDUMP_BYTES_IN_LINE 16 |
| |
| /** |
| * @brief Flag indicates that optional arguments will be treated as one, |
| * unformatted argument. |
| * |
| * By default, shell is parsing all arguments, treats all spaces as argument |
| * separators unless they are within quotation marks which are removed in that |
| * case. If command rely on unformatted argument then this flag shall be used |
| * in place of number of optional arguments in command definition to indicate |
| * that only mandatory arguments shall be parsed and remaining command string is |
| * passed as a raw string. |
| */ |
| #define SHELL_OPT_ARG_RAW (0xFE) |
| |
| /** |
| * @brief Flag indicateding that number of optional arguments is not limited. |
| */ |
| #define SHELL_OPT_ARG_CHECK_SKIP (0xFF) |
| |
| /** |
| * @brief Flag indicating maximum number of optional arguments that can be |
| * validated. |
| */ |
| #define SHELL_OPT_ARG_MAX (0xFD) |
| |
| /** |
| * @brief Shell API |
| * @defgroup shell_api Shell API |
| * @ingroup shell |
| * @{ |
| */ |
| |
| struct getopt_state; |
| struct shell_static_entry; |
| |
| /** |
| * @brief Shell dynamic command descriptor. |
| * |
| * @details Function shall fill the received shell_static_entry structure |
| * with requested (idx) dynamic subcommand data. If there is more than |
| * one dynamic subcommand available, the function shall ensure that the |
| * returned commands: entry->syntax are sorted in alphabetical order. |
| * If idx exceeds the available dynamic subcommands, the function must |
| * write to entry->syntax NULL value. This will indicate to the shell |
| * module that there are no more dynamic commands to read. |
| */ |
| typedef void (*shell_dynamic_get)(size_t idx, |
| struct shell_static_entry *entry); |
| |
| /** |
| * @brief Shell command descriptor. |
| */ |
| struct shell_cmd_entry { |
| bool is_dynamic; |
| union union_cmd_entry { |
| /*!< Pointer to function returning dynamic commands.*/ |
| shell_dynamic_get dynamic_get; |
| |
| /*!< Pointer to array of static commands. */ |
| const struct shell_static_entry *entry; |
| } u; |
| }; |
| |
| struct shell; |
| |
| struct shell_static_args { |
| uint8_t mandatory; /*!< Number of mandatory arguments. */ |
| uint8_t optional; /*!< Number of optional arguments. */ |
| }; |
| |
| /** |
| * @brief Get by index a device that matches . |
| * |
| * This can be used, for example, to identify I2C_1 as the second I2C |
| * device. |
| * |
| * Devices that failed to initialize or do not have a non-empty name |
| * are excluded from the candidates for a match. |
| * |
| * @param idx the device number starting from zero. |
| * |
| * @param prefix optional name prefix used to restrict candidate |
| * devices. Indexing is done relative to devices with names that |
| * start with this text. Pass null if no prefix match is required. |
| */ |
| const struct device *shell_device_lookup(size_t idx, |
| const char *prefix); |
| |
| /** |
| * @brief Shell command handler prototype. |
| * |
| * @param shell Shell instance. |
| * @param argc Arguments count. |
| * @param argv Arguments. |
| * |
| * @retval 0 Successful command execution. |
| * @retval 1 Help printed and command not executed. |
| * @retval -EINVAL Argument validation failed. |
| * @retval -ENOEXEC Command not executed. |
| */ |
| typedef int (*shell_cmd_handler)(const struct shell *shell, |
| size_t argc, char **argv); |
| |
| /** |
| * @brief Shell dictionary command handler prototype. |
| * |
| * @param shell Shell instance. |
| * @param argc Arguments count. |
| * @param argv Arguments. |
| * @param data Pointer to the user data. |
| * |
| * @retval 0 Successful command execution. |
| * @retval 1 Help printed and command not executed. |
| * @retval -EINVAL Argument validation failed. |
| * @retval -ENOEXEC Command not executed. |
| */ |
| typedef int (*shell_dict_cmd_handler)(const struct shell *shell, size_t argc, |
| char **argv, void *data); |
| |
| /* |
| * @brief Shell static command descriptor. |
| */ |
| struct shell_static_entry { |
| const char *syntax; /*!< Command syntax strings. */ |
| const char *help; /*!< Command help string. */ |
| const struct shell_cmd_entry *subcmd; /*!< Pointer to subcommand. */ |
| shell_cmd_handler handler; /*!< Command handler. */ |
| struct shell_static_args args; /*!< Command arguments. */ |
| }; |
| |
| /** |
| * @brief Macro for defining and adding a root command (level 0) with required |
| * number of arguments. |
| * |
| * @note Each root command shall have unique syntax. If a command will be called |
| * with wrong number of arguments shell will print an error message and command |
| * handler will not be called. |
| * |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| * @param[in] mandatory Number of mandatory arguments includig command name. |
| * @param[in] optional Number of optional arguments. |
| */ |
| #define SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, \ |
| mandatory, optional) \ |
| static const struct shell_static_entry UTIL_CAT(_shell_, syntax) = \ |
| SHELL_CMD_ARG(syntax, subcmd, help, handler, mandatory, optional); \ |
| static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \ |
| __attribute__ ((section("." \ |
| STRINGIFY(UTIL_CAT(shell_root_cmd_, syntax))))) \ |
| __attribute__((used)) = { \ |
| .is_dynamic = false, \ |
| .u = {.entry = &UTIL_CAT(_shell_, syntax)} \ |
| } |
| |
| /** |
| * @brief Macro for defining and adding a conditional root command (level 0) |
| * with required number of arguments. |
| * |
| * @see SHELL_CMD_ARG_REGISTER for details. |
| * |
| * Macro can be used to create a command which can be conditionally present. |
| * It is and alternative to \#ifdefs around command registration and command |
| * handler. If command is disabled handler and subcommands are removed from |
| * the application. |
| * |
| * @param[in] flag Compile time flag. Command is present only if flag |
| * exists and equals 1. |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| * @param[in] mandatory Number of mandatory arguments includig command name. |
| * @param[in] optional Number of optional arguments. |
| */ |
| #define SHELL_COND_CMD_ARG_REGISTER(flag, syntax, subcmd, help, handler, \ |
| mandatory, optional) \ |
| COND_CODE_1(\ |
| flag, \ |
| (\ |
| SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, \ |
| mandatory, optional) \ |
| ), \ |
| (\ |
| static shell_cmd_handler dummy_##syntax##_handler __unused = \ |
| handler;\ |
| static const struct shell_cmd_entry *dummy_subcmd_##syntax \ |
| __unused = subcmd\ |
| )\ |
| ) |
| /** |
| * @brief Macro for defining and adding a root command (level 0) with |
| * arguments. |
| * |
| * @note All root commands must have different name. |
| * |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| */ |
| #define SHELL_CMD_REGISTER(syntax, subcmd, help, handler) \ |
| SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, 0, 0) |
| |
| /** |
| * @brief Macro for defining and adding a conditional root command (level 0) |
| * with arguments. |
| * |
| * @see SHELL_COND_CMD_ARG_REGISTER. |
| * |
| * @param[in] flag Compile time flag. Command is present only if flag |
| * exists and equals 1. |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| */ |
| #define SHELL_COND_CMD_REGISTER(flag, syntax, subcmd, help, handler) \ |
| SHELL_COND_CMD_ARG_REGISTER(flag, syntax, subcmd, help, handler, 0, 0) |
| |
| /** |
| * @brief Macro for creating a subcommand set. It must be used outside of any |
| * function body. |
| * |
| * Example usage: |
| * SHELL_STATIC_SUBCMD_SET_CREATE( |
| * foo, |
| * SHELL_CMD(abc, ...), |
| * SHELL_CMD(def, ...), |
| * SHELL_SUBCMD_SET_END |
| * ) |
| * |
| * @param[in] name Name of the subcommand set. |
| * @param[in] ... List of commands created with @ref SHELL_CMD_ARG or |
| * or @ref SHELL_CMD |
| */ |
| #define SHELL_STATIC_SUBCMD_SET_CREATE(name, ...) \ |
| static const struct shell_static_entry shell_##name[] = { \ |
| __VA_ARGS__ \ |
| }; \ |
| static const struct shell_cmd_entry name = { \ |
| .is_dynamic = false, \ |
| .u = { .entry = shell_##name } \ |
| } |
| |
| /** |
| * @brief Define ending subcommands set. |
| * |
| */ |
| #define SHELL_SUBCMD_SET_END {NULL} |
| |
| /** |
| * @brief Macro for creating a dynamic entry. |
| * |
| * @param[in] name Name of the dynamic entry. |
| * @param[in] get Pointer to the function returning dynamic commands array |
| */ |
| #define SHELL_DYNAMIC_CMD_CREATE(name, get) \ |
| static const struct shell_cmd_entry name = { \ |
| .is_dynamic = true, \ |
| .u = { .dynamic_get = get } \ |
| } |
| |
| /** |
| * @brief Initializes a shell command with arguments. |
| * |
| * @note If a command will be called with wrong number of arguments shell will |
| * print an error message and command handler will not be called. |
| * |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| * @param[in] mand Number of mandatory arguments includig command name. |
| * @param[in] opt Number of optional arguments. |
| */ |
| #define SHELL_CMD_ARG(syntax, subcmd, help, handler, mand, opt) \ |
| SHELL_EXPR_CMD_ARG(1, syntax, subcmd, help, handler, mand, opt) |
| |
| /** |
| * @brief Initializes a conditional shell command with arguments. |
| * |
| * @see SHELL_CMD_ARG. Based on the flag, creates a valid entry or an empty |
| * command which is ignored by the shell. It is an alternative to \#ifdefs |
| * around command registration and command handler. However, empty structure is |
| * present in the flash even if command is disabled (subcommands and handler are |
| * removed). Macro internally handles case if flag is not defined so flag must |
| * be provided without any wrapper, e.g.: SHELL_COND_CMD_ARG(CONFIG_FOO, ...) |
| * |
| * @param[in] flag Compile time flag. Command is present only if flag |
| * exists and equals 1. |
| * @param[in] syntax Command syntax (for example: history). |
| * @param[in] subcmd Pointer to a subcommands array. |
| * @param[in] help Pointer to a command help string. |
| * @param[in] handler Pointer to a function handler. |
| * @param[in] mand Number of mandatory arguments includig command name. |
| * @param[in] opt Number of optional arguments. |
| */ |
| #define SHELL_COND_CMD_ARG(flag, syntax, subcmd, help, handler, mand, opt) \ |
| SHELL_EXPR_CMD_ARG(IS_ENABLED(flag), syntax, subcmd, help, \ |
| handler, mand, opt) |
| |
| /** |
| * @brief Initializes a conditional shell command with arguments if expression |
| * gives non-zero result at compile time. |
| * |
| * @see SHELL_CMD_ARG. Based on the expression, creates a valid entry or an |
| * empty command which is ignored by the shell. It should be used instead of |
| * @ref SHELL_COND_CMD_ARG if condition is not a single configuration flag, |
| * e.g.: |
| * SHELL_EXPR_CMD_ARG(IS_ENABLED(CONFIG_FOO) && |
| * IS_ENABLED(CONFIG_FOO_SETTING_1), ...) |
| * |
| * @param[in] _expr Expression. |
| * @param[in] _syntax Command syntax (for example: history). |
| * @param[in] _subcmd Pointer to a subcommands array. |
| * @param[in] _help Pointer to a command help string. |
| * @param[in] _handler Pointer to a function handler. |
| * @param[in] _mand Number of mandatory arguments includig command name. |
| * @param[in] _opt Number of optional arguments. |
| */ |
| #define SHELL_EXPR_CMD_ARG(_expr, _syntax, _subcmd, _help, _handler, \ |
| _mand, _opt) \ |
| { \ |
| .syntax = (_expr) ? (const char *)STRINGIFY(_syntax) : "", \ |
| .help = (_expr) ? (const char *)_help : NULL, \ |
| .subcmd = (const struct shell_cmd_entry *)((_expr) ? \ |
| _subcmd : NULL), \ |
| .handler = (shell_cmd_handler)((_expr) ? _handler : NULL), \ |
| .args = { .mandatory = _mand, .optional = _opt} \ |
| } |
| |
| /** |
| * @brief Initializes a shell command. |
| * |
| * @param[in] _syntax Command syntax (for example: history). |
| * @param[in] _subcmd Pointer to a subcommands array. |
| * @param[in] _help Pointer to a command help string. |
| * @param[in] _handler Pointer to a function handler. |
| */ |
| #define SHELL_CMD(_syntax, _subcmd, _help, _handler) \ |
| SHELL_CMD_ARG(_syntax, _subcmd, _help, _handler, 0, 0) |
| |
| /** |
| * @brief Initializes a conditional shell command. |
| * |
| * @see SHELL_COND_CMD_ARG. |
| * |
| * @param[in] _flag Compile time flag. Command is present only if flag |
| * exists and equals 1. |
| * @param[in] _syntax Command syntax (for example: history). |
| * @param[in] _subcmd Pointer to a subcommands array. |
| * @param[in] _help Pointer to a command help string. |
| * @param[in] _handler Pointer to a function handler. |
| */ |
| #define SHELL_COND_CMD(_flag, _syntax, _subcmd, _help, _handler) \ |
| SHELL_COND_CMD_ARG(_flag, _syntax, _subcmd, _help, _handler, 0, 0) |
| |
| /** |
| * @brief Initializes shell command if expression gives non-zero result at |
| * compile time. |
| * |
| * @see SHELL_EXPR_CMD_ARG. |
| * |
| * @param[in] _expr Compile time expression. Command is present only if |
| * expression is non-zero. |
| * @param[in] _syntax Command syntax (for example: history). |
| * @param[in] _subcmd Pointer to a subcommands array. |
| * @param[in] _help Pointer to a command help string. |
| * @param[in] _handler Pointer to a function handler. |
| */ |
| #define SHELL_EXPR_CMD(_expr, _syntax, _subcmd, _help, _handler) \ |
| SHELL_EXPR_CMD_ARG(_expr, _syntax, _subcmd, _help, _handler, 0, 0) |
| |
| /* Internal macro used for creating handlers for dictionary commands. */ |
| #define Z_SHELL_CMD_DICT_HANDLER_CREATE(_data, _handler) \ |
| static int UTIL_CAT(cmd_dict_, GET_ARG_N(1, __DEBRACKET _data))( \ |
| const struct shell *shell, size_t argc, char **argv) \ |
| { \ |
| return _handler(shell, argc, argv, \ |
| (void *)GET_ARG_N(2, __DEBRACKET _data)); \ |
| } |
| |
| /* Internal macro used for creating dictionary commands. */ |
| #define SHELL_CMD_DICT_CREATE(_data) \ |
| SHELL_CMD_ARG(GET_ARG_N(1, __DEBRACKET _data), NULL, NULL, \ |
| UTIL_CAT(cmd_dict_, GET_ARG_N(1, __DEBRACKET _data)), 1, 0) |
| |
| /** |
| * @brief Initializes shell dictionary commands. |
| * |
| * This is a special kind of static commands. Dictionary commands can be used |
| * every time you want to use a pair: (string <-> corresponding data) in |
| * a command handler. The string is usually a verbal description of a given |
| * data. The idea is to use the string as a command syntax that can be prompted |
| * by the shell and corresponding data can be used to process the command. |
| * |
| * @param[in] _name Name of the dictionary subcommand set |
| * @param[in] _handler Command handler common for all dictionary commands. |
| * @see shell_dict_cmd_handler |
| * @param[in] ... Dictionary pairs: (command_syntax, value). Value will be |
| * passed to the _handler as user data. |
| * |
| * Example usage: |
| * static int my_handler(const struct shell *shell, |
| * size_t argc, char **argv, void *data) |
| * { |
| * int val = (int)data; |
| * |
| * shell_print(shell, "(syntax, value) : (%s, %d)", argv[0], val); |
| * return 0; |
| * } |
| * |
| * SHELL_SUBCMD_DICT_SET_CREATE(sub_dict_cmds, my_handler, |
| * (value_0, 0), (value_1, 1), (value_2, 2), (value_3, 3) |
| * ); |
| * SHELL_CMD_REGISTER(dictionary, &sub_dict_cmds, NULL, NULL); |
| */ |
| #define SHELL_SUBCMD_DICT_SET_CREATE(_name, _handler, ...) \ |
| FOR_EACH_FIXED_ARG(Z_SHELL_CMD_DICT_HANDLER_CREATE, (), \ |
| _handler, __VA_ARGS__) \ |
| SHELL_STATIC_SUBCMD_SET_CREATE(_name, \ |
| FOR_EACH(SHELL_CMD_DICT_CREATE, (,), __VA_ARGS__), \ |
| SHELL_SUBCMD_SET_END \ |
| ) |
| |
| /** |
| * @internal @brief Internal shell state in response to data received from the |
| * terminal. |
| */ |
| enum shell_receive_state { |
| SHELL_RECEIVE_DEFAULT, |
| SHELL_RECEIVE_ESC, |
| SHELL_RECEIVE_ESC_SEQ, |
| SHELL_RECEIVE_TILDE_EXP |
| }; |
| |
| /** |
| * @internal @brief Internal shell state. |
| */ |
| enum shell_state { |
| SHELL_STATE_UNINITIALIZED, |
| SHELL_STATE_INITIALIZED, |
| SHELL_STATE_ACTIVE, |
| SHELL_STATE_PANIC_MODE_ACTIVE, /*!< Panic activated.*/ |
| SHELL_STATE_PANIC_MODE_INACTIVE /*!< Panic requested, not supported.*/ |
| }; |
| |
| /** @brief Shell transport event. */ |
| enum shell_transport_evt { |
| SHELL_TRANSPORT_EVT_RX_RDY, |
| SHELL_TRANSPORT_EVT_TX_RDY |
| }; |
| |
| typedef void (*shell_transport_handler_t)(enum shell_transport_evt evt, |
| void *context); |
| |
| |
| typedef void (*shell_uninit_cb_t)(const struct shell *shell, int res); |
| |
| /** @brief Bypass callback. |
| * |
| * @param shell Shell instance. |
| * @param data Raw data from transport. |
| * @param len Data length. |
| */ |
| typedef void (*shell_bypass_cb_t)(const struct shell *shell, |
| uint8_t *data, |
| size_t len); |
| |
| struct shell_transport; |
| |
| /** |
| * @brief Unified shell transport interface. |
| */ |
| struct shell_transport_api { |
| /** |
| * @brief Function for initializing the shell transport interface. |
| * |
| * @param[in] transport Pointer to the transfer instance. |
| * @param[in] config Pointer to instance configuration. |
| * @param[in] evt_handler Event handler. |
| * @param[in] context Pointer to the context passed to event |
| * handler. |
| * |
| * @return Standard error code. |
| */ |
| int (*init)(const struct shell_transport *transport, |
| const void *config, |
| shell_transport_handler_t evt_handler, |
| void *context); |
| |
| /** |
| * @brief Function for uninitializing the shell transport interface. |
| * |
| * @param[in] transport Pointer to the transfer instance. |
| * |
| * @return Standard error code. |
| */ |
| int (*uninit)(const struct shell_transport *transport); |
| |
| /** |
| * @brief Function for enabling transport in given TX mode. |
| * |
| * Function can be used to reconfigure TX to work in blocking mode. |
| * |
| * @param transport Pointer to the transfer instance. |
| * @param blocking_tx If true, the transport TX is enabled in blocking |
| * mode. |
| * |
| * @return NRF_SUCCESS on successful enabling, error otherwise (also if |
| * not supported). |
| */ |
| int (*enable)(const struct shell_transport *transport, |
| bool blocking_tx); |
| |
| /** |
| * @brief Function for writing data to the transport interface. |
| * |
| * @param[in] transport Pointer to the transfer instance. |
| * @param[in] data Pointer to the source buffer. |
| * @param[in] length Source buffer length. |
| * @param[out] cnt Pointer to the sent bytes counter. |
| * |
| * @return Standard error code. |
| */ |
| int (*write)(const struct shell_transport *transport, |
| const void *data, size_t length, size_t *cnt); |
| |
| /** |
| * @brief Function for reading data from the transport interface. |
| * |
| * @param[in] p_transport Pointer to the transfer instance. |
| * @param[in] p_data Pointer to the destination buffer. |
| * @param[in] length Destination buffer length. |
| * @param[out] cnt Pointer to the received bytes counter. |
| * |
| * @return Standard error code. |
| */ |
| int (*read)(const struct shell_transport *transport, |
| void *data, size_t length, size_t *cnt); |
| |
| /** |
| * @brief Function called in shell thread loop. |
| * |
| * Can be used for backend operations that require longer execution time |
| * |
| * @param[in] transport Pointer to the transfer instance. |
| */ |
| void (*update)(const struct shell_transport *transport); |
| |
| }; |
| |
| struct shell_transport { |
| const struct shell_transport_api *api; |
| void *ctx; |
| }; |
| |
| /** |
| * @brief Shell statistics structure. |
| */ |
| struct shell_stats { |
| atomic_t log_lost_cnt; /*!< Lost log counter.*/ |
| }; |
| |
| #ifdef CONFIG_SHELL_STATS |
| #define Z_SHELL_STATS_DEFINE(_name) static struct shell_stats _name##_stats |
| #define Z_SHELL_STATS_PTR(_name) (&(_name##_stats)) |
| #else |
| #define Z_SHELL_STATS_DEFINE(_name) |
| #define Z_SHELL_STATS_PTR(_name) NULL |
| #endif /* CONFIG_SHELL_STATS */ |
| |
| /** |
| * @internal @brief Flags for internal shell usage. |
| */ |
| struct shell_flags { |
| 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 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 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_flags) == sizeof(uint32_t)), |
| "Structure must fit in 4 bytes"); |
| |
| /** |
| * @internal @brief Union for internal shell usage. |
| */ |
| union shell_internal { |
| uint32_t value; |
| struct shell_flags flags; |
| }; |
| |
| enum shell_signal { |
| SHELL_SIGNAL_RXRDY, |
| SHELL_SIGNAL_LOG_MSG, |
| SHELL_SIGNAL_KILL, |
| SHELL_SIGNAL_TXDONE, /* TXDONE must be last one before SHELL_SIGNALS */ |
| SHELL_SIGNALS |
| }; |
| |
| /** |
| * @brief Shell instance context. |
| */ |
| struct shell_ctx { |
| const char *prompt; /*!< shell current prompt. */ |
| |
| enum shell_state state; /*!< Internal module state.*/ |
| enum shell_receive_state receive_state;/*!< Escape sequence indicator.*/ |
| |
| /*!< Currently executed command.*/ |
| struct shell_static_entry active_cmd; |
| |
| /* New root command. If NULL shell uses default root commands. */ |
| const struct shell_static_entry *selected_cmd; |
| |
| /*!< VT100 color and cursor position, terminal width.*/ |
| struct shell_vt100_ctx vt100_ctx; |
| |
| /*!< Callback called from shell thread context when unitialization is |
| * completed just before aborting shell thread. |
| */ |
| shell_uninit_cb_t uninit_cb; |
| |
| /*!< When bypass is set, all incoming data is passed to the callback. */ |
| shell_bypass_cb_t bypass; |
| |
| #if defined CONFIG_SHELL_GETOPT |
| /*!< getopt context for a shell backend. */ |
| struct getopt_state getopt_state; |
| #endif |
| |
| uint16_t cmd_buff_len; /*!< Command length.*/ |
| uint16_t cmd_buff_pos; /*!< Command buffer cursor position.*/ |
| |
| uint16_t cmd_tmp_buff_len; /*!< Command length in tmp buffer.*/ |
| |
| /*!< Command input buffer.*/ |
| char cmd_buff[CONFIG_SHELL_CMD_BUFF_SIZE]; |
| |
| /*!< Command temporary buffer.*/ |
| char temp_buff[CONFIG_SHELL_CMD_BUFF_SIZE]; |
| |
| /*!< Printf buffer size.*/ |
| char printf_buff[CONFIG_SHELL_PRINTF_BUFF_SIZE]; |
| |
| volatile union shell_internal internal; /*!< Internal shell data.*/ |
| |
| struct k_poll_signal signals[SHELL_SIGNALS]; |
| |
| /*!< Events that should be used only internally by shell thread. |
| * Event for SHELL_SIGNAL_TXDONE is initialized but unused. |
| */ |
| struct k_poll_event events[SHELL_SIGNALS]; |
| |
| struct k_mutex wr_mtx; |
| k_tid_t tid; |
| }; |
| |
| extern const struct log_backend_api log_backend_shell_api; |
| |
| /** |
| * @brief Flags for setting shell output newline sequence. |
| */ |
| enum shell_flag { |
| SHELL_FLAG_CRLF_DEFAULT = (1<<0), /* Do not map CR or LF */ |
| SHELL_FLAG_OLF_CRLF = (1<<1) /* Map LF to CRLF on output */ |
| }; |
| |
| /** |
| * @brief Shell instance internals. |
| */ |
| struct shell { |
| const char *default_prompt; /*!< shell default prompt. */ |
| |
| const struct shell_transport *iface; /*!< Transport interface.*/ |
| struct shell_ctx *ctx; /*!< Internal context.*/ |
| |
| struct shell_history *history; |
| |
| const enum shell_flag shell_flag; |
| |
| const struct shell_fprintf *fprintf_ctx; |
| |
| struct shell_stats *stats; |
| |
| const struct shell_log_backend *log_backend; |
| |
| LOG_INSTANCE_PTR_DECLARE(log); |
| |
| const char *thread_name; |
| struct k_thread *thread; |
| k_thread_stack_t *stack; |
| }; |
| |
| extern void z_shell_print_stream(const void *user_ctx, const char *data, |
| size_t data_len); |
| /** |
| * @brief Macro for defining a shell instance. |
| * |
| * @param[in] _name Instance name. |
| * @param[in] _prompt Shell default prompt string. |
| * @param[in] _transport_iface Pointer to the transport interface. |
| * @param[in] _log_queue_size Logger processing queue size. |
| * @param[in] _log_timeout Logger thread timeout in milliseconds on full |
| * log queue. If queue is full logger thread is |
| * blocked for given amount of time before log |
| * message is dropped. |
| * @param[in] _shell_flag Shell output newline sequence. |
| */ |
| #define SHELL_DEFINE(_name, _prompt, _transport_iface, \ |
| _log_queue_size, _log_timeout, _shell_flag) \ |
| static const struct shell _name; \ |
| static struct shell_ctx UTIL_CAT(_name, _ctx); \ |
| static uint8_t _name##_out_buffer[CONFIG_SHELL_PRINTF_BUFF_SIZE]; \ |
| Z_SHELL_LOG_BACKEND_DEFINE(_name, _name##_out_buffer, \ |
| CONFIG_SHELL_PRINTF_BUFF_SIZE, \ |
| _log_queue_size, _log_timeout); \ |
| Z_SHELL_HISTORY_DEFINE(_name##_history, CONFIG_SHELL_HISTORY_BUFFER); \ |
| Z_SHELL_FPRINTF_DEFINE(_name##_fprintf, &_name, _name##_out_buffer, \ |
| CONFIG_SHELL_PRINTF_BUFF_SIZE, \ |
| true, z_shell_print_stream); \ |
| LOG_INSTANCE_REGISTER(shell, _name, CONFIG_SHELL_LOG_LEVEL); \ |
| Z_SHELL_STATS_DEFINE(_name); \ |
| static K_KERNEL_STACK_DEFINE(_name##_stack, CONFIG_SHELL_STACK_SIZE); \ |
| static struct k_thread _name##_thread; \ |
| static const STRUCT_SECTION_ITERABLE(shell, _name) = { \ |
| .default_prompt = _prompt, \ |
| .iface = _transport_iface, \ |
| .ctx = &UTIL_CAT(_name, _ctx), \ |
| .history = IS_ENABLED(CONFIG_SHELL_HISTORY) ? \ |
| &_name##_history : NULL, \ |
| .shell_flag = _shell_flag, \ |
| .fprintf_ctx = &_name##_fprintf, \ |
| .stats = Z_SHELL_STATS_PTR(_name), \ |
| .log_backend = Z_SHELL_LOG_BACKEND_PTR(_name), \ |
| LOG_INSTANCE_PTR_INIT(log, shell, _name) \ |
| .thread_name = STRINGIFY(_name), \ |
| .thread = &_name##_thread, \ |
| .stack = _name##_stack \ |
| } |
| |
| /** |
| * @brief Function for initializing a transport layer and internal shell state. |
| * |
| * @param[in] shell Pointer to shell instance. |
| * @param[in] transport_config Transport configuration during initialization. |
| * @param[in] use_colors Enables colored prints. |
| * @param[in] log_backend If true, the console will be used as logger |
| * backend. |
| * @param[in] init_log_level Default severity level for the logger. |
| * |
| * @return Standard error code. |
| */ |
| int shell_init(const struct shell *shell, const void *transport_config, |
| bool use_colors, bool log_backend, uint32_t init_log_level); |
| |
| /** |
| * @brief Uninitializes the transport layer and the internal shell state. |
| * |
| * @param shell Pointer to shell instance. |
| * @param cb Callback called when uninitialization is completed. |
| * |
| * @return Standard error code. |
| */ |
| void shell_uninit(const struct shell *shell, shell_uninit_cb_t cb); |
| |
| /** |
| * @brief Function for starting shell processing. |
| * |
| * @param shell Pointer to the shell instance. |
| * |
| * @return Standard error code. |
| */ |
| int shell_start(const struct shell *shell); |
| |
| /** |
| * @brief Function for stopping shell processing. |
| * |
| * @param shell Pointer to shell instance. |
| * |
| * @return Standard error code. |
| */ |
| int shell_stop(const struct shell *shell); |
| |
| /** |
| * @brief Terminal default text color for shell_fprintf function. |
| */ |
| #define SHELL_NORMAL SHELL_VT100_COLOR_DEFAULT |
| |
| /** |
| * @brief Green text color for shell_fprintf function. |
| */ |
| #define SHELL_INFO SHELL_VT100_COLOR_GREEN |
| |
| /** |
| * @brief Cyan text color for shell_fprintf function. |
| */ |
| #define SHELL_OPTION SHELL_VT100_COLOR_CYAN |
| |
| /** |
| * @brief Yellow text color for shell_fprintf function. |
| */ |
| #define SHELL_WARNING SHELL_VT100_COLOR_YELLOW |
| |
| /** |
| * @brief Red text color for shell_fprintf function. |
| */ |
| #define SHELL_ERROR SHELL_VT100_COLOR_RED |
| |
| /** |
| * @brief printf-like function which sends formatted data stream to the shell. |
| * |
| * This function can be used from the command handler or from threads, but not |
| * from an interrupt context. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] color Printed text color. |
| * @param[in] fmt Format string. |
| * @param[in] ... List of parameters to print. |
| */ |
| void shell_fprintf(const struct shell *shell, enum shell_vt100_color color, |
| const char *fmt, ...); |
| |
| /** |
| * @brief vprintf-like function which sends formatted data stream to the shell. |
| * |
| * This function can be used from the command handler or from threads, but not |
| * from an interrupt context. It is similar to shell_fprintf() but takes a |
| * va_list instead of variable arguments. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] color Printed text color. |
| * @param[in] fmt Format string. |
| * @param[in] args List of parameters to print. |
| */ |
| void shell_vfprintf(const struct shell *shell, enum shell_vt100_color color, |
| const char *fmt, va_list args); |
| |
| /** |
| * @brief Print a line of data in hexadecimal format. |
| * |
| * Each line shows the offset, bytes and then ASCII representation. |
| * |
| * For example: |
| * |
| * 00008010: 20 25 00 20 2f 48 00 08 80 05 00 20 af 46 00 |
| * | %. /H.. ... .F. | |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] offset Offset to show for this line. |
| * @param[in] data Pointer to data. |
| * @param[in] len Length of data. |
| */ |
| void shell_hexdump_line(const struct shell *shell, unsigned int offset, |
| const uint8_t *data, size_t len); |
| |
| /** |
| * @brief Print data in hexadecimal format. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] data Pointer to data. |
| * @param[in] len Length of data. |
| */ |
| void shell_hexdump(const struct shell *shell, const uint8_t *data, size_t len); |
| |
| /** |
| * @brief Print info message to the shell. |
| * |
| * See @ref shell_fprintf. |
| * |
| * @param[in] _sh Pointer to the shell instance. |
| * @param[in] _ft Format string. |
| * @param[in] ... List of parameters to print. |
| */ |
| #define shell_info(_sh, _ft, ...) \ |
| shell_fprintf(_sh, SHELL_INFO, _ft "\n", ##__VA_ARGS__) |
| |
| /** |
| * @brief Print normal message to the shell. |
| * |
| * See @ref shell_fprintf. |
| * |
| * @param[in] _sh Pointer to the shell instance. |
| * @param[in] _ft Format string. |
| * @param[in] ... List of parameters to print. |
| */ |
| #define shell_print(_sh, _ft, ...) \ |
| shell_fprintf(_sh, SHELL_NORMAL, _ft "\n", ##__VA_ARGS__) |
| |
| /** |
| * @brief Print warning message to the shell. |
| * |
| * See @ref shell_fprintf. |
| * |
| * @param[in] _sh Pointer to the shell instance. |
| * @param[in] _ft Format string. |
| * @param[in] ... List of parameters to print. |
| */ |
| #define shell_warn(_sh, _ft, ...) \ |
| shell_fprintf(_sh, SHELL_WARNING, _ft "\n", ##__VA_ARGS__) |
| |
| /** |
| * @brief Print error message to the shell. |
| * |
| * See @ref shell_fprintf. |
| * |
| * @param[in] _sh Pointer to the shell instance. |
| * @param[in] _ft Format string. |
| * @param[in] ... List of parameters to print. |
| */ |
| #define shell_error(_sh, _ft, ...) \ |
| shell_fprintf(_sh, SHELL_ERROR, _ft "\n", ##__VA_ARGS__) |
| |
| /** |
| * @brief Process function, which should be executed when data is ready in the |
| * transport interface. To be used if shell thread is disabled. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| */ |
| void shell_process(const struct shell *shell); |
| |
| /** |
| * @brief Change displayed shell prompt. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] prompt New shell prompt. |
| * |
| * @return 0 Success. |
| * @return -EINVAL Pointer to new prompt is not correct. |
| */ |
| int shell_prompt_change(const struct shell *shell, const char *prompt); |
| |
| /** |
| * @brief Prints the current command help. |
| * |
| * Function will print a help string with: the currently entered command |
| * and subcommands (if they exist). |
| * |
| * @param[in] shell Pointer to the shell instance. |
| */ |
| void shell_help(const struct shell *shell); |
| |
| /* @brief Command's help has been printed */ |
| #define SHELL_CMD_HELP_PRINTED (1) |
| |
| #if defined CONFIG_SHELL_GETOPT |
| /** |
| * @brief Parses the command-line arguments. |
| * |
| * It is based on FreeBSD implementation. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] argc Arguments count. |
| * @param[in] argv Arguments. |
| * @param[in] ostr String containing the legitimate option characters. |
| * |
| * @return If an option was successfully found, function returns |
| * the option character. |
| * @return If options have been detected that is not in @p ostr |
| * function will return '?'. |
| * If function encounters an option with a missing |
| * argument, then the return value depends on the first |
| * character in optstring: if it is ':', then ':' is |
| * returned; otherwise '?' is returned. |
| * @return -1 If all options have been parsed. |
| */ |
| int shell_getopt(const struct shell *shell, int argc, char *const argv[], |
| const char *ostr); |
| |
| /** |
| * @brief Returns shell_getopt state. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * |
| * @return Pointer to struct getopt_state. |
| */ |
| struct getopt_state *shell_getopt_state_get(const struct shell *shell); |
| #endif /* CONFIG_SHELL_GETOPT */ |
| |
| /** @brief Execute command. |
| * |
| * Pass command line to shell to execute. |
| * |
| * Note: This by no means makes any of the commands a stable interface, so |
| * this function should only be used for debugging/diagnostic. |
| * |
| * This function must not be called from shell command context! |
| |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * It can be NULL when the |
| * @kconfig{CONFIG_SHELL_BACKEND_DUMMY} option is enabled. |
| * @param[in] cmd Command to be executed. |
| * |
| * @return Result of the execution |
| */ |
| int shell_execute_cmd(const struct shell *shell, const char *cmd); |
| |
| /** @brief Set root command for all shell instances. |
| * |
| * It allows setting from the code the root command. It is an equivalent of |
| * calling select command with one of the root commands as the argument |
| * (e.g "select log") except it sets command for all shell instances. |
| * |
| * @param cmd String with one of the root commands or null pointer to reset. |
| * |
| * @retval 0 if root command is set. |
| * @retval -EINVAL if invalid root command is provided. |
| */ |
| int shell_set_root_cmd(const char *cmd); |
| |
| /** @brief Set bypass callback. |
| * |
| * Bypass callback is called whenever data is received. Shell is bypassed and |
| * data is passed directly to the callback. Use null to disable bypass functionality. |
| * |
| * @param[in] shell Pointer to the shell instance. |
| * @param[in] bypass Bypass callback or null to disable. |
| */ |
| void shell_set_bypass(const struct shell *shell, shell_bypass_cb_t bypass); |
| |
| /** |
| * @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] val Insert mode. |
| * |
| * @retval 0 or 1: previous value |
| * @retval -EINVAL if shell is NULL. |
| */ |
| 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 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); |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* SHELL_H__ */ |