diff --git a/include/shell/shell.h b/include/shell/shell.h index 186fe3a75dd..2025ca2ef4e 100644 --- a/include/shell/shell.h +++ b/include/shell/shell.h @@ -600,7 +600,9 @@ void shell_print_stream(const void *user_ctx, const char *data, * Note: This by no means makes any of the commands a stable interface, so * this function should only be used for debugging/diagnostic. * - * @param[in] shell Pointer to the shell instance. + * @param[in] shell Pointer to the shell instance. It can be NULL when + * the :option:`CONFIG_SHELL_BACKEND_DUMMY` option is + * enabled. * @param[in] cmd Command to be executed. * * @returns Result of the execution diff --git a/include/shell/shell_dummy.h b/include/shell/shell_dummy.h new file mode 100644 index 00000000000..c39eeb88fca --- /dev/null +++ b/include/shell/shell_dummy.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SHELL_DUMMY_H__ +#define SHELL_DUMMY_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct shell_transport_api shell_dummy_transport_api; + +struct shell_dummy { + bool initialized; +}; + +#define SHELL_DUMMY_DEFINE(_name) \ + static struct shell_dummy _name##_shell_dummy; \ + struct shell_transport _name = { \ + .api = &shell_dummy_transport_api, \ + .ctx = (struct shell_dummy *)&_name##_shell_dummy \ + } + +/** + * @brief This function shall not be used directly. It provides pointer to shell + * dummy backend instance. + * + * Function returns pointer to the shell dummy instance. This instance can be + * next used with shell_execute_cmd function in order to test commands behavior. + * + * @returns Pointer to the shell instance. + */ +const struct shell *shell_backend_dummy_get_ptr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SHELL_DUMMY_H__ */ diff --git a/include/shell/shell_uart.h b/include/shell/shell_uart.h index a1e4b1ba168..17f2d311543 100644 --- a/include/shell/shell_uart.h +++ b/include/shell/shell_uart.h @@ -31,6 +31,16 @@ struct shell_uart { .ctx = (struct shell_uart *)&_name##_shell_uart \ } +/** + * @brief This function provides pointer to shell uart backend instance. + * + * Function returns pointer to the shell uart instance. This instance can be + * next used with shell_execute_cmd function in order to test commands behavior. + * + * @returns Pointer to the shell instance. + */ +const struct shell *shell_backend_uart_get_ptr(void); + #ifdef __cplusplus } #endif diff --git a/subsys/shell/CMakeLists.txt b/subsys/shell/CMakeLists.txt index f364c5854ee..f6b73076411 100644 --- a/subsys/shell/CMakeLists.txt +++ b/subsys/shell/CMakeLists.txt @@ -21,7 +21,12 @@ zephyr_sources_ifdef( zephyr_sources_ifdef( CONFIG_SHELL_BACKEND_SERIAL shell_uart.c - ) +) + +zephyr_sources_ifdef( + CONFIG_SHELL_BACKEND_DUMMY + shell_dummy.c +) zephyr_sources_ifdef( CONFIG_SHELL_CMDS diff --git a/subsys/shell/Kconfig.backends b/subsys/shell/Kconfig.backends index 7ef1b9296b5..982cf762bd2 100644 --- a/subsys/shell/Kconfig.backends +++ b/subsys/shell/Kconfig.backends @@ -21,5 +21,12 @@ config SHELL_BACKEND_SERIAL help Enable serial backends. +config SHELL_BACKEND_DUMMY + bool "Enable dummy backend." + select SERIAL + help + Enable dummy backend which can be used to test commands with no need + for physical transport interface. + endif # SHELL_BACKENDS diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index 535b41cf223..20a47fe399f 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "shell_utils.h" #include "shell_ops.h" #include "shell_wildcard.h" @@ -1748,7 +1749,7 @@ int shell_execute_cmd(const struct shell *shell, const char *cmd) { u16_t cmd_len = shell_strlen(cmd); - if ((cmd == NULL) || (shell == NULL)) { + if (cmd == NULL) { return -ENOEXEC; } @@ -1756,8 +1757,17 @@ int shell_execute_cmd(const struct shell *shell, const char *cmd) return -ENOEXEC; } + if (shell == NULL) { +#if CONFIG_SHELL_BACKEND_DUMMY + shell = shell_backend_dummy_get_ptr(); +#else + return -EINVAL; +#endif + } + strcpy(shell->ctx->cmd_buff, cmd); shell->ctx->cmd_buff_len = cmd_len; + shell->ctx->cmd_buff_pos = cmd_len; return shell_execute(shell); } diff --git a/subsys/shell/shell_dummy.c b/subsys/shell/shell_dummy.c new file mode 100644 index 00000000000..313cc558e9c --- /dev/null +++ b/subsys/shell/shell_dummy.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +SHELL_DUMMY_DEFINE(shell_transport_dummy); +SHELL_DEFINE(dummy_shell, "~$ ", &shell_transport_dummy, 10, + SHELL_FLAG_OLF_CRLF); + +static int init(const struct shell_transport *transport, + const void *config, + shell_transport_handler_t evt_handler, + void *context) +{ + struct shell_dummy *sh_dummy = (struct shell_dummy *)transport->ctx; + + if (sh_dummy->initialized) { + return -EINVAL; + } + + sh_dummy->initialized = true; + + return 0; +} + +static int uninit(const struct shell_transport *transport) +{ + struct shell_dummy *sh_dummy = (struct shell_dummy *)transport->ctx; + + if (sh_dummy->initialized == false) { + return -EINVAL; + } + + sh_dummy->initialized = false; + + return 0; +} + +static int enable(const struct shell_transport *transport, bool blocking) +{ + struct shell_dummy *sh_dummy = (struct shell_dummy *)transport->ctx; + + if (sh_dummy->initialized == false) { + return -EINVAL; + } + + return 0; +} + +static int write(const struct shell_transport *transport, + const void *data, size_t length, size_t *cnt) +{ + struct shell_dummy *sh_dummy = (struct shell_dummy *)transport->ctx; + + if (!sh_dummy->initialized) { + *cnt = 0; + return -EINVAL; + } + + *cnt = length; + return 0; +} + +static int read(const struct shell_transport *transport, + void *data, size_t length, size_t *cnt) +{ + struct shell_dummy *sh_dummy = (struct shell_dummy *)transport->ctx; + + + if (sh_dummy->initialized) { + return -EINVAL; + } + + *cnt = 0; + + return 0; +} + +const struct shell_transport_api shell_dummy_transport_api = { + .init = init, + .uninit = uninit, + .enable = enable, + .write = write, + .read = read +}; + +static int enable_shell_dummy(struct device *arg) +{ + ARG_UNUSED(arg); + shell_init(&dummy_shell, NULL, true, true, LOG_LEVEL_INF); + return 0; +} +SYS_INIT(enable_shell_dummy, POST_KERNEL, 0); + +const struct shell *shell_backend_dummy_get_ptr(void) +{ + return &dummy_shell; +} diff --git a/subsys/shell/shell_uart.c b/subsys/shell/shell_uart.c index 50b25025aae..901b63fc87a 100644 --- a/subsys/shell/shell_uart.c +++ b/subsys/shell/shell_uart.c @@ -100,3 +100,8 @@ static int enable_shell_uart(struct device *arg) return 0; } SYS_INIT(enable_shell_uart, POST_KERNEL, 0); + +const struct shell *shell_backend_uart_get_ptr(void) +{ + return &uart_shell; +}