Ai-Thinker-Open_RTL8710BX_A.../Living_SDK/tools/cli/cli.c
2020-06-18 22:04:32 +08:00

1174 lines
27 KiB
C
Executable file

/*
* Copyright (C) 2015-2019 Alibaba Group Holding Limited
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <aos/aos.h>
#ifdef CONFIG_AOS_CLI
#define RET_CHAR '\n'
#define END_CHAR '\r'
#define PROMPT "# "
#define EXIT_MSG "exit"
static struct cli_st *cli = NULL;
static int cliexit = 0;
char esc_tag[64] = {0};
static uint8_t esc_tag_len = 0;
extern void hal_reboot(void);
extern void log_cli_init(void);
#ifdef CONFIG_AOS_CLI_BOARD
extern int board_cli_init(void);
#endif
#ifdef VCALL_RHINO
extern uint32_t krhino_version_get(void);
#endif
extern int32_t aos_uart_send(void *data, uint32_t size, uint32_t timeout);
extern int32_t aos_uart_recv(void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout);
int cli_getchar(char *inbuf);
int cli_putstr(char *msg);
/* Find the command 'name' in the cli commands table.
* If len is 0 then full match will be performed else upto len bytes.
* Returns: a pointer to the corresponding cli_command struct or NULL.
*/
static const struct cli_command *lookup_command(char *name, int len)
{
int i = 0;
int n = 0;
while (i < MAX_COMMANDS && n < cli->num_commands)
{
if (cli->commands[i]->name == NULL)
{
i++;
continue;
}
/* See if partial or full match is expected */
if (len != 0)
{
if (!strncmp(cli->commands[i]->name, name, len))
{
return cli->commands[i];
}
}
else
{
if (!strcmp(cli->commands[i]->name, name))
{
return cli->commands[i];
}
}
i++;
n++;
}
return NULL;
}
/*proc one cli cmd and to run the according funtion
* Returns: 0 on success:
1 fail
*/
static int proc_onecmd(int argc, char *argv[])
{
int i = 0;
const char *p;
const struct cli_command *command = NULL;
if (argc < 1)
{
return 0;
}
if (!cli->echo_disabled)
{
csp_printf("\r\n");
fflush(stdout);
}
/*
* Some comamands can allow extensions like foo.a, foo.b and hence
* compare commands before first dot.
*/
i = ((p = strchr(argv[0], '.')) == NULL) ? 0 : (p - argv[0]);
command = lookup_command(argv[0], i);
if (command == NULL)
{
return 1;
}
cli->outbuf = aos_malloc(OUTBUF_SIZE);
if (NULL == cli->outbuf)
{
cli_putstr("Error! cli alloc mem fail!\r\n");
return 1;
}
memset(cli->outbuf, 0, OUTBUF_SIZE);
command->function(cli->outbuf, OUTBUF_SIZE, argc, argv);
cli_putstr(cli->outbuf);
aos_free(cli->outbuf);
cli->outbuf = NULL;
return 0;
}
/* Parse input line and locate arguments (if any), keeping count of the number
* of arguments and their locations. Look up and call the corresponding cli
* function if one is found and pass it the argv array.
*
* Returns: 0 on success: the input line contained at least a function name and
* that function exists and was called.
* 1 on lookup failure: there is no corresponding function for the
* input line.
* 2 on invalid syntax: the arguments list couldn't be parsed
*/
static int handle_input(char *inbuf)
{
struct
{
unsigned inArg : 1;
unsigned inQuote : 1;
unsigned done : 1;
} stat;
static char *argvall[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
int argcall[CLI_MAX_ONCECMD_NUM] = {0};
/*
static char *argv[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
int argc = 0;*/
int cmdnum = 0;
int *pargc = &argcall[0];
int i = 0;
int ret = 0;
memset((void *)&argvall, 0, sizeof(argvall));
memset((void *)&argcall, 0, sizeof(argcall));
memset(&stat, 0, sizeof(stat));
do
{
switch (inbuf[i])
{
case '\0':
if (stat.inQuote)
{
return 2;
}
stat.done = 1;
break;
case '"':
if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg)
{
memcpy(&inbuf[i - 1], &inbuf[i], strlen(&inbuf[i]) + 1);
--i;
break;
}
if (!stat.inQuote && stat.inArg)
{
break;
}
if (stat.inQuote && !stat.inArg)
{
return 2;
}
if (!stat.inQuote && !stat.inArg)
{
stat.inArg = 1;
stat.inQuote = 1;
(*pargc)++;
argvall[cmdnum][(*pargc) - 1] = &inbuf[i + 1];
}
else if (stat.inQuote && stat.inArg)
{
stat.inArg = 0;
stat.inQuote = 0;
inbuf[i] = '\0';
}
break;
case ' ':
if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg)
{
memcpy(&inbuf[i - 1], &inbuf[i],
strlen(&inbuf[i]) + 1);
--i;
break;
}
if (!stat.inQuote && stat.inArg)
{
stat.inArg = 0;
inbuf[i] = '\0';
}
break;
case ';':
if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg)
{
memcpy(&inbuf[i - 1], &inbuf[i],
strlen(&inbuf[i]) + 1);
--i;
break;
}
if (stat.inQuote)
{
return 2;
}
if (!stat.inQuote && stat.inArg)
{
stat.inArg = 0;
inbuf[i] = '\0';
if (*pargc)
{
if (++cmdnum < CLI_MAX_ONCECMD_NUM)
{
pargc = &argcall[cmdnum];
}
}
}
break;
default:
if (!stat.inArg)
{
stat.inArg = 1;
(*pargc)++;
argvall[cmdnum][(*pargc) - 1] = &inbuf[i];
}
break;
}
} while (!stat.done && ++i < INBUF_SIZE && cmdnum < CLI_MAX_ONCECMD_NUM && (*pargc) < CLI_MAX_ARG_NUM);
if (stat.inQuote)
{
return 2;
}
for (i = 0; i <= cmdnum && i < CLI_MAX_ONCECMD_NUM; i++)
{
ret |= proc_onecmd(argcall[i], argvall[i]);
}
return ret;
}
/* Perform basic tab-completion on the input buffer by string-matching the
* current input line against the cli functions table. The current input line
* is assumed to be NULL-terminated.
*/
static void tab_complete(char *inbuf, unsigned int *bp)
{
int i, n, m;
const char *fm = NULL;
aos_cli_printf("\r\n");
/* show matching commands */
for (i = 0, n = 0, m = 0; i < MAX_COMMANDS && n < cli->num_commands;
i++)
{
if (cli->commands[i]->name != NULL)
{
if (!strncmp(inbuf, cli->commands[i]->name, *bp))
{
m++;
if (m == 1)
{
fm = cli->commands[i]->name;
}
else if (m == 2)
aos_cli_printf("%s %s ", fm,
cli->commands[i]->name);
else
aos_cli_printf("%s ",
cli->commands[i]->name);
}
n++;
}
}
/* there's only one match, so complete the line */
if (m == 1 && fm)
{
n = strlen(fm) - *bp;
if (*bp + n < INBUF_SIZE)
{
memcpy(inbuf + *bp, fm + *bp, n);
*bp += n;
inbuf[(*bp)++] = ' ';
inbuf[*bp] = '\0';
}
}
/* just redraw input line */
aos_cli_printf("%s%s", PROMPT, inbuf);
}
#if (AOS_CLI_MINI_SIZE <= 0)
static void cli_history_input(void)
{
char *inbuf = cli->inbuf;
int charnum = strlen(cli->inbuf) + 1;
int his_cur = cli->his_cur;
int left_num = INBUF_SIZE - his_cur;
char lastchar;
int tmp_idx;
cli->his_idx = his_cur;
if (left_num >= charnum)
{
tmp_idx = his_cur + charnum - 1;
lastchar = cli->history[tmp_idx];
strncpy(&(cli->history[his_cur]), inbuf, charnum);
}
else
{
tmp_idx = (his_cur + charnum - 1) % INBUF_SIZE;
lastchar = cli->history[tmp_idx];
strncpy(&(cli->history[his_cur]), inbuf, left_num);
strncpy(&(cli->history[0]), inbuf + left_num, charnum - left_num);
}
tmp_idx = (tmp_idx + 1) % INBUF_SIZE;
cli->his_cur = tmp_idx;
/*overwrite*/
if ('\0' != lastchar)
{
while (cli->history[tmp_idx] != '\0')
{
cli->history[tmp_idx] = '\0';
tmp_idx = (tmp_idx + 1) % INBUF_SIZE;
}
}
}
static void cli_up_history(char *inaddr)
{
int index;
int lastindex = 0;
lastindex = cli->his_idx;
index = (cli->his_idx - 1 + INBUF_SIZE) % INBUF_SIZE;
while ((cli->history[index] == '\0') && (index != cli->his_idx))
{
index = (index - 1 + INBUF_SIZE) % INBUF_SIZE;
}
if (index != cli->his_idx)
{
while (cli->history[index] != '\0')
{
index = (index - 1 + INBUF_SIZE) % INBUF_SIZE;
}
index = (index + 1) % INBUF_SIZE;
}
cli->his_idx = index;
while (cli->history[lastindex] != '\0')
{
*inaddr++ = cli->history[lastindex];
lastindex = (lastindex + 1) % INBUF_SIZE;
}
*inaddr = '\0';
return;
}
static void cli_down_history(char *inaddr)
{
int index;
int lastindex = 0;
lastindex = cli->his_idx;
index = cli->his_idx;
while ((cli->history[index] != '\0'))
{
index = (index + 1) % INBUF_SIZE;
}
if (index != cli->his_idx)
{
while (cli->history[index] == '\0')
{
index = (index + 1) % INBUF_SIZE;
}
}
cli->his_idx = index;
while (cli->history[lastindex] != '\0')
{
*inaddr++ = cli->history[lastindex];
lastindex = (lastindex + 1) % INBUF_SIZE;
}
*inaddr = '\0';
return;
}
#endif
/* Get an input line.
*
* Returns: 1 if there is input, 0 if the line should be ignored.
*/
static int get_input(char *inbuf, unsigned int *bp)
{
char c;
int esc = 0, key1 = -1, key2 = -1;
if (inbuf == NULL)
{
aos_cli_printf("inbuf_null\r\n");
return 0;
}
while (cli_getchar(&c) == 1)
{
if (c == RET_CHAR || c == END_CHAR)
{ /* end of input line */
inbuf[*bp] = '\0';
*bp = 0;
return 1;
}
if (c == 0x1b)
{ /* escape sequence */
esc = 1;
key1 = -1;
key2 = -1;
continue;
}
if (esc)
{
if (key1 < 0)
{
key1 = c;
if (key1 != 0x5b)
{
/* not '[' */
inbuf[(*bp)] = 0x1b;
(*bp)++;
inbuf[*bp] = key1;
(*bp)++;
if (!cli->echo_disabled)
{
csp_printf("\x1b%c", key1);
fflush(stdout);
}
esc = 0; /* quit escape sequence */
}
continue;
}
if (key2 < 0)
{
key2 = c;
if (key2 == 't')
{
esc_tag[0] = 0x1b;
esc_tag[1] = key1;
esc_tag_len = 2;
}
}
if (key2 != 0x41 && key2 != 0x42 && key2 != 't')
{
/*unsupported esc sequence*/
inbuf[(*bp)] = 0x1b;
(*bp)++;
inbuf[*bp] = key1;
(*bp)++;
inbuf[*bp] = key2;
(*bp)++;
if (!cli->echo_disabled)
{
csp_printf("\x1b%c%c", key1, key2);
fflush(stdout);
}
esc_tag[0] = '\x0';
esc_tag_len = 0;
esc = 0; /* quit escape sequence */
continue;
}
#if (AOS_CLI_MINI_SIZE > 0)
if (key2 == 0x41 || key2 == 0x42)
{
csp_printf("\r\n" PROMPT "Warning! mini cli mode do not support history cmds!");
}
#else
if (key2 == 0x41)
{ /* UP */
cli_up_history(inbuf);
csp_printf("\r\n" PROMPT "%s", inbuf);
*bp = strlen(inbuf);
esc_tag[0] = '\x0';
esc_tag_len = 0;
esc = 0; /* quit escape sequence */
continue;
}
if (key2 == 0x42)
{ /* DOWN */
cli_down_history(inbuf);
csp_printf("\r\n" PROMPT "%s", inbuf);
*bp = strlen(inbuf);
esc_tag[0] = '\x0';
esc_tag_len = 0;
esc = 0; /* quit escape sequence */
continue;
}
#endif
/* ESC_TAG */
if (esc_tag_len >= sizeof(esc_tag))
{
esc_tag[0] = '\x0';
esc_tag_len = 0;
esc = 0; /* quit escape sequence */
csp_printf("Error: esc_tag buffer overflow\r\n");
fflush(stdout);
continue;
}
esc_tag[esc_tag_len++] = c;
if (c == 'm')
{
esc_tag[esc_tag_len++] = '\x0';
if (!cli->echo_disabled)
{
csp_printf("%s", esc_tag);
fflush(stdout);
}
esc = 0; /* quit escape sequence */
}
continue;
}
inbuf[*bp] = c;
if ((c == 0x08) || /* backspace */
(c == 0x7f))
{ /* DEL */
if (*bp > 0)
{
(*bp)--;
if (!cli->echo_disabled)
{
csp_printf("%c %c", 0x08, 0x08);
fflush(stdout);
}
}
continue;
}
if (c == '\t')
{
inbuf[*bp] = '\0';
tab_complete(inbuf, bp);
continue;
}
if (!cli->echo_disabled)
{
csp_printf("%c", c);
fflush(stdout);
}
(*bp)++;
if (*bp >= INBUF_SIZE)
{
aos_cli_printf("Error: input buffer overflow\r\n");
aos_cli_printf(PROMPT);
*bp = 0;
return 0;
}
}
return 0;
}
/* Print out a bad command string, including a hex
* representation of non-printable characters.
* Non-printable characters show as "\0xXX".
*/
static void print_bad_command(char *cmd_string)
{
if (cmd_string != NULL)
{
aos_cli_printf("command '%s' not found\r\n", cmd_string);
}
}
/* Main CLI processing thread
*
* Waits to receive a command buffer pointer from an input collector, and
* then processes. Note that it must cleanup the buffer when done with it.
*
* Input collectors handle their own lexical analysis and must pass complete
* command lines to CLI.
*/
static void cli_main(void *data)
{
while (!cliexit)
{
int ret;
char *msg = NULL;
if (get_input(cli->inbuf, &cli->bp))
{
msg = cli->inbuf;
#if 0
if (strcmp(msg, EXIT_MSG) == 0) {
break;
}
#endif
#if (AOS_CLI_MINI_SIZE <= 0)
if (strlen(cli->inbuf) > 0)
{
cli_history_input();
}
#endif
ret = handle_input(msg);
if (ret == 1)
{
print_bad_command(msg);
}
else if (ret == 2)
{
aos_cli_printf("syntax error\r\n");
}
aos_cli_printf("\r\n");
esc_tag[0] = '\x0';
esc_tag_len = 0;
aos_cli_printf(PROMPT);
}
}
aos_cli_printf("CLI exited\r\n");
aos_free(cli);
cli = NULL;
aos_task_exit(0);
}
static void help_cmd(char *buf, int len, int argc, char **argv);
static void version_cmd(char *buf, int len, int argc, char **argv);
#if (AOS_CLI_MINI_SIZE <= 0)
static void echo_cmd(char *buf, int len, int argc, char **argv);
static void exit_cmd(char *buf, int len, int argc, char **argv);
static void devname_cmd(char *buf, int len, int argc, char **argv);
#endif
static void reboot_cmd(char *buf, int len, int argc, char **argv);
static void uptime_cmd(char *buf, int len, int argc, char **argv);
static void ota_cmd(char *buf, int len, int argc, char **argv);
static void pmem_cmd(char *buf, int32_t len, int32_t argc, char **argv);
static void mmem_cmd(char *buf, int32_t len, int32_t argc, char **argv);
static void ip_cmd(char *buf, int32_t len, int32_t argc, char **argv);
static const struct cli_command built_ins[] = {
/*cli self*/
{"help", NULL, help_cmd},
#if (AOS_CLI_MINI_SIZE <= 0)
{"echo", NULL, echo_cmd},
{"exit", "CLI exit", exit_cmd},
{"devname", "print device name", devname_cmd},
#endif
/*rhino*/
{"sysver", NULL, version_cmd},
{"reboot", "reboot system", reboot_cmd},
/*aos_rhino*/
{"time", "system time", uptime_cmd},
{"ota", "system ota", ota_cmd},
{"p", "print memory", pmem_cmd},
{"m", "modify memory", mmem_cmd},
{"ip", "show lan ip", ip_cmd},
};
/* Built-in "help" command: prints all registered commands and their help
* text string, if any.
*/
static void help_cmd(char *buf, int len, int argc, char **argv)
{
int i, n;
uint32_t build_in_count = sizeof(built_ins) / sizeof(struct cli_command);
#if (DEBUG)
build_in_count++;
#endif
aos_cli_printf("====Build-in Commands====\r\n");
aos_cli_printf("====Support six cmds once, seperate by ; ====\r\n");
for (i = 0, n = 0; i < MAX_COMMANDS && n < cli->num_commands; i++)
{
if (cli->commands[i]->name)
{
aos_cli_printf("%s: %s\r\n", cli->commands[i]->name,
cli->commands[i]->help ? cli->commands[i]->help : "");
n++;
if (n == build_in_count)
{
aos_cli_printf("\r\n");
aos_cli_printf("====User Commands====\r\n");
}
}
}
}
static void version_cmd(char *buf, int len, int argc, char **argv)
{
#ifdef VCALL_RHINO
aos_cli_printf("kernel version :%d\r\n", krhino_version_get());
#else
aos_cli_printf("kernel version :posix\r\n");
#endif
}
#if (AOS_CLI_MINI_SIZE <= 0)
static void echo_cmd(char *buf, int len, int argc, char **argv)
{
if (argc == 1)
{
aos_cli_printf("Usage: echo on/off. Echo is currently %s\r\n",
cli->echo_disabled ? "Disabled" : "Enabled");
return;
}
if (!strcmp(argv[1], "on"))
{
aos_cli_printf("Enable echo\r\n");
cli->echo_disabled = 0;
}
else if (!strcmp(argv[1], "off"))
{
aos_cli_printf("Disable echo\r\n");
cli->echo_disabled = 1;
}
}
static void exit_cmd(char *buf, int len, int argc, char **argv)
{
cliexit = 1;
return;
}
static void devname_cmd(char *buf, int len, int argc, char **argv)
{
aos_cli_printf("device name: %s\r\n", SYSINFO_DEVICE_NAME);
}
#endif
static void reboot_cmd(char *buf, int len, int argc, char **argv)
{
aos_cli_printf("reboot\r\n");
hal_reboot();
}
static void uptime_cmd(char *buf, int len, int argc, char **argv)
{
aos_cli_printf("UP time %ld ms\r\n", (long)aos_now_ms());
}
void tftp_ota_thread(void *arg)
{
aos_task_exit(0);
}
static void ota_cmd(char *buf, int len, int argc, char **argv)
{
aos_task_new("LOCAL OTA", tftp_ota_thread, 0, 4096);
}
/* ------------------------------------------------------------------------- */
static void pmem_cmd(char *buf, int32_t len, int32_t argc, char **argv)
{
int32_t i;
int32_t nunits = 16;
int32_t width = 4;
char *pos = NULL;
char *addr = NULL;
switch (argc)
{
case 4:
width = strtoul(argv[3], NULL, 0);
case 3:
nunits = strtoul(argv[2], NULL, 0);
nunits = nunits > 0x400 ? 0x400 : nunits;
case 2:
addr = (char *)strtoul(argv[1], &pos, 0);
break;
default:
break;
}
if (pos == NULL || pos == argv[1] || nunits > 0x1000 || addr == NULL)
{
aos_cli_printf("p <addr> <nunits> <width>\r\n"
"addr : address to display\r\n"
"nunits: number of units to display (default is 16)\r\n"
"width : width of unit, 1/2/4 (default is 4)\r\n");
return;
}
switch (width)
{
case 1:
for (i = 0; i < nunits; i++)
{
if (i % 16 == 0)
{
aos_cli_printf("0x%08x:", (uint32_t)addr);
}
aos_cli_printf(" %02x", *(unsigned char *)addr);
addr += 1;
if (i % 16 == 15)
{
aos_cli_printf("\r\n");
}
}
break;
case 2:
for (i = 0; i < nunits; i++)
{
if (i % 8 == 0)
{
aos_cli_printf("0x%08x:", (uint32_t)addr);
}
aos_cli_printf(" %04x", *(unsigned short *)addr);
addr += 2;
if (i % 8 == 7)
{
aos_cli_printf("\r\n");
}
}
break;
default:
for (i = 0; i < nunits; i++)
{
if (i % 4 == 0)
{
aos_cli_printf("0x%08x:", (uint32_t)addr);
}
aos_cli_printf(" %08x", *(unsigned int *)addr);
addr += 4;
if (i % 4 == 3)
{
aos_cli_printf("\r\n");
}
}
break;
}
}
static void mmem_cmd(char *buf, int32_t len, int32_t argc, char **argv)
{
void *addr = NULL;
int32_t width = 4;
uint32_t value = 0;
uint32_t old_value;
uint32_t new_value;
switch (argc)
{
case 4:
width = strtoul(argv[3], NULL, 0);
case 3:
value = strtoul(argv[2], NULL, 0);
case 2:
addr = (void *)strtoul(argv[1], NULL, 0);
break;
default:
addr = NULL;
break;
}
if (addr == NULL)
{
aos_cli_printf("m <addr> <value> <width>\r\n"
"addr : address to modify\r\n"
"value : new value (default is 0)\r\n"
"width : width of unit, 1/2/4 (default is 4)\r\n");
return;
}
switch (width)
{
case 1:
old_value = (uint32_t)(*(uint8_t volatile *)addr);
*(uint8_t volatile *)addr = (uint8_t)value;
new_value = (uint32_t)(*(uint8_t volatile *)addr);
break;
case 2:
old_value = (uint32_t)(*(unsigned short volatile *)addr);
*(unsigned short volatile *)addr = (unsigned short)value;
new_value = (uint32_t)(*(unsigned short volatile *)addr);
break;
case 4:
default:
old_value = *(uint32_t volatile *)addr;
*(uint32_t volatile *)addr = (uint32_t)value;
new_value = *(uint32_t volatile *)addr;
break;
}
aos_cli_printf("value on 0x%x change from 0x%x to 0x%x.\r\n", (uint32_t)addr,
old_value, new_value);
}
extern void wifi_get_ip(char ips[16]);
static void ip_cmd(char *buf, int32_t len, int32_t argc, char **argv)
{
char ip_str[17] = {0};
wifi_get_ip(ip_str);
aos_cli_printf("lan ip:%s\r\n", ip_str);
}
int aos_cli_register_command(const struct cli_command *cmd)
{
int i;
if (!cli)
{
return 1;
}
if (!cmd->name || !cmd->function)
{
return -EINVAL;
}
if (cli->num_commands < MAX_COMMANDS)
{
/* Check if the command has already been registered.
* Return 0, if it has been registered.
*/
for (i = 0; i < cli->num_commands; i++)
{
if (cli->commands[i] == cmd)
{
return 0;
}
}
cli->commands[cli->num_commands++] = cmd;
return 0;
}
return -ENOMEM;
}
int aos_cli_unregister_command(const struct cli_command *cmd)
{
int i;
if (!cmd->name || !cmd->function)
{
return -EINVAL;
}
for (i = 0; i < cli->num_commands; i++)
{
if (cli->commands[i] == cmd)
{
cli->num_commands--;
int remaining_cmds = cli->num_commands - i;
if (remaining_cmds > 0)
{
memmove(&cli->commands[i], &cli->commands[i + 1],
(remaining_cmds * sizeof(struct cli_command *)));
}
cli->commands[cli->num_commands] = NULL;
return 0;
}
}
return -ENOMEM;
}
int aos_cli_register_commands(const struct cli_command *cmds, int num_cmds)
{
int i;
int err;
if (!cli)
{
return 1;
}
for (i = 0; i < num_cmds; i++)
{
if ((err = aos_cli_register_command(cmds++)) != 0)
{
return err;
}
}
return 0;
}
int aos_cli_unregister_commands(const struct cli_command *cmds, int num_cmds)
{
int i;
int err;
for (i = 0; i < num_cmds; i++)
{
if ((err = aos_cli_unregister_command(cmds++)) != 0)
{
return err;
}
}
return 0;
}
int aos_cli_stop(void)
{
cliexit = 1;
return 0;
}
#ifndef CONFIG_AOS_CLI_STACK_SIZE
#define CONFIG_AOS_CLI_STACK_SIZE 2048
#endif
int aos_cli_init(void)
{
int ret;
aos_task_t task;
cli = (struct cli_st *)aos_malloc(sizeof(struct cli_st));
if (cli == NULL)
{
return -ENOMEM;
}
memset((void *)cli, 0, sizeof(struct cli_st));
/* add our built-in commands */
if ((ret = aos_cli_register_commands(&built_ins[0],
sizeof(built_ins) / sizeof(struct cli_command))) != 0)
{
goto init_general_err;
}
ret = aos_task_new_ext(&task, "cli", cli_main, 0, CONFIG_AOS_CLI_STACK_SIZE, AOS_DEFAULT_APP_PRI + 1);
if (ret != 0)
{
aos_cli_printf("Error: Failed to create cli thread: %d\r\n",
ret);
goto init_general_err;
}
cli->initialized = 1;
cli->echo_disabled = 0;
#ifdef CONFIG_AOS_CLI_BOARD
board_cli_init();
#endif
log_cli_init();
return 0;
init_general_err:
if (cli)
{
aos_free(cli);
cli = NULL;
}
return ret;
}
const char *aos_cli_get_tag(void)
{
return esc_tag;
}
#if defined BUILD_BIN || defined BUILD_KERNEL
int aos_cli_printf(const char *msg, ...)
{
va_list ap;
char *pos, message[256];
int sz;
int len;
memset(message, 0, 256);
sz = 0;
if (esc_tag_len)
{
strcpy(message, esc_tag);
sz = strlen(esc_tag);
}
pos = message + sz;
va_start(ap, msg);
len = vsnprintf(pos, 256 - sz, msg, ap);
va_end(ap);
if (len <= 0)
{
return 0;
}
cli_putstr(message);
return 0;
}
#endif
int cli_putstr(char *msg)
{
if (msg[0] != 0)
{
aos_uart_send(msg, strlen(msg), 0);
}
return 0;
}
int cli_getchar(char *inbuf)
{
if (aos_uart_recv(inbuf, 1, NULL, 0xFFFFFFFF) == 0)
{
return 1;
}
else
{
return 0;
}
}
#endif