shell: removing legacy shell
Legacy shell removed in order to avoid maintaining two shells systems. All examples and tests have been migrated to the new shell. Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
parent
bfad9721d2
commit
fd0b7f7767
9 changed files with 4 additions and 952 deletions
|
@ -1,228 +0,0 @@
|
||||||
/* shell.h - Shell header */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_SHELL_SHELL_H_
|
|
||||||
#define ZEPHYR_INCLUDE_SHELL_SHELL_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct device;
|
|
||||||
|
|
||||||
/** @brief Callback called when command is entered.
|
|
||||||
*
|
|
||||||
* @param argc Number of parameters passed.
|
|
||||||
* @param argv Array of option strings. First option is always command name.
|
|
||||||
*
|
|
||||||
* @return 0 in case of success or negative value in case of error.
|
|
||||||
*/
|
|
||||||
typedef int (*shell_cmd_function_t)(int argc, char *argv[]);
|
|
||||||
|
|
||||||
struct shell_cmd {
|
|
||||||
const char *cmd_name;
|
|
||||||
shell_cmd_function_t cb;
|
|
||||||
const char *help;
|
|
||||||
const char *desc;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @brief Callback to get the current prompt.
|
|
||||||
*
|
|
||||||
* @returns Current prompt string.
|
|
||||||
*/
|
|
||||||
typedef const char *(*shell_prompt_function_t)(void);
|
|
||||||
|
|
||||||
/** @brief Callback for custom line2argv parsing
|
|
||||||
*
|
|
||||||
* If this callback is set, command parsing for specified module works only
|
|
||||||
* if it is selected as default module. This is to not break other modules.
|
|
||||||
*
|
|
||||||
* @returns Current prompt string.
|
|
||||||
*/
|
|
||||||
typedef size_t (*shell_line2argv_function_t)(char *str, char *argv[],
|
|
||||||
size_t size);
|
|
||||||
|
|
||||||
struct shell_module {
|
|
||||||
const char *module_name;
|
|
||||||
const struct shell_cmd *commands;
|
|
||||||
shell_prompt_function_t prompt;
|
|
||||||
shell_line2argv_function_t line2argv;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @typedef shell_mcumgr_function_t
|
|
||||||
* @brief Callback that is executed when an mcumgr packet is received over the
|
|
||||||
* shell.
|
|
||||||
*
|
|
||||||
* The packet argument must be exactly what was received over the console,
|
|
||||||
* except the terminating newline must be replaced with '\0'.
|
|
||||||
*
|
|
||||||
* @param line The received mcumgr packet.
|
|
||||||
* @param arg An optional argument.
|
|
||||||
*
|
|
||||||
* @return on success; negative error code on failure.
|
|
||||||
*/
|
|
||||||
typedef int (*shell_mcumgr_function_t)(const char *line, void *arg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Kernel Shell API
|
|
||||||
* @defgroup _shell_api_functions Shell API Functions
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @def SHELL_REGISTER
|
|
||||||
*
|
|
||||||
* @brief Create shell_module object and set it up for boot time initialization.
|
|
||||||
*
|
|
||||||
* @details This macro defines a shell_module object that is automatically
|
|
||||||
* configured by the kernel during system initialization.
|
|
||||||
*
|
|
||||||
* @param _name Module name to be entered in shell console.
|
|
||||||
* @param _commands Array of commands to register.
|
|
||||||
* Shell array entries must be packed to calculate array size correctly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @def SHELL_REGISTER_WITH_PROMPT
|
|
||||||
*
|
|
||||||
* @brief Create shell_module object and set it up for boot time initialization.
|
|
||||||
*
|
|
||||||
* @details This macro defines a shell_module object that is automatically
|
|
||||||
* configured by the kernel during system initialization, in addition to that
|
|
||||||
* this also enables setting a custom prompt handler when the module is
|
|
||||||
* selected.
|
|
||||||
*
|
|
||||||
* @param _name Module name to be entered in shell console.
|
|
||||||
* @param _commands Array of commands to register.
|
|
||||||
* Shell array entries must be packed to calculate array size correctly.
|
|
||||||
* @param _prompt Optional prompt handler to be set when module is selected.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @def SHELL_REGISTER_COMMAND
|
|
||||||
*
|
|
||||||
* @brief Create a standalone command and set it up for boot time
|
|
||||||
* initialization.
|
|
||||||
*
|
|
||||||
* @details This macro defines a shell_cmd object that is automatically
|
|
||||||
* configured by the kernel during system initialization.
|
|
||||||
*
|
|
||||||
* The command will be available in the default module, so it will be available
|
|
||||||
* immediately.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_CONSOLE_SHELL
|
|
||||||
#define SHELL_REGISTER(_name, _commands) \
|
|
||||||
SHELL_REGISTER_WITH_PROMPT_AND_LINE2ARGV(_name, _commands, NULL, NULL)
|
|
||||||
|
|
||||||
#define SHELL_REGISTER_WITH_PROMPT(_name, _commands, _prompt) \
|
|
||||||
SHELL_REGISTER_WITH_PROMPT_AND_LINE2ARGV(_name, _commands, _prompt, NULL)
|
|
||||||
|
|
||||||
#define SHELL_REGISTER_WITH_LINE2ARGV(_name, _commands, _line2argv) \
|
|
||||||
SHELL_REGISTER_WITH_PROMPT_AND_LINE2ARGV(_name, _commands, NULL, \
|
|
||||||
_line2argv)
|
|
||||||
|
|
||||||
#define SHELL_REGISTER_WITH_PROMPT_AND_LINE2ARGV(_name, _commands, _prompt, \
|
|
||||||
_line2argv) \
|
|
||||||
\
|
|
||||||
static struct shell_module (__shell__name) __used \
|
|
||||||
__attribute__((__section__(".shell_module_"))) = { \
|
|
||||||
.module_name = _name, \
|
|
||||||
.commands = _commands, \
|
|
||||||
.prompt = _prompt, \
|
|
||||||
.line2argv = _line2argv, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SHELL_REGISTER_COMMAND(name, callback, _help) \
|
|
||||||
\
|
|
||||||
const struct shell_cmd (__shell__##name) __used \
|
|
||||||
__attribute__((__section__(".shell_cmd_"))) = { \
|
|
||||||
.cmd_name = name, \
|
|
||||||
.cb = callback, \
|
|
||||||
.help = _help \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define SHELL_REGISTER(_name, _commands)
|
|
||||||
#define SHELL_REGISTER_WITH_PROMPT(_name, _commands, _prompt)
|
|
||||||
#define SHELL_REGISTER_COMMAND(_name, _callback, _help)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @brief Initialize shell with optional prompt, NULL in case no prompt is
|
|
||||||
* needed.
|
|
||||||
*
|
|
||||||
* @param prompt Prompt to be printed on serial console.
|
|
||||||
*/
|
|
||||||
void shell_init(const char *prompt);
|
|
||||||
|
|
||||||
/** @brief Optionally register an app default cmd handler.
|
|
||||||
*
|
|
||||||
* @param handler To be called if no cmd found in cmds registered with
|
|
||||||
* shell_init.
|
|
||||||
*/
|
|
||||||
void shell_register_app_cmd_handler(shell_cmd_function_t handler);
|
|
||||||
|
|
||||||
/** @brief Optionally register a custom prompt callback.
|
|
||||||
*
|
|
||||||
* @param handler To be called to get the current prompt.
|
|
||||||
*/
|
|
||||||
void shell_register_prompt_handler(shell_prompt_function_t handler);
|
|
||||||
|
|
||||||
/** @brief Optionally register a default module, to eliminate typing it in
|
|
||||||
* shell console or for backwards compatibility.
|
|
||||||
*
|
|
||||||
* @param name Module name.
|
|
||||||
*/
|
|
||||||
void shell_register_default_module(const char *name);
|
|
||||||
|
|
||||||
/** @brief Configures a callback for received mcumgr packets.
|
|
||||||
*
|
|
||||||
* @param handler The callback to execute when an mcumgr packet is received.
|
|
||||||
* @param arg An optional argument to pass to the callback.
|
|
||||||
*/
|
|
||||||
void shell_register_mcumgr_handler(shell_mcumgr_function_t handler, void *arg);
|
|
||||||
|
|
||||||
/** @brief Execute command line.
|
|
||||||
*
|
|
||||||
* Pass command line to shell to execute. The line cannot be a C string literal
|
|
||||||
* since it will be modified in place, instead a variable can be used:
|
|
||||||
*
|
|
||||||
* char cmd[] = "command";
|
|
||||||
* shell_exec(cmd);
|
|
||||||
*
|
|
||||||
* Note: This by no means makes any of the commands a stable interface, so
|
|
||||||
* this function should only be used for debugging/diagnostic.
|
|
||||||
*
|
|
||||||
* @param line Command line to be executed
|
|
||||||
* @returns Result of the execution
|
|
||||||
*/
|
|
||||||
int shell_exec(char *line);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_CONSOLE_SHELL
|
|
||||||
int shell_run(struct device *dev);
|
|
||||||
#else
|
|
||||||
static inline int shell_run(struct device *dev)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(dev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_SHELL_SHELL_H_ */
|
|
|
@ -14,8 +14,7 @@ CONFIG_NET_BUF_DATA_SIZE=128
|
||||||
CONFIG_IEEE802154=y
|
CONFIG_IEEE802154=y
|
||||||
CONFIG_IEEE802154_RAW_MODE=y
|
CONFIG_IEEE802154_RAW_MODE=y
|
||||||
|
|
||||||
CONFIG_CONSOLE_HANDLER=y
|
CONFIG_SHELL=y
|
||||||
CONFIG_CONSOLE_SHELL=y
|
|
||||||
CONFIG_KERNEL_SHELL=y
|
CONFIG_KERNEL_SHELL=y
|
||||||
|
|
||||||
CONFIG_NET_CONFIG_SETTINGS=y
|
CONFIG_NET_CONFIG_SETTINGS=y
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
CONFIG_PRINTK=y
|
CONFIG_PRINTK=y
|
||||||
CONFIG_SHELL=y
|
CONFIG_SHELL=y
|
||||||
CONFIG_SERIAL=y
|
|
||||||
CONFIG_KERNEL_SHELL=n
|
CONFIG_KERNEL_SHELL=n
|
||||||
|
CONFIG_SHELL_BACKEND_SERIAL=y
|
||||||
CONFIG_OBJECT_TRACING=y
|
CONFIG_OBJECT_TRACING=y
|
||||||
CONFIG_THREAD_MONITOR=y
|
CONFIG_THREAD_MONITOR=y
|
||||||
CONFIG_INIT_STACKS=y
|
CONFIG_INIT_STACKS=y
|
||||||
|
@ -9,8 +9,9 @@ CONFIG_BOOT_BANNER=n
|
||||||
CONFIG_THREAD_NAME=y
|
CONFIG_THREAD_NAME=y
|
||||||
CONFIG_LOG=n
|
CONFIG_LOG=n
|
||||||
CONFIG_SHELL_HISTORY=n
|
CONFIG_SHELL_HISTORY=n
|
||||||
CONFIG_CONSOLE_SHELL_STACKSIZE=1024
|
CONFIG_SHELL_STACK_SIZE=1024
|
||||||
CONFIG_SHELL_CMD_BUFF_SIZE=128
|
CONFIG_SHELL_CMD_BUFF_SIZE=128
|
||||||
CONFIG_SHELL_WILDCARD=n
|
CONFIG_SHELL_WILDCARD=n
|
||||||
CONFIG_SHELL_FOREGROUND_CMDS=n
|
CONFIG_SHELL_FOREGROUND_CMDS=n
|
||||||
CONFIG_SHELL_DYNAMIC_CMDS=n
|
CONFIG_SHELL_DYNAMIC_CMDS=n
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ add_subdirectory(debug)
|
||||||
add_subdirectory(logging)
|
add_subdirectory(logging)
|
||||||
add_subdirectory_ifdef(CONFIG_BT bluetooth)
|
add_subdirectory_ifdef(CONFIG_BT bluetooth)
|
||||||
add_subdirectory_ifdef(CONFIG_CONSOLE_SUBSYS console)
|
add_subdirectory_ifdef(CONFIG_CONSOLE_SUBSYS console)
|
||||||
add_subdirectory_ifdef(CONFIG_CONSOLE_SHELL shell)
|
|
||||||
add_subdirectory_ifdef(CONFIG_SHELL shell)
|
add_subdirectory_ifdef(CONFIG_SHELL shell)
|
||||||
add_subdirectory_ifdef(CONFIG_CPLUSPLUS cpp)
|
add_subdirectory_ifdef(CONFIG_CPLUSPLUS cpp)
|
||||||
add_subdirectory_ifdef(CONFIG_DISK_ACCESS disk)
|
add_subdirectory_ifdef(CONFIG_DISK_ACCESS disk)
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include "net/buf.h"
|
#include "net/buf.h"
|
||||||
#include "shell/legacy_shell.h"
|
|
||||||
#include "mgmt/mgmt.h"
|
#include "mgmt/mgmt.h"
|
||||||
#include "mgmt/serial.h"
|
#include "mgmt/serial.h"
|
||||||
#include "mgmt/buf.h"
|
#include "mgmt/buf.h"
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
zephyr_include_directories_ifdef(CONFIG_CONSOLE_SHELL
|
|
||||||
${ZEPHYR_BASE}/include/drivers
|
|
||||||
)
|
|
||||||
|
|
||||||
zephyr_sources_ifdef(
|
|
||||||
CONFIG_CONSOLE_SHELL
|
|
||||||
shell_service.c
|
|
||||||
legacy_shell.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(modules)
|
add_subdirectory(modules)
|
||||||
|
|
||||||
zephyr_sources_ifdef(
|
zephyr_sources_ifdef(
|
||||||
|
|
|
@ -10,31 +10,6 @@
|
||||||
|
|
||||||
menu "Shell Options"
|
menu "Shell Options"
|
||||||
|
|
||||||
menuconfig CONSOLE_SHELL
|
|
||||||
bool "Enable legacy shell [ Experimental ]"
|
|
||||||
select CONSOLE_HANDLER
|
|
||||||
select CONSOLE_SUBSYS
|
|
||||||
help
|
|
||||||
Shell implementation based on CONSOLE_HANDLER.
|
|
||||||
|
|
||||||
|
|
||||||
if CONSOLE_SHELL
|
|
||||||
|
|
||||||
config CONSOLE_SHELL_STACKSIZE
|
|
||||||
int "Console handler shell stack size"
|
|
||||||
default 2000
|
|
||||||
help
|
|
||||||
Stack size for the console handler shell.
|
|
||||||
|
|
||||||
config CONSOLE_SHELL_MAX_CMD_QUEUED
|
|
||||||
int "Shell's command queue size"
|
|
||||||
default 3
|
|
||||||
help
|
|
||||||
Maximum size of the queue for input commands.
|
|
||||||
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
menuconfig SHELL
|
menuconfig SHELL
|
||||||
bool "Enable shell"
|
bool "Enable shell"
|
||||||
select LOG_RUNTIME_FILTERING
|
select LOG_RUNTIME_FILTERING
|
||||||
|
|
|
@ -1,653 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2015 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Console handler implementation of shell.h API
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <zephyr.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <version.h>
|
|
||||||
|
|
||||||
#include <console.h>
|
|
||||||
#include <drivers/console/console.h>
|
|
||||||
#include <misc/printk.h>
|
|
||||||
#include <misc/util.h>
|
|
||||||
#include "mgmt/serial.h"
|
|
||||||
|
|
||||||
#include <shell/legacy_shell.h>
|
|
||||||
|
|
||||||
#if defined(CONFIG_NATIVE_POSIX_CONSOLE)
|
|
||||||
#include "drivers/console/native_posix_console.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ARGC_MAX 10
|
|
||||||
#define COMMAND_MAX_LEN 50
|
|
||||||
#define MODULE_NAME_MAX_LEN 20
|
|
||||||
/* additional chars are " >" (include '\0' )*/
|
|
||||||
#define PROMPT_SUFFIX 3
|
|
||||||
#define PROMPT_MAX_LEN (MODULE_NAME_MAX_LEN + PROMPT_SUFFIX)
|
|
||||||
|
|
||||||
/* command table is located in the dedicated memory segment (.shell_) */
|
|
||||||
extern struct shell_module __shell_module_start[];
|
|
||||||
extern struct shell_module __shell_module_end[];
|
|
||||||
|
|
||||||
extern struct shell_cmd __shell_cmd_start[];
|
|
||||||
extern struct shell_cmd __shell_cmd_end[];
|
|
||||||
|
|
||||||
#define NUM_OF_SHELL_ENTITIES (__shell_module_end - __shell_module_start)
|
|
||||||
#define NUM_OF_SHELL_CMDS (__shell_cmd_end - __shell_cmd_start)
|
|
||||||
|
|
||||||
static const char *prompt;
|
|
||||||
static char default_module_prompt[PROMPT_MAX_LEN];
|
|
||||||
static struct shell_module *default_module;
|
|
||||||
static bool no_promt;
|
|
||||||
|
|
||||||
#define STACKSIZE CONFIG_CONSOLE_SHELL_STACKSIZE
|
|
||||||
static K_THREAD_STACK_DEFINE(stack, STACKSIZE);
|
|
||||||
static struct k_thread shell_thread;
|
|
||||||
|
|
||||||
#define MAX_CMD_QUEUED CONFIG_CONSOLE_SHELL_MAX_CMD_QUEUED
|
|
||||||
static struct console_input buf[MAX_CMD_QUEUED];
|
|
||||||
|
|
||||||
static struct k_fifo avail_queue;
|
|
||||||
static struct k_fifo cmds_queue;
|
|
||||||
|
|
||||||
static shell_cmd_function_t app_cmd_handler;
|
|
||||||
static shell_prompt_function_t app_prompt_handler;
|
|
||||||
|
|
||||||
static shell_mcumgr_function_t mcumgr_cmd_handler;
|
|
||||||
static void *mcumgr_arg;
|
|
||||||
|
|
||||||
static const char *get_prompt(void)
|
|
||||||
{
|
|
||||||
if (app_prompt_handler) {
|
|
||||||
const char *str;
|
|
||||||
|
|
||||||
str = app_prompt_handler();
|
|
||||||
if (str) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (default_module) {
|
|
||||||
if (default_module->prompt) {
|
|
||||||
const char *ret;
|
|
||||||
|
|
||||||
ret = default_module->prompt();
|
|
||||||
if (ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return default_module_prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void line_queue_init(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_CMD_QUEUED; i++) {
|
|
||||||
k_fifo_put(&avail_queue, &buf[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t line2argv(char *str, char *argv[], size_t size)
|
|
||||||
{
|
|
||||||
size_t argc = 0;
|
|
||||||
|
|
||||||
if (!strlen(str)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*str && *str == ' ') {
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*str) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[argc++] = str;
|
|
||||||
|
|
||||||
while ((str = strchr(str, ' '))) {
|
|
||||||
*str++ = '\0';
|
|
||||||
|
|
||||||
while (*str && *str == ' ') {
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*str) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[argc++] = str;
|
|
||||||
|
|
||||||
if (argc == size) {
|
|
||||||
printk("Too many parameters (max %zu)\n", size - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keep it POSIX style where argv[argc] is required to be NULL */
|
|
||||||
argv[argc] = NULL;
|
|
||||||
|
|
||||||
return argc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct shell_module *get_destination_module(const char *module_str)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_OF_SHELL_ENTITIES; i++) {
|
|
||||||
if (!strncmp(module_str,
|
|
||||||
__shell_module_start[i].module_name,
|
|
||||||
MODULE_NAME_MAX_LEN)) {
|
|
||||||
return &__shell_module_start[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int show_cmd_help(const struct shell_cmd *cmd, bool full)
|
|
||||||
{
|
|
||||||
printk("Usage: %s %s\n", cmd->cmd_name, cmd->help ? cmd->help : "");
|
|
||||||
|
|
||||||
if (full && cmd->desc) {
|
|
||||||
printk("%s\n", cmd->desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_module_commands(struct shell_module *module)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
printk("help\n");
|
|
||||||
|
|
||||||
for (i = 0; module->commands[i].cmd_name; i++) {
|
|
||||||
printk("%-28s %s\n",
|
|
||||||
module->commands[i].cmd_name,
|
|
||||||
module->commands[i].help ?
|
|
||||||
module->commands[i].help : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct shell_cmd *get_cmd(const struct shell_cmd cmds[],
|
|
||||||
const char *cmd_str)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; cmds[i].cmd_name; i++) {
|
|
||||||
if (!strcmp(cmd_str, cmds[i].cmd_name)) {
|
|
||||||
return &cmds[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct shell_cmd *get_module_cmd(struct shell_module *module,
|
|
||||||
const char *cmd_str)
|
|
||||||
{
|
|
||||||
return get_cmd(module->commands, cmd_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct shell_cmd *get_standalone(const char *command)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_OF_SHELL_CMDS; i++) {
|
|
||||||
if (!strcmp(command, __shell_cmd_start[i].cmd_name)) {
|
|
||||||
return &__shell_cmd_start[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle internal 'help' command
|
|
||||||
*/
|
|
||||||
static int cmd_help(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct shell_module *module = default_module;
|
|
||||||
|
|
||||||
/* help per command */
|
|
||||||
if (argc > 1) {
|
|
||||||
const struct shell_cmd *cmd;
|
|
||||||
const char *cmd_str;
|
|
||||||
|
|
||||||
module = get_destination_module(argv[1]);
|
|
||||||
if (module) {
|
|
||||||
if (argc == 2) {
|
|
||||||
goto module_help;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_str = argv[2];
|
|
||||||
} else {
|
|
||||||
cmd_str = argv[1];
|
|
||||||
module = default_module;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!module) {
|
|
||||||
cmd = get_standalone(cmd_str);
|
|
||||||
if (cmd) {
|
|
||||||
return show_cmd_help(cmd, true);
|
|
||||||
}
|
|
||||||
printk("No help found for '%s'\n", cmd_str);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
cmd = get_module_cmd(module, cmd_str);
|
|
||||||
if (cmd) {
|
|
||||||
return show_cmd_help(cmd, true);
|
|
||||||
}
|
|
||||||
printk("Unknown command '%s'\n", cmd_str);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_help:
|
|
||||||
/* help per module */
|
|
||||||
if (module) {
|
|
||||||
print_module_commands(module);
|
|
||||||
printk("\nEnter 'exit' to leave current module.\n");
|
|
||||||
} else { /* help for all entities */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
printk("[Modules]\n");
|
|
||||||
|
|
||||||
if (NUM_OF_SHELL_ENTITIES == 0) {
|
|
||||||
printk("No registered modules.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_OF_SHELL_ENTITIES; i++) {
|
|
||||||
printk("%s\n", __shell_module_start[i].module_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("\n[Commands]\n");
|
|
||||||
|
|
||||||
if (NUM_OF_SHELL_CMDS == 0) {
|
|
||||||
printk("No registered commands.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_OF_SHELL_CMDS; i++) {
|
|
||||||
printk("%s\n", __shell_cmd_start[i].cmd_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("\nTo select a module, enter 'select <module name>'.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int set_default_module(const char *name)
|
|
||||||
{
|
|
||||||
struct shell_module *module;
|
|
||||||
|
|
||||||
if (strlen(name) > MODULE_NAME_MAX_LEN) {
|
|
||||||
printk("Module name %s is too long, default is not changed\n",
|
|
||||||
name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
module = get_destination_module(name);
|
|
||||||
|
|
||||||
if (!module) {
|
|
||||||
printk("Illegal module %s, default is not changed\n", name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
default_module = module;
|
|
||||||
|
|
||||||
strncpy(default_module_prompt, name, MODULE_NAME_MAX_LEN);
|
|
||||||
strcat(default_module_prompt, "> ");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_select(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc == 1) {
|
|
||||||
default_module = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return set_default_module(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_exit(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc == 1) {
|
|
||||||
default_module = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_noprompt(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
no_promt = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SHELL_CMD_NOPROMPT "noprompt"
|
|
||||||
SHELL_REGISTER_COMMAND(SHELL_CMD_NOPROMPT, cmd_noprompt,
|
|
||||||
"Disable shell prompt");
|
|
||||||
|
|
||||||
static const struct shell_cmd *get_internal(const char *command)
|
|
||||||
{
|
|
||||||
static const struct shell_cmd internal_commands[] = {
|
|
||||||
{ "help", cmd_help, "[command]" },
|
|
||||||
{ "select", cmd_select, "[module]" },
|
|
||||||
{ "exit", cmd_exit, NULL },
|
|
||||||
{ NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
return get_cmd(internal_commands, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shell_register_mcumgr_handler(shell_mcumgr_function_t handler, void *arg)
|
|
||||||
{
|
|
||||||
mcumgr_cmd_handler = handler;
|
|
||||||
mcumgr_arg = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
int shell_exec(char *line)
|
|
||||||
{
|
|
||||||
char *argv[ARGC_MAX + 1], **argv_start = argv;
|
|
||||||
const struct shell_cmd *cmd;
|
|
||||||
int argc, err;
|
|
||||||
|
|
||||||
if (default_module && default_module->line2argv) {
|
|
||||||
argc = default_module->line2argv(line, argv, ARRAY_SIZE(argv));
|
|
||||||
} else {
|
|
||||||
argc = line2argv(line, argv, ARRAY_SIZE(argv));
|
|
||||||
}
|
|
||||||
if (!argc) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = get_internal(argv[0]);
|
|
||||||
if (cmd) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = get_standalone(argv[0]);
|
|
||||||
if (cmd) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc == 1 && !default_module && NUM_OF_SHELL_CMDS == 0) {
|
|
||||||
printk("No module selected. Use 'select' or 'help'.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (default_module) {
|
|
||||||
cmd = get_module_cmd(default_module, argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cmd && argc > 1) {
|
|
||||||
struct shell_module *module;
|
|
||||||
|
|
||||||
module = get_destination_module(argv[0]);
|
|
||||||
if (module) {
|
|
||||||
cmd = get_module_cmd(module, argv[1]);
|
|
||||||
if (cmd) {
|
|
||||||
argc--;
|
|
||||||
argv_start++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cmd) {
|
|
||||||
if (app_cmd_handler) {
|
|
||||||
return app_cmd_handler(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("Unrecognized command: %s\n", argv[0]);
|
|
||||||
printk("Type 'help' for list of available commands\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
err = cmd->cb(argc, argv_start);
|
|
||||||
if (err < 0) {
|
|
||||||
show_cmd_help(cmd, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shell(void *p1, void *p2, void *p3)
|
|
||||||
{
|
|
||||||
bool skip_prompt = false;
|
|
||||||
|
|
||||||
ARG_UNUSED(p1);
|
|
||||||
ARG_UNUSED(p2);
|
|
||||||
ARG_UNUSED(p3);
|
|
||||||
|
|
||||||
printk("Zephyr Shell, Zephyr version: %s\n", KERNEL_VERSION_STRING);
|
|
||||||
printk("Type 'help' for a list of available commands\n");
|
|
||||||
while (1) {
|
|
||||||
struct console_input *cmd;
|
|
||||||
|
|
||||||
if (!no_promt && !skip_prompt) {
|
|
||||||
printk("%s", get_prompt());
|
|
||||||
#if defined(CONFIG_NATIVE_POSIX_CONSOLE)
|
|
||||||
/* The native printk driver is line buffered */
|
|
||||||
posix_flush_stdout();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = k_fifo_get(&cmds_queue, K_FOREVER);
|
|
||||||
|
|
||||||
/* If the received line is an mcumgr frame, divert it to the
|
|
||||||
* mcumgr handler. Don't print the shell prompt this time, as
|
|
||||||
* that will interfere with the mcumgr response.
|
|
||||||
*/
|
|
||||||
if (mcumgr_cmd_handler != NULL && cmd->is_mcumgr) {
|
|
||||||
mcumgr_cmd_handler(cmd->line, mcumgr_arg);
|
|
||||||
skip_prompt = true;
|
|
||||||
} else {
|
|
||||||
shell_exec(cmd->line);
|
|
||||||
skip_prompt = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
k_fifo_put(&avail_queue, cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct shell_module *get_completion_module(char *str,
|
|
||||||
char **command_prefix)
|
|
||||||
{
|
|
||||||
char dest_str[MODULE_NAME_MAX_LEN];
|
|
||||||
struct shell_module *dest;
|
|
||||||
char *start;
|
|
||||||
|
|
||||||
/* remove ' ' at the beginning of the line */
|
|
||||||
while (*str && *str == ' ') {
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*str) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = str;
|
|
||||||
|
|
||||||
if (default_module) {
|
|
||||||
dest = default_module;
|
|
||||||
/* caller function already checks str len and put '\0' */
|
|
||||||
*command_prefix = str;
|
|
||||||
} else {
|
|
||||||
dest = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In case of a default module: only one parameter is possible.
|
|
||||||
* Otherwise, only two parameters are possibles.
|
|
||||||
*/
|
|
||||||
str = strchr(str, ' ');
|
|
||||||
if (default_module) {
|
|
||||||
return str ? NULL : dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!str) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((str - start + 1) >= MODULE_NAME_MAX_LEN) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(dest_str, start, (str - start + 1));
|
|
||||||
dest_str[str - start] = '\0';
|
|
||||||
dest = get_destination_module(dest_str);
|
|
||||||
if (!dest) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
str++;
|
|
||||||
|
|
||||||
/* caller func has already checked str len and put '\0' at the end */
|
|
||||||
*command_prefix = str;
|
|
||||||
str = strchr(str, ' ');
|
|
||||||
|
|
||||||
/* only two parameters are possibles in case of no default module */
|
|
||||||
return str ? NULL : dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8_t completion(char *line, u8_t len)
|
|
||||||
{
|
|
||||||
const char *first_match = NULL;
|
|
||||||
int common_chars = -1, space = 0;
|
|
||||||
int i, command_len;
|
|
||||||
const struct shell_module *module;
|
|
||||||
char *command_prefix;
|
|
||||||
|
|
||||||
if (len >= (MODULE_NAME_MAX_LEN + COMMAND_MAX_LEN - 1)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* line to completion is not ended by '\0' as the line that gets from
|
|
||||||
* k_fifo_get function
|
|
||||||
*/
|
|
||||||
line[len] = '\0';
|
|
||||||
module = get_completion_module(line, &command_prefix);
|
|
||||||
if (!module) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
command_len = strlen(command_prefix);
|
|
||||||
|
|
||||||
for (i = 0; module->commands[i].cmd_name; i++) {
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (strncmp(command_prefix,
|
|
||||||
module->commands[i].cmd_name, command_len)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!first_match) {
|
|
||||||
first_match = module->commands[i].cmd_name;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* more commands match, print first match */
|
|
||||||
if (first_match && (common_chars < 0)) {
|
|
||||||
printk("\n%s\n", first_match);
|
|
||||||
common_chars = strlen(first_match);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cut common part of matching names */
|
|
||||||
for (j = 0; j < common_chars; j++) {
|
|
||||||
if (first_match[j] != module->commands[i].cmd_name[j]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
common_chars = j;
|
|
||||||
|
|
||||||
printk("%s\n", module->commands[i].cmd_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no match, do nothing */
|
|
||||||
if (!first_match) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common_chars >= 0) {
|
|
||||||
/* multiple match, restore prompt */
|
|
||||||
printk("%s", get_prompt());
|
|
||||||
printk("%s", line);
|
|
||||||
} else {
|
|
||||||
common_chars = strlen(first_match);
|
|
||||||
space = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* complete common part */
|
|
||||||
for (i = command_len; i < common_chars; i++) {
|
|
||||||
printk("%c", first_match[i]);
|
|
||||||
line[len++] = first_match[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for convenience add space after command */
|
|
||||||
if (space) {
|
|
||||||
printk(" ");
|
|
||||||
line[len] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return common_chars - command_len + space;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void shell_init(const char *str)
|
|
||||||
{
|
|
||||||
k_fifo_init(&cmds_queue);
|
|
||||||
k_fifo_init(&avail_queue);
|
|
||||||
|
|
||||||
line_queue_init();
|
|
||||||
|
|
||||||
prompt = str ? str : "";
|
|
||||||
|
|
||||||
k_thread_create(&shell_thread, stack, STACKSIZE, shell, NULL, NULL,
|
|
||||||
NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
|
|
||||||
|
|
||||||
/* Register console handler */
|
|
||||||
console_register_line_input(&avail_queue, &cmds_queue, completion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Optionally register an app default cmd handler.
|
|
||||||
*
|
|
||||||
* @param handler To be called if no cmd found in cmds registered with
|
|
||||||
* shell_init.
|
|
||||||
*/
|
|
||||||
void shell_register_app_cmd_handler(shell_cmd_function_t handler)
|
|
||||||
{
|
|
||||||
app_cmd_handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shell_register_prompt_handler(shell_prompt_function_t handler)
|
|
||||||
{
|
|
||||||
app_prompt_handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shell_register_default_module(const char *name)
|
|
||||||
{
|
|
||||||
int err = set_default_module(name);
|
|
||||||
|
|
||||||
if (!err) {
|
|
||||||
printk("\n%s", default_module_prompt);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Shell framework services
|
|
||||||
*
|
|
||||||
* This module initiates shell.
|
|
||||||
* Includes also adding basic framework commands to shell commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <misc/printk.h>
|
|
||||||
#include <shell/legacy_shell.h>
|
|
||||||
#include <init.h>
|
|
||||||
|
|
||||||
#define SHELL_PROMPT "shell> "
|
|
||||||
|
|
||||||
int shell_run(struct device *dev)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(dev);
|
|
||||||
|
|
||||||
shell_init(SHELL_PROMPT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SYS_INIT(shell_run, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
|
Loading…
Add table
Add a link
Reference in a new issue