sdk-hwV1.3/lichee/xr806/appos/project/common/cmd/cmd_shell.h

372 lines
9.8 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CMD_SHELL_H_
#define _CMD_SHELL_H_
#include "cmd_util.h"
#include "errno.h"
//#include "zephyr/types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct shell {
};
struct shell_static_args {
uint8_t mandatory; /*!< Number of mandatory arguments. */
uint8_t optional; /*!< Number of optional arguments. */
};
/**
* @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,
int argc, char **argv);
struct shell_cmd_entry {
};
/*
* @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 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.
* @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 ? _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 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.
* @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 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 Define ending subcommands set.
*
*/
#define SHELL_SUBCMD_SET_END {NULL}
/**
* @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__ \
}
#define SHELL_CMD_ARG_REGISTER(a,b,c,d,e,f)
#define SHELL_CMD_REGISTER(syntax, subcmd, help, handler) \
SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, 0, 0)
#define ARGC_MAX (12)
#define SHELL_CMD_HELP_PRINTED (1)
/* cmd format: <command-name> <arg>... */
static enum cmd_status cmd_exec_shell(char *cmd, const struct shell_static_entry *cdata, int count)
{
int i;
// char *args;
const struct shell_static_entry *cdata1 = cdata;
// args = cmd_strchr(cmd, ' ');
// if (args) {
// *args++ = '\0'; /* has arguments */
// }
int argc;
char *argv[ARGC_MAX];
argc = cmd_parse_argv(cmd, argv, ARGC_MAX);
for (i = 0; i < count; ++i, ++cdata) {
if (cmd_strcmp(cmd, cdata->syntax) == 0) {
enum cmd_status ret = -1;
if ((argc > (cdata->args.mandatory + cdata->args.optional))
|| (argc < cdata->args.mandatory)) {
CMD_ERR("invalid param number %d\n", argc);
return CMD_STATUS_INVALID_ARG;
}
if (cdata->handler)
ret = cdata->handler(NULL, argc, argv);
else
CMD_ERR("null handler for command %s\n", cdata1->syntax);
if ((ret == SHELL_CMD_HELP_PRINTED) || (ret == -ENOEXEC)) {
CMD_DBG("command arg: %s\n", cdata->help);
return CMD_STATUS_INVALID_ARG;
} else if (ret != 0)
return CMD_STATUS_FAIL;
else
return CMD_STATUS_OK;
}
}
CMD_ERR("unknown cmd '%s'\n", cmd);
for (i = 0; i < count; ++i, ++cdata1) {
CMD_DBG("%s %s\n", cdata1->syntax, cdata1->help ? cdata1->help : "");
}
return CMD_STATUS_UNKNOWN_CMD;
}
extern void print_hex_dump_bytes(const void *addr, unsigned int len);
#define shell_error(shell, fmt, arg...) (void)shell; CMD_ERR(fmt"\n", ##arg)
#define shell_print(shell, fmt, arg...) (void)shell; CMD_DBG(fmt"\n", ##arg)
#define shell_hexdump(shell, data, len) (void)shell; print_hex_dump_bytes(data, len)
#define shell_help(shell) (void)shell;
#if 0
static int char2hex(char c, u8_t *x)
{
if (c >= '0' && c <= '9') {
*x = c - '0';
} else if (c >= 'a' && c <= 'f') {
*x = c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
*x = c - 'A' + 10;
} else {
return -EINVAL;
}
return 0;
}
static int hex2char(u8_t x, char *c)
{
if (x <= 9) {
*c = x + '0';
} else if (x >= 10 && x <= 15) {
*c = x - 10 + 'a';
} else {
return -EINVAL;
}
return 0;
}
static size_t hex2bin(const char *hex, size_t hexlen, u8_t *buf, size_t buflen)
{
u8_t dec;
if (buflen < hexlen / 2 + hexlen % 2) {
return 0;
}
/* if hexlen is uneven, insert leading zero nibble */
if (hexlen % 2) {
if (char2hex(hex[0], &dec) < 0) {
return 0;
}
buf[0] = dec;
hex++;
buf++;
}
/* regular hex conversion */
for (size_t i = 0; i < hexlen / 2; i++) {
if (char2hex(hex[2 * i], &dec) < 0) {
return 0;
}
buf[i] = dec << 4;
if (char2hex(hex[2 * i + 1], &dec) < 0) {
return 0;
}
buf[i] += dec;
}
return hexlen / 2 + hexlen % 2;
}
static size_t bin2hex(const u8_t *buf, size_t buflen, char *hex, size_t hexlen)
{
if ((hexlen + 1) < buflen * 2) {
return 0;
}
for (size_t i = 0; i < buflen; i++) {
if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
return 0;
}
if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
return 0;
}
}
hex[2 * buflen] = '\0';
return 2 * buflen;
}
static int bt_addr_from_str(const char *str, bt_addr_t *addr)
{
int i, j;
u8_t tmp;
if (strlen(str) != 17U) {
return -EINVAL;
}
for (i = 5, j = 1; *str != '\0'; str++, j++) {
if (!(j % 3) && (*str != ':')) {
return -EINVAL;
} else if (*str == ':') {
i--;
continue;
}
addr->val[i] = addr->val[i] << 4;
if (char2hex(*str, &tmp) < 0) {
return -EINVAL;
}
addr->val[i] |= tmp;
}
return 0;
}
static int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr)
{
int err;
err = bt_addr_from_str(str, &addr->a);
if (err < 0) {
return err;
}
if (!strcmp(type, "public") || !strcmp(type, "(public)")) {
addr->type = BT_ADDR_LE_PUBLIC;
} else if (!strcmp(type, "random") || !strcmp(type, "(random)")) {
addr->type = BT_ADDR_LE_RANDOM;
} else if (!strcmp(type, "public-id") || !strcmp(type, "(public-id)")) {
addr->type = BT_ADDR_LE_PUBLIC_ID;
} else if (!strcmp(type, "random-id") || !strcmp(type, "(random-id)")) {
addr->type = BT_ADDR_LE_RANDOM_ID;
} else {
return -EINVAL;
}
return 0;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* _CMD_SHELL_H_ */