diff --git a/components/msh/Kconfig b/components/msh/Kconfig index d9f658e..0b1dfad 100644 --- a/components/msh/Kconfig +++ b/components/msh/Kconfig @@ -13,20 +13,20 @@ menu "Msh configure" help "This option sets the buffer size used by the shell." - config MR_CFG_MSH_NAME_MAX - int "Msh command name max length" - default 8 - range 8 64 - help - "This option sets the max length of the command name." - - config MR_CFG_MSH_ARGS_MAX + config MR_CFG_MSH_ARGS_NUM int "Msh argument max number" default 16 - range 1 64 + range 4 64 help "This option sets the max number of arguments." + config MR_CFG_MSH_HISTORY_LINES + int "Msh history max lines" + default 4 + range 1 64 + help + "This option sets the max number of history lines." + config MR_CFG_MSH_DEV_NAME string "Msh device name" default "serial1" diff --git a/components/msh/msh.c b/components/msh/msh.c index b381f47..4483162 100644 --- a/components/msh/msh.c +++ b/components/msh/msh.c @@ -13,37 +13,47 @@ /** * @brief MSH structure. */ -static struct +static struct mr_msh { #ifndef MR_CFG_MSH_BUFSZ #define MR_CFG_MSH_BUFSZ (32) #endif /* MR_CFG_MSHELL_BUFSZ */ char buf[MR_CFG_MSH_BUFSZ]; /**< Buffer for reading */ - uint32_t cursor: 16; /**< Cursor position */ - uint32_t bytes: 16; /**< Bytes in the buffer */ + uint32_t cursor; /**< Cursor position */ + uint32_t bytes; /**< Bytes in the buffer */ char key_buf[8]; /**< Buffer for keys */ - uint32_t key_bytes: 4; /**< Bytes in the key buffer */ - uint32_t echo: 1; /**< Echo or not */ - uint32_t reserved: 27; /**< Reserved */ + uint16_t key_bytes: 15; /**< Bytes in the key buffer */ + uint16_t echo: 1; /**< Echo or not */ + uint16_t history_index; /**< History index */ + uint16_t history_pos; /**< History position */ + uint16_t history_len; /**< History length */ +#ifndef MR_CFG_MSH_HISTORY_LINES +#define MR_CFG_MSH_HISTORY_LINES (4) +#endif /* MR_CFG_MSH_HISTORY_LINES */ + char history[MR_CFG_MSH_HISTORY_LINES][MR_CFG_MSH_BUFSZ]; /**< History buffer */ char *prompt; /**< Prompt string */ int desc; /**< Device descriptor */ } msh; #define MR_MSH_EXPORT(name, fn, help, level) \ MR_USED const struct mr_msh_cmd _mr_msh_cmd_##name MR_SECTION("mr_msh_cmd."level) = {#name, fn, help}; +MR_MSH_EXPORT(start, MR_NULL, MR_NULL, "0"); /**< Start shell command */ +MR_MSH_EXPORT(end, MR_NULL, MR_NULL, "1.end"); /**< End shell command */ -MR_MSH_EXPORT(start, MR_NULL, MR_NULL, "0"); -MR_MSH_EXPORT(end, MR_NULL, MR_NULL, "1.end"); +/** + * @brief Shell commands. + */ +#define MSH_CURSOR_FORWARD "\x1b[1D" /**< Move cursor forward */ +#define MSH_CURSOR_BACKWARD "\x1b[1C" /**< Move cursor backward */ +#define MSH_DELETE_CHAR "\x1b[1P" /**< Delete chars */ +#define MSH_INSERT_CHAR "\x1b[1@" /**< Insert chars */ +#define MSH_CLEAR_SCREEN "\x1b[2J""\x1b[1;1H" /**< Clear screen */ +#define MSH_CLEAR_LINE "\x1b[2K""\x1b[1G" /**< Clear line */ -#define MSH_CURSOR_FORWARD(x) "\x1b["#x"D" -#define MSH_CURSOR_BACKWARD(x) "\x1b["#x"C" -#define MSH_DELETE_CHAR(x) "\x1b["#x"P" -#define MSH_INSERT_CHAR(x) "\x1b["#x"@" -#define MSH_CLEAR "\x1b[2J""\x1b[1;1H" - -static void msh_refresh_line(void) +MR_INLINE void msh_new_current_line(void) { - /* Move the cursor to the beginning of the line and print a new line */ + msh.cursor = 0; + msh.bytes = 0; if (msh.echo == MR_ENABLE) { #ifndef MR_CFG_MSH_PROMPT @@ -56,47 +66,41 @@ static void msh_refresh_line(void) #endif /* MR_USING_MSH_PRINTF_COLOR */ mr_msh_printf(MR_MSH_COLOR_CYAN("%s ")MR_MSH_COLOR_YELLOW("%s> "), MR_CFG_MSH_PROMPT, msh.prompt); } - msh.cursor = 0; - msh.bytes = 0; - msh.key_bytes = 0; } -static void msh_new_line(void) +MR_INLINE void msh_refresh_line(void) { - /* Move the cursor to the beginning of the line and print a new line */ if (msh.echo == MR_ENABLE) { - mr_msh_printf("\r\n"MR_MSH_COLOR_CYAN("%s ")MR_MSH_COLOR_YELLOW("%s> "), MR_CFG_MSH_PROMPT, msh.prompt); + mr_msh_printf(MSH_CLEAR_LINE); + mr_msh_printf(MR_MSH_COLOR_CYAN("%s ")MR_MSH_COLOR_YELLOW("%s> ")"%s", MR_CFG_MSH_PROMPT, msh.prompt, msh.buf); } - msh.cursor = 0; - msh.bytes = 0; - msh.key_bytes = 0; } -static void msh_move_cursor_left(void) +MR_INLINE void msh_move_cursor_left(void) { if (msh.cursor > 0) { msh.cursor--; - mr_msh_printf(MSH_CURSOR_FORWARD(1)); + mr_msh_printf(MSH_CURSOR_FORWARD); } } -static void msh_move_cursor_right(void) +MR_INLINE void msh_move_cursor_right(void) { if (msh.cursor < msh.bytes) { msh.cursor++; - mr_msh_printf(MSH_CURSOR_BACKWARD(1)); + mr_msh_printf(MSH_CURSOR_BACKWARD); } } -static void msh_delete_char(void) +MR_INLINE void msh_delete_char(void) { if (msh.cursor > 0) { /* Move the cursor forward and delete the character */ - mr_msh_printf(MSH_CURSOR_FORWARD(1)MSH_DELETE_CHAR(1)); + mr_msh_printf(MSH_CURSOR_FORWARD MSH_DELETE_CHAR); /* Check if you need to remove characters from the middle */ if (msh.cursor != msh.bytes) @@ -109,12 +113,12 @@ static void msh_delete_char(void) } msh.cursor--; msh.bytes--; + msh.buf[msh.bytes] = '\0'; } } -static void msh_insert_char(char c) +MR_INLINE void msh_insert_char(char c) { - /* Check if there is enough space */ if ((msh.bytes + 1) == MR_CFG_MSH_BUFSZ) { return; @@ -123,13 +127,15 @@ static void msh_insert_char(char c) /* Check whether the cursor is at the end of the buffer */ if (msh.cursor != msh.bytes) { - /* Insert the character */ - mr_msh_printf(MSH_INSERT_CHAR(1)); + if (msh.echo == MR_ENABLE) + { + mr_msh_printf(MSH_INSERT_CHAR); + } /* Readjust string */ - for (size_t i = msh.cursor; i < msh.bytes; i++) + for (size_t i = msh.bytes; i > msh.cursor; i--) { - msh.buf[i + 1] = msh.buf[i]; + msh.buf[i] = msh.buf[i - 1]; } } msh.buf[msh.cursor] = c; @@ -144,12 +150,91 @@ static void msh_insert_char(char c) } } -static int msh_parse_cmd(void) +MR_INLINE void msh_auto_complete(void) { - /* Check whether the buffer is empty */ + const struct mr_msh_cmd *msh_comp = MR_NULL; + + /* Find the command */ + for (const struct mr_msh_cmd *msh_cmd = ((&_mr_msh_cmd_start) + 1); msh_cmd < &_mr_msh_cmd_end; msh_cmd++) + { + /* When cursor is equal to 0, all commands are satisfied, so there is no auto-completion */ + if (strncmp(msh_cmd->name, msh.buf, msh.cursor) == 0) + { + /* Check whether multiple commands are met */ + if (msh_comp != MR_NULL) + { + return; + } + msh_comp = msh_cmd; + } + } + + /* Complete the command */ + if (msh_comp != MR_NULL) + { + for (size_t i = msh.cursor; i < strlen(msh_comp->name); i++) + { + msh_insert_char(msh_comp->name[i]); + } + } +} + +MR_INLINE void msh_history_push(void) +{ + uint16_t history_prev = (msh.history_index + (MR_CFG_MSH_HISTORY_LINES - 1)) % MR_CFG_MSH_HISTORY_LINES; + + /* Check whether this command is the same as the previous one */ + if ((msh.bytes != 0) && (strncmp(msh.history[history_prev], msh.buf, msh.bytes) != 0)) + { + memcpy(msh.history[msh.history_index], msh.buf, (msh.bytes + 1)); + msh.history_index = (msh.history_index + 1) % MR_CFG_MSH_HISTORY_LINES; + msh.history_len = MR_BOUND(msh.history_len + 1, 0, MR_CFG_MSH_HISTORY_LINES); + } + msh.history_pos = 0; +} + +MR_INLINE void msh_history_pop_prev(void) +{ + if (msh.history_pos < msh.history_len) + { + msh.history_pos++; + + /* If the previous index is equal to the current index, no previous record is available */ + uint16_t index = (msh.history_index + MR_CFG_MSH_HISTORY_LINES - msh.history_pos) % MR_CFG_MSH_HISTORY_LINES; + + /* Refresh the line with the previous command */ + msh.cursor = msh.bytes = strlen(msh.history[index]); + strncpy(msh.buf, msh.history[index], msh.bytes + 1); + msh_refresh_line(); + } +} + +MR_INLINE void msh_history_pop_next(void) +{ + if (msh.history_pos > 1) + { + msh.history_pos--; + uint16_t index = (msh.history_index + MR_CFG_MSH_HISTORY_LINES - msh.history_pos) % MR_CFG_MSH_HISTORY_LINES; + if (index >= msh.history_len) + { + index = 0; + } + + /* Refresh the line with the next command */ + msh.cursor = msh.bytes = strlen(msh.history[index]); + strncpy(msh.buf, msh.history[index], msh.bytes + 1); + msh_refresh_line(); + } +} + +MR_INLINE void msh_parse_cmd(void) +{ + mr_msh_printf("\r\n"); + if (msh.bytes == 0) { - return MR_FALSE; + msh_new_current_line(); + return; } /* Find the command */ @@ -162,7 +247,7 @@ static int msh_parse_cmd(void) /* Execute the command */ for (const struct mr_msh_cmd *msh_cmd = ((&_mr_msh_cmd_start) + 1); msh_cmd < &_mr_msh_cmd_end; msh_cmd++) { - if (strncmp(msh_cmd->name, msh.buf, MR_CFG_MSH_NAME_MAX) != 0) + if (strncmp(msh_cmd->name, msh.buf, strlen(msh_cmd->name)) != 0) { continue; } @@ -175,12 +260,12 @@ static int msh_parse_cmd(void) /* Parse the arguments */ int argc; -#ifndef MR_CFG_MSH_ARGS_MAX -#define MR_CFG_MSH_ARGS_MAX (8) -#endif /* MR_CFG_MSH_ARGS_MAX */ - char *argv[MR_CFG_MSH_ARGS_MAX] = {MR_NULL}; +#ifndef MR_CFG_MSH_ARGS_NUM +#define MR_CFG_MSH_ARGS_NUM (8) +#endif /* MR_CFG_MSH_ARGS_NUM */ + char *argv[MR_CFG_MSH_ARGS_NUM] = {MR_NULL}; char *old_arg = msh.buf; - for (argc = 0; argc < MR_CFG_MSH_ARGS_MAX; argc++) + for (argc = 0; argc < MR_CFG_MSH_ARGS_NUM; argc++) { char *arg = strchr(old_arg, ' '); if ((arg == MR_NULL) || (*(arg + 1) == '\0') || (*(arg + 1) == ' ')) @@ -192,36 +277,21 @@ static int msh_parse_cmd(void) old_arg = arg; } - mr_msh_printf("\r\n"); - msh_cmd->call(argc, argv); - return MR_TRUE; + /* Execute the command */ + msh_cmd->fn(argc, argv); + msh_new_current_line(); + return; } - return MR_FALSE; + + /* Command not found */ + mr_msh_printf("%s: command not found\r\n", msh.buf); + msh_new_current_line(); } -#define KEY_BACKSPACE "\b" -#define KEY_ENTER "\r" -#define KEY_LEFT "\x1b[D" -#define KEY_RIGHT "\x1b[C" -#define KEY_DELETE "\x1B[3~" -#define KEY_TABLE "\t" - -#define MSH_IS_PRINTABLE(c) ((c) >= 0x20 && (c) <= 0x7e) -#define MSH_IS_ESC_KEY(c) ((c) == 0x1b) -#define MSH_IS_END_KEY(c) ((((c) >= 'A') && ((c) <= 'Z')) || ((c) >= '~')) - static void msh_key_enter(void) { - int ret = msh_parse_cmd(); - - /* If the command was not found, add a new line */ - if (ret == MR_FALSE) - { - msh_new_line(); - } else - { - msh_refresh_line(); - } + msh_history_push(); + msh_parse_cmd(); } static void msh_key_backspace(void) @@ -229,6 +299,21 @@ static void msh_key_backspace(void) msh_delete_char(); } +static void msh_key_table(void) +{ + msh_auto_complete(); +} + +static void msh_key_up(void) +{ + msh_history_pop_prev(); +} + +static void msh_key_down(void) +{ + msh_history_pop_next(); +} + static void msh_key_left(void) { msh_move_cursor_left(); @@ -245,66 +330,39 @@ static void msh_key_delete(void) msh_delete_char(); } -static size_t msh_strnlen(const char *str, size_t max_len) -{ - for (size_t i = 0; i < max_len; i++) - { - if (str[i] == '\0') - { - return i; - } - } - return max_len; -} +#define KEY_ENTER "\r" /**< Enter key */ +#define KEY_BACKSPACE "\b" /**< Backspace key */ +#define KEY_TABLE "\t" /**< Tab key */ +#define KEY_LEFT "\x1b[D" /**< Left key */ +#define KEY_RIGHT "\x1b[C" /**< Right key */ +#define KEY_UP "\x1B[A" /**< Up key */ +#define KEY_DOWN "\x1B[B" /**< Down key */ +#define KEY_DELETE "\x1B[3~" /**< Delete key */ -static void msh_key_table(void) -{ - /* Find the command */ - const struct mr_msh_cmd *msh_comp = MR_NULL; - - for (const struct mr_msh_cmd *msh_cmd = ((&_mr_msh_cmd_start) + 1); msh_cmd < &_mr_msh_cmd_end; msh_cmd++) - { - if (strncmp(msh_cmd->name, msh.buf, msh.cursor) == 0) - { - if (msh_comp != MR_NULL) - { - return; - } - msh_comp = msh_cmd; - } - } - - /* Complete the command */ - if (msh_comp != MR_NULL) - { -#ifndef MR_CFG_MSH_NAME_MAX -#define MR_CFG_MSH_NAME_MAX (8) -#endif /* MR_CFG_MSH_NAME_MAX */ - for (size_t i = msh.cursor; i < msh_strnlen(msh_comp->name, MR_CFG_MSH_NAME_MAX); i++) - { - msh_insert_char(msh_comp->name[i]); - } - } -} +#define MSH_IS_PRINTABLE(c) ((c) >= 0x20 && (c) <= 0x7e) +#define MSH_IS_ESC_KEY(c) ((c) == 0x1b) +#define MSH_IS_END_KEY(c) ((((c) >= 'A') && ((c) <= 'Z')) || ((c) >= '~')) /** * @brief Msh long character key map structure. */ static struct { - char *key; - void (*exec)(void); + const char *key; + void (*fn)(void); } msh_key_map[] = { {KEY_ENTER, msh_key_enter}, {KEY_BACKSPACE, msh_key_backspace}, + {KEY_TABLE, msh_key_table}, {KEY_LEFT, msh_key_left}, {KEY_RIGHT, msh_key_right}, + {KEY_UP, msh_key_up}, + {KEY_DOWN, msh_key_down}, {KEY_DELETE, msh_key_delete}, - {KEY_TABLE, msh_key_table}, }; -static void msh_parse_key(char c) +MR_INLINE void msh_parse_key(char c) { int parse_flag = MR_DISABLE; @@ -345,7 +403,7 @@ static void msh_parse_key(char c) { if (strncmp(msh.key_buf, msh_key_map[i].key, msh.key_bytes) == 0) { - msh_key_map[i].exec(); + msh_key_map[i].fn(); break; } } @@ -353,110 +411,6 @@ static void msh_parse_key(char c) } } -static int msh_cmd_help(int argc, void *argv) -{ - for (const struct mr_msh_cmd *msh_cmd = ((&_mr_msh_cmd_start) + 1); msh_cmd < &_mr_msh_cmd_end; msh_cmd++) - { - mr_msh_printf("%-*s - %s\r\n", MR_CFG_MSH_NAME_MAX, msh_cmd->name, msh_cmd->help); - } - return MR_EOK; -} - -static int msh_cmd_clear(int argc, void *argv) -{ - mr_msh_printf(MSH_CLEAR); - return MR_EOK; -} - -static int msh_cmd_logo(int argc, void *argv) -{ - mr_msh_printf(" __ __ _ _ _ \r\n"); - mr_msh_printf("| \\/ | _ __ | | (_) | |__ _ __ __ _ _ __ _ _\r\n"); - mr_msh_printf("| |\\/| | | '__| _____ | | | | | '_ \\ | '__| / _` | | '__| | | | |\r\n"); - mr_msh_printf("| | | | | | |_____| | | | | | |_) | | | | (_| | | | | |_| |\r\n"); - mr_msh_printf("|_| |_| |_| |_| |_| |_.__/ |_| \\__,_| |_| \\__, |\r\n"); - mr_msh_printf(" |___/\r\n"); - return MR_EOK; -} - -static int msh_cmd_echo(int argc, void *argv) -{ - /* Check the arguments */ - if (argc == 1) - { - if (strncmp(MR_MSH_GET_ARG(1), "on", 2) == 0) - { - msh.echo = MR_ENABLE; - mr_msh_printf("Echo is on.\r\n"); - return MR_EOK; - } else if (strncmp(MR_MSH_GET_ARG(1), "off", 3) == 0) - { - msh.echo = MR_DISABLE; - mr_msh_printf("Echo is off.\r\n"); - return MR_EOK; - } - } - mr_msh_printf("Usage: echo \r\n"); - return MR_EINVAL; -} - -/** - * @brief This function initialize the msh. - * - * @return MR_ERR_OK on success, otherwise an error code. - */ -static int mr_msh_init(void) -{ - msh.cursor = 0; - msh.bytes = 0; - msh.key_bytes = 0; -#ifdef MR_USING_MSH_ECHO - msh.echo = MR_ENABLE; -#endif /* MR_USING_MSH_ECHO */ - msh.prompt = "/"; - msh.desc = -1; - /* Print the prompt */ - mr_msh_printf(MSH_CLEAR); - msh_refresh_line(); - return MR_EOK; -} -MR_INIT_DEV_EXPORT(mr_msh_init); - -/** - * @brief Exports default MSH commands. - */ -MR_MSH_CMD_EXPORT(help, msh_cmd_help, "show help information."); -MR_MSH_CMD_EXPORT(clear, msh_cmd_clear, "clear the screen."); -MR_MSH_CMD_EXPORT(logo, msh_cmd_logo, "show the logo."); -MR_MSH_CMD_EXPORT(echo, msh_cmd_echo, "enable or disable echo."); - -/** - * @brief This function printf output to the msh. - * - * @param buf The buffer to receive. - * @param size The size of the buffer. - * @return - */ -MR_WEAK int mr_msh_printf_output(const char *buf, size_t size) -{ - if (mr_dev_is_valid(msh.desc) == MR_FALSE) - { -#ifndef MR_CFG_MSH_DEV_NAME -#define MR_CFG_MSH_DEV_NAME "serial1" -#endif /* MR_CFG_MSH_DEV_NAME */ -#ifndef MR_CFG_MSH_NONBLOCKING - msh.desc = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_OFLAG_RDWR); -#else - msh.desc = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_OFLAG_RDWR | MR_OFLAG_NONBLOCK); -#endif /* MR_CFG_MSH_NONBLOCKING */ - if (mr_dev_is_valid(msh.desc) == MR_FALSE) - { - return msh.desc; - } - } - return (int)mr_dev_write(msh.desc, buf, size); -} - /** * @brief This function input from the msh. * @@ -466,19 +420,55 @@ MR_WEAK int mr_msh_printf_output(const char *buf, size_t size) */ MR_WEAK int mr_msh_input(char *c) { - if (mr_dev_is_valid(msh.desc) == MR_FALSE) + /* Try to open the serial port */ + if (msh.desc == -1) + { +#ifndef MR_CFG_MSH_DEV_NAME +#define MR_CFG_MSH_DEV_NAME "serial1" +#endif /* MR_CFG_MSH_DEV_NAME */ +#ifndef MR_CFG_MSH_NONBLOCKING + int ret = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_O_RDWR); +#else + int ret = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_O_RDWR | MR_O_NONBLOCK); +#endif /* MR_CFG_MSH_NONBLOCKING */ + if (ret < 0) + { + return ret; + } + msh.desc = ret; + } + + /* Read data from the serial port */ + return (int)mr_dev_read(msh.desc, c, sizeof(*c)); +} + +/** + * @brief This function printf output to the msh. + * + * @param buf The buffer to receive. + * @param size The size of the buffer. + * + * @return The actual output size. + */ +MR_WEAK int mr_msh_printf_output(const char *buf, size_t size) +{ + /* Try to open the serial port */ + if (msh.desc == -1) { #ifndef MR_CFG_MSH_NONBLOCKING - msh.desc = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_OFLAG_RDWR); + int ret = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_O_RDWR); #else - msh.desc = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_OFLAG_RDWR | MR_OFLAG_NONBLOCK); + int ret = mr_dev_open(MR_CFG_MSH_DEV_NAME, MR_O_RDWR | MR_O_NONBLOCK); #endif /* MR_CFG_MSH_NONBLOCKING */ - if (mr_dev_is_valid(msh.desc) == MR_FALSE) + if (ret < 0) { - return 0; + return ret; } + msh.desc = ret; } - return (int)mr_dev_read(msh.desc, c, sizeof(*c)); + + /* Write data to the serial port */ + return (int)mr_dev_write(msh.desc, buf, size); } /** @@ -494,14 +484,16 @@ int mr_msh_printf(const char *fmt, ...) #ifndef MR_CFG_MSH_PRINTF_BUFSZ #define MR_CFG_MSH_PRINTF_BUFSZ (128) #endif /* MR_CFG_MSH_PRINTF_BUFSZ */ - char buf[MR_CFG_MSH_PRINTF_BUFSZ] = {0}; + static char buf[MR_CFG_MSH_PRINTF_BUFSZ] = {0}; va_list args; + /* Format the string */ va_start(args, fmt); int ret = vsnprintf(buf, sizeof(buf) - 1, fmt, args); - ret = mr_msh_printf_output(buf, ret); va_end(args); - return ret; + + /* Output the string */ + return mr_msh_printf_output(buf, ret); } /** @@ -533,4 +525,80 @@ void mr_msh_handle(void) } } +/** + * @brief This function initialize the msh. + * + * @return MR_ERR_OK on success, otherwise an error code. + */ +static void mr_msh_init(void) +{ + msh.cursor = 0; + msh.bytes = 0; + msh.key_bytes = 0; +#ifdef MR_USING_MSH_ECHO + msh.echo = MR_ENABLE; +#endif /* MR_USING_MSH_ECHO */ + msh.history_index = 0; + msh.history_len = 0; + msh.history_pos = 0; + msh.prompt = "/"; + msh.desc = -1; + /* Print the prompt */ + mr_msh_printf(MSH_CLEAR_SCREEN); + msh_new_current_line(); +} +MR_INIT_DEV_EXPORT(mr_msh_init); + +static void msh_cmd_help(int argc, void *argv) +{ + for (const struct mr_msh_cmd *msh_cmd = ((&_mr_msh_cmd_start) + 1); msh_cmd < &_mr_msh_cmd_end; msh_cmd++) + { + mr_msh_printf("%-*s - %s\r\n", 16, msh_cmd->name, msh_cmd->help); + } +} + +static void msh_cmd_clear(int argc, void *argv) +{ + mr_msh_printf(MSH_CLEAR_SCREEN); +} + +static void msh_cmd_logo(int argc, void *argv) +{ + mr_msh_printf(" __ __ _ _ _ \r\n"); + mr_msh_printf("| \\/ | _ __ | | (_) | |__ _ __ __ _ _ __ _ _\r\n"); + mr_msh_printf("| |\\/| | | '__| _____ | | | | | '_ \\ | '__| / _` | | '__| | | | |\r\n"); + mr_msh_printf("| | | | | | |_____| | | | | | |_) | | | | (_| | | | | |_| |\r\n"); + mr_msh_printf("|_| |_| |_| |_| |_| |_.__/ |_| \\__,_| |_| \\__, |\r\n"); + mr_msh_printf(" |___/\r\n"); +} + +static void msh_cmd_echo(int argc, void *argv) +{ + if (argc == 1) + { + goto usage; + } + + if (strncmp(MR_MSH_GET_ARG(1), "on", 2) == 0) + { + msh.echo = MR_ENABLE; + return; + } else if (strncmp(MR_MSH_GET_ARG(1), "off", 3) == 0) + { + msh.echo = MR_DISABLE; + return; + } + + usage: + mr_msh_printf("usage: echo \r\n"); +} + +/** + * @brief Exports default MSH commands. + */ +MR_MSH_CMD_EXPORT(help, msh_cmd_help, "show help information."); +MR_MSH_CMD_EXPORT(clear, msh_cmd_clear, "clear the screen."); +MR_MSH_CMD_EXPORT(logo, msh_cmd_logo, "show the logo."); +MR_MSH_CMD_EXPORT(echo, msh_cmd_echo, "enable or disable echo."); + #endif /* MR_USING_MSH */ diff --git a/components/msh/msh_device.c b/components/msh/msh_device.c index c98275a..19fe855 100644 --- a/components/msh/msh_device.c +++ b/components/msh/msh_device.c @@ -10,31 +10,28 @@ #if defined(MR_USING_MSH) && defined(MR_USING_MSH_DEV_CMD) -static int msh_desc = -1; +static int msh_desc = -1; /**< MSH device descriptor */ -#define MSH_SET_DESC(desc) (msh_desc = (desc)) -#define MSH_GET_DESC() (msh_desc) +#define MSH_SET_DESC(desc) (msh_desc = (desc)) /**< Set MSH device descriptor */ +#define MSH_GET_DESC() (msh_desc) /**< Get MSH device descriptor */ + +int msh_dev_get_path(int desc, char *buf, size_t size); +void msh_dlist_tree(struct mr_dev *parent, int level); +struct mr_dev *msh_get_root(void); static int msh_update_path(int desc) { - static char msh_path[MR_CFG_DEV_NAME_MAX * 6]; - struct - { - char *buf; - size_t bufsz; - } path = {msh_path, sizeof(msh_path)}; - int offset; + static char msh_path[MR_CFG_DEV_NAME_LEN * 6] = {0}; + int position; - /* Update the path */ - int ret = mr_dev_ioctl(desc, MR_CTL_GET_PATH, &path); + /* Get the path and position */ + int ret = msh_dev_get_path(desc, msh_path, sizeof(msh_path)); if (ret < 0) { return ret; } - - /* Update the offset */ - mr_dev_ioctl(desc, MR_CTL_GET_OFFSET, &offset); - snprintf(msh_path + ret, sizeof(msh_path) - ret, "/%d", offset); + mr_dev_ioctl(desc, MR_IOC_GPOS, &position); + snprintf(msh_path + ret, sizeof(msh_path) - ret, "/%d", position); /* Update the prompt */ MSH_SET_DESC(desc); @@ -42,66 +39,112 @@ static int msh_update_path(int desc) return MR_EOK; } -static int msh_cmd_dopen(int argc, void *argv) +static void msh_cmd_dlist(int argc, void *argv) +{ + msh_dlist_tree(msh_get_root(), 0); +} + +static void msh_cmd_dselect(int argc, void *argv) +{ + int desc, ret; + + if ((argc < 1) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) + { + goto usage; + } + + /* Parse <-g|desc (>=0)> */ + if (strncmp(MR_MSH_GET_ARG(1), "-g", 2) == 0) + { + mr_msh_printf("%d\r\n", MSH_GET_DESC()); + } else + { + ret = sscanf(MR_MSH_GET_ARG(1), "%d", &desc); + if ((ret < 1) || (desc < 0)) + { + goto usage; + } + + /* Switch to the new descriptor */ + ret = msh_update_path(desc); + if (ret < 0) + { + mr_msh_printf("dselect: %d: %s\r\n", desc, mr_strerror(ret)); + } + } + return; + + usage: + mr_msh_printf("usage: dselect =0)|-g>\r\n"); +} + +static void msh_cmd_dopen(int argc, void *argv) { const char *path; - int oflags = MR_OFLAG_CLOSED; - int desc; + int flags, ret; - /* Check the arguments and print usage */ if (argc < 2) { goto usage; } - /* Parse [r|w|rw] */ - if (strncmp(MR_MSH_GET_ARG(2), "rw", 2) == 0) + /* Parse <-g> */ + if (strncmp(MR_MSH_GET_ARG(2), "-g", 2) == 0) { - MR_BIT_SET(oflags, MR_OFLAG_RDWR); + flags = MR_O_QUERY; + + /* Parse */ + } else if (strncmp(MR_MSH_GET_ARG(2), "rw", 2) == 0) + { + flags = MR_O_RDWR; } else if (strncmp(MR_MSH_GET_ARG(2), "r", 1) == 0) { - MR_BIT_SET(oflags, MR_OFLAG_RDONLY); + flags = MR_O_RDONLY; } else if (strncmp(MR_MSH_GET_ARG(2), "w", 1) == 0) { - MR_BIT_SET(oflags, MR_OFLAG_WRONLY); + flags = MR_O_WRONLY; } else { goto usage; } + /* Parse [-n] */ if ((MR_MSH_GET_ARG(3) != MR_NULL) && (strncmp(MR_MSH_GET_ARG(3), "-n", 2) == 0)) { - MR_BIT_SET(oflags, MR_OFLAG_NONBLOCK); + flags |= MR_O_NONBLOCK; } /* Open the new device */ path = MR_MSH_GET_ARG(1); - desc = mr_dev_open(path, oflags); - if (desc < 0) + ret = mr_dev_open(path, flags); + if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(desc)); - return desc; + mr_msh_printf("dopen: %s: %s\r\n", path, mr_strerror(ret)); + return; } - /* Switch to the new descriptor */ - return msh_update_path(desc); + if (flags != MR_O_QUERY) + { + msh_update_path(ret); + } else + { + mr_msh_printf("%s %s\r\n", mr_strflags(ret), path); + } + return; usage: - mr_msh_printf("usage: dopen [-n]\r\n"); - return MR_EINVAL; + mr_msh_printf("usage: dopen [-n]\r\n"); } -static int msh_cmd_dclose(int argc, void *argv) +static void msh_cmd_dclose(int argc, void *argv) { - int desc; - int ret; + int desc, ret; - /* Check the arguments and print usage */ if ((MR_MSH_GET_ARG(1) != MR_NULL) && (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) { goto usage; } - /* Parse [desc (>=0)] */ + /* Parse [desc] */ if (MR_MSH_GET_ARG(1) != MR_NULL) { ret = sscanf(MR_MSH_GET_ARG(1), "%d", &desc); @@ -119,8 +162,8 @@ static int msh_cmd_dclose(int argc, void *argv) ret = mr_dev_close(desc); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dclose: %d: %s\r\n", desc, mr_strerror(ret)); + return; } /* Switch to the root device */ @@ -129,101 +172,55 @@ static int msh_cmd_dclose(int argc, void *argv) MSH_SET_DESC(-1); mr_msh_set_prompt("/"); } - return MR_EOK; + return; usage: mr_msh_printf("usage: dclose [desc (>=0)]\r\n"); - return MR_EINVAL; } -static int msh_cmd_dselect(int argc, void *argv) +MR_INLINE void msh_dioctl_pos(int argc, void *argv) { - int desc; - int ret; + int cmd = MR_IOC_SPOS, position, ret; - /* Check the arguments and print usage */ - if ((argc < 1) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) + if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(2), "-h", 2) == 0)) { goto usage; } - /* Parse <-g|desc (>=0)> */ - if (strncmp(MR_MSH_GET_ARG(1), "-g", 2) == 0) - { - mr_msh_printf("%d\r\n", MSH_GET_DESC()); - return MR_EOK; - } else - { - ret = sscanf(MR_MSH_GET_ARG(1), "%d", &desc); - if ((ret < 1) || (desc < 0)) - { - goto usage; - } - - /* Switch to the new descriptor */ - ret = msh_update_path(desc); - if (ret < 0) - { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - } - return MR_EOK; - } - - usage: - mr_msh_printf("usage: dselect =0)|-g>\r\n"); - return MR_EINVAL; -} - -static int msh_dioctl_offset(int argc, void *argv) -{ - int cmd = MR_CTL_SET_OFFSET; - int offset; - int ret; - - /* Check the arguments and print usage */ - if (argc < 2) - { - goto usage; - } - - /* Parse <-g|offset> */ + /* Parse <-g|position> */ if (strncmp(MR_MSH_GET_ARG(2), "-g", 2) == 0) { cmd = -cmd; } else { - ret = sscanf(MR_MSH_GET_ARG(2), "%d", &offset); + ret = sscanf(MR_MSH_GET_ARG(2), "%d", &position); if (ret < 1) { goto usage; } } - /* Get/set the offset */ - mr_dev_ioctl(MSH_GET_DESC(), cmd, &offset); + /* Get/set the position */ + mr_dev_ioctl(MSH_GET_DESC(), cmd, &position); if (cmd < 0) { - mr_msh_printf("%d\r\n", offset); + mr_msh_printf("%d\r\n", position); } else { - /* Update the offset */ + /* Update the path */ msh_update_path(MSH_GET_DESC()); } - return MR_EOK; + return; usage: - mr_msh_printf("usage: dioctl off \r\n"); - return MR_EINVAL; + mr_msh_printf("usage: dioctl pos \r\n"); } -static int msh_dioctl_bufsz(int argc, void *argv) +MR_INLINE void msh_dioctl_bufsz(int argc, void *argv) { - int cmd; - int bufsz; - int ret; + int cmd, bufsz, ret; - /* Check the arguments and print usage */ - if (argc < 3) + if ((argc < 3) || (strncmp(MR_MSH_GET_ARG(2), "-h", 2) == 0)) { goto usage; } @@ -231,16 +228,16 @@ static int msh_dioctl_bufsz(int argc, void *argv) /* Parse <-r|-w> */ if (strncmp(MR_MSH_GET_ARG(3), "-r", 2) == 0) { - cmd = MR_CTL_SET_RD_BUFSZ; + cmd = MR_IOC_SRBSZ; } else if (strncmp(MR_MSH_GET_ARG(3), "-w", 2) == 0) { - cmd = MR_CTL_SET_WR_BUFSZ; + cmd = MR_IOC_SWBSZ; } else { goto usage; } - /* Parse <-g|bufsz (>=0)> */ + /* Parse <-g|bufsz> */ if (strncmp(MR_MSH_GET_ARG(2), "-g", 2) == 0) { cmd = -cmd; @@ -257,8 +254,8 @@ static int msh_dioctl_bufsz(int argc, void *argv) ret = mr_dev_ioctl(MSH_GET_DESC(), cmd, &bufsz); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: bufsz: %s\r\n", mr_strerror(ret)); + return; } /* If the command is <-g>, print the buffer size */ @@ -266,21 +263,18 @@ static int msh_dioctl_bufsz(int argc, void *argv) { mr_msh_printf("%d\r\n", bufsz); } - return MR_EOK; + return; usage: mr_msh_printf("usage: dioctl bufsz =0)|-g> <-r|-w>\r\n"); - return MR_EINVAL; } -static int msh_dioctl_datasz(int argc, void *argv) +MR_INLINE void msh_dioctl_datasz(int argc, void *argv) { - int cmd = MR_CTL_SET_RD_BUFSZ; - int datasz; - int ret; + int cmd, datasz, ret; /* Check the arguments and print usage */ - if (argc < 3) + if ((argc < 3) || (strncmp(MR_MSH_GET_ARG(2), "-h", 2) == 0)) { goto usage; } @@ -288,10 +282,10 @@ static int msh_dioctl_datasz(int argc, void *argv) /* Parse <-r|-w> */ if (strncmp(MR_MSH_GET_ARG(3), "-r", 2) == 0) { - cmd = MR_CTL_CLR_RD_BUF; + cmd = MR_IOC_CRBD; } else if (strncmp(MR_MSH_GET_ARG(3), "-w", 2) == 0) { - cmd = MR_CTL_CLR_WR_BUF; + cmd = MR_IOC_CWBD; } else { goto usage; @@ -310,8 +304,8 @@ static int msh_dioctl_datasz(int argc, void *argv) ret = mr_dev_ioctl(MSH_GET_DESC(), cmd, &datasz); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: datasz: %s\r\n", mr_strerror(ret)); + return; } /* If the command is <-g>, print the buffer size */ @@ -319,20 +313,20 @@ static int msh_dioctl_datasz(int argc, void *argv) { mr_msh_printf("%d\r\n", datasz); } - return MR_EOK; + return; usage: mr_msh_printf("usage: dioctl datasz <-c|-g> <-r|-w>\r\n"); - return MR_EINVAL; } -static int msh_cmd_dioctl_cfg(int argc, void *argv) +MR_INLINE void msh_cmd_dioctl_cfg(int argc, void *argv) { - int cfg[32]; - int ret; +#ifndef MR_CFG_MSH_ARGS_NUM +#define MR_CFG_MSH_ARGS_NUM (8) +#endif /* MR_CFG_MSH_ARGS_NUM */ + int cfg[MR_CFG_MSH_ARGS_NUM] = {0}, ret; - /* Check the arguments and print usage */ - if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) + if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(2), "-h", 2) == 0)) { goto usage; } @@ -342,18 +336,18 @@ static int msh_cmd_dioctl_cfg(int argc, void *argv) if (strncmp(MR_MSH_GET_ARG(2), "-g", 2) == 0) { /* Get the config */ - ret = mr_dev_ioctl(MSH_GET_DESC(), MR_CTL_GET_CONFIG, cfg); + ret = mr_dev_ioctl(MSH_GET_DESC(), MR_IOC_GCFG, cfg); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: cfg: %s\r\n", mr_strerror(ret)); + return; } for (size_t i = 0; i < ret / sizeof(int); i++) { mr_msh_printf("%d ", cfg[i]); } mr_msh_printf("\r\n"); - return MR_EOK; + return; } /* Parse */ @@ -367,78 +361,23 @@ static int msh_cmd_dioctl_cfg(int argc, void *argv) } /* Set the config */ - ret = mr_dev_ioctl(MSH_GET_DESC(), MR_CTL_SET_CONFIG, cfg); + ret = mr_dev_ioctl(MSH_GET_DESC(), MR_IOC_SCFG, cfg); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: cfg: %s\r\n", mr_strerror(ret)); + return; } - return MR_EOK; + return; usage: mr_msh_printf("usage: dioctl cfg \r\n"); - return MR_EINVAL; } -static int msh_dioctl_flags(int argc, void *argv) +MR_INLINE void msh_dioctl_cmd(int argc, void *argv) { - int cmd; + int args[MR_CFG_MSH_ARGS_NUM] = {0}, cmd, ret; - /* Check the arguments and print usage */ - if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) - { - goto usage; - } - - /* Parse <-o|-s> */ - if (strncmp(MR_MSH_GET_ARG(2), "-o", 2) == 0) - { - cmd = MR_CTL_GET_OFLAGS; - } else if (strncmp(MR_MSH_GET_ARG(2), "-s", 2) == 0) - { - cmd = MR_CTL_GET_SFLAGS; - } else - { - goto usage; - } - - /* Parse <-g> */ - if ((MR_MSH_GET_ARG(3) != MR_NULL) && (strncmp(MR_MSH_GET_ARG(3), "-g", 2) == 0)) - { - int flags; - - mr_dev_ioctl(MSH_GET_DESC(), cmd, &flags); - if (MR_BIT_IS_SET(flags, MR_OFLAG_RDWR) == MR_ENABLE) - { - mr_msh_printf("rw"); - } else if (MR_BIT_IS_SET(flags, MR_OFLAG_WRONLY) == MR_ENABLE) - { - mr_msh_printf("w"); - } else - { - mr_msh_printf("r"); - } - if (MR_BIT_IS_SET(flags, MR_OFLAG_NONBLOCK) == MR_ENABLE) - { - mr_msh_printf("n"); - } - mr_msh_printf("\r\n"); - return MR_EOK; - } - - usage: - mr_msh_printf("usage: dioctl flags <-s|-o> <-g>\r\n"); - return MR_EINVAL; -} - -static int msh_dioctl_cmd(int argc, void *argv) -{ - int cmd; - int args[32]; - int ret; - - /* Check the arguments and print usage */ - if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) + if ((argc < 2) || (strncmp(MR_MSH_GET_ARG(2), "-h", 2) == 0)) { goto usage; } @@ -473,15 +412,14 @@ static int msh_dioctl_cmd(int argc, void *argv) ret = mr_dev_ioctl(MSH_GET_DESC(), cmd, args); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: %s: %s\r\n", MR_MSH_GET_ARG(1), mr_strerror(ret)); + return; } for (size_t i = 0; i < ret / sizeof(int); i++) { mr_msh_printf("%d ", args[i]); } mr_msh_printf("\r\n"); - return MR_EOK; } else { /* Set the arguments */ @@ -496,54 +434,47 @@ static int msh_dioctl_cmd(int argc, void *argv) ret = mr_dev_ioctl(MSH_GET_DESC(), cmd, args); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dioctl: %s: %s\r\n", MR_MSH_GET_ARG(1), mr_strerror(ret)); } } - return MR_EOK; + return; usage: mr_msh_printf("usage: dioctl \r\n"); - return MR_EINVAL; } -static int msh_cmd_dioctl(int argc, void *argv) +static void msh_cmd_dioctl(int argc, void *argv) { - /* Check the arguments and print usage */ if ((argc < 1) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) { goto usage; } - /* Parse */ - if (strncmp(MR_MSH_GET_ARG(1), "off", 6) == 0) + /* Parse */ + if (strncmp(MR_MSH_GET_ARG(1), "pos", 6) == 0) { - return msh_dioctl_offset(argc, argv); + msh_dioctl_pos(argc, argv); } else if (strncmp(MR_MSH_GET_ARG(1), "cfg", 3) == 0) { - return msh_cmd_dioctl_cfg(argc, argv); + msh_cmd_dioctl_cfg(argc, argv); } else if (strncmp(MR_MSH_GET_ARG(1), "bufsz", 5) == 0) { - return msh_dioctl_bufsz(argc, argv); + msh_dioctl_bufsz(argc, argv); } else if (strncmp(MR_MSH_GET_ARG(1), "datasz", 6) == 0) { - return msh_dioctl_datasz(argc, argv); - } else if (strncmp(MR_MSH_GET_ARG(1), "flags", 6) == 0) - { - return msh_dioctl_flags(argc, argv); + msh_dioctl_datasz(argc, argv); } else { - return msh_dioctl_cmd(argc, argv); + msh_dioctl_cmd(argc, argv); } + return; usage: mr_msh_printf("usage: dioctl \r\n"); - mr_msh_printf(" dioctl off \r\n"); + mr_msh_printf(" dioctl pos \r\n"); mr_msh_printf(" dioctl cfg \r\n"); mr_msh_printf(" dioctl bufsz =0)|-g> <-r|-w>\r\n"); mr_msh_printf(" dioctl datasz <-c|-g> <-r|-w>\r\n"); - mr_msh_printf(" dioctl flags <-s|-o> <-g>\r\n"); - return MR_EINVAL; } static void msh_printf_1(void *buf, size_t size, char format) @@ -610,24 +541,20 @@ static void (*msh_printf_fn[])(void *buf, size_t size, char format) = msh_printf_4, }; -static int msh_cmd_dread(int argc, void *argv) +static void msh_cmd_dread(int argc, void *argv) { - int printf_index = 0; - int itemsz = 1; + uint8_t buf[128] = {0}; + int printf_index = 0, itemsz = 1, count, ret; char format = 'x'; - int size; - uint8_t buf[128]; - int ret; - /* Check the arguments and print usage */ if ((argc < 1) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) { goto usage; } /* Parse */ - ret = sscanf(MR_MSH_GET_ARG(1), "%d", &size); - if ((ret < 1) || (size < 0)) + ret = sscanf(MR_MSH_GET_ARG(1), "%d", &count); + if ((ret < 1) || (count < 0)) { goto usage; } @@ -681,37 +608,36 @@ static int msh_cmd_dread(int argc, void *argv) } /* Read data */ - size = MR_BOUND(size * itemsz, 0, sizeof(buf)); - ret = (int)mr_dev_read(MSH_GET_DESC(), buf, size); + count = MR_BOUND(count * itemsz, 0, sizeof(buf)); + ret = (int)mr_dev_read(MSH_GET_DESC(), buf, count); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); - return ret; + mr_msh_printf("dread: %s\r\n", mr_strerror(ret)); + return; + } else if (ret == 0) + { + mr_msh_printf("dread: no data\r\n"); + return; } /* Print data */ - msh_printf_fn[printf_index](buf, size, format); + msh_printf_fn[printf_index](buf, ret, format); mr_msh_printf("\r\n"); - return MR_EOK; + return; usage: - mr_msh_printf("usage: dread [-1|-2|-4] [-x|-d|-u|-c]\r\n"); - mr_msh_printf(" [-1]: \r\n"); - mr_msh_printf(" [-2]: \r\n"); - mr_msh_printf(" [-4]: \r\n"); - return MR_EINVAL; + mr_msh_printf("usage: dread [-1|-2|-4] [-x|-d|-u|-c]\r\n"); + mr_msh_printf(" [-1]: \r\n"); + mr_msh_printf(" [-2]: \r\n"); + mr_msh_printf(" [-4]: \r\n"); } -static int msh_cmd_dwrite(int argc, void *argv) +static void msh_cmd_dwrite(int argc, void *argv) { - int data_index = 1; - int itemsz = 1; - char format = 'x'; - int size; uint8_t buf[128]; - int ret; + int data_index = 1, itemsz = 1, count, ret; + char format = 'x'; - /* Check the arguments and print usage */ if ((argc < 1) || (strncmp(MR_MSH_GET_ARG(1), "-h", 2) == 0)) { goto usage; @@ -765,7 +691,7 @@ static int msh_cmd_dwrite(int argc, void *argv) } /* Parse data and write */ - size = MR_BOUND((argc - data_index + 1) * itemsz, 0, sizeof(buf)); + count = MR_BOUND((argc - data_index + 1) * itemsz, 0, sizeof(buf)); for (size_t i = data_index; i <= (argc < (sizeof(buf) / itemsz + data_index) ? argc : (sizeof(buf) / itemsz + data_index)); i++) @@ -791,24 +717,24 @@ static int msh_cmd_dwrite(int argc, void *argv) goto usage; } } - ret = (int)mr_dev_write(MSH_GET_DESC(), buf, size); + ret = (int)mr_dev_write(MSH_GET_DESC(), buf, count); if (ret < 0) { - mr_msh_printf("error: %s\r\n", mr_strerror(ret)); + mr_msh_printf("dwrite: %s\r\n", mr_strerror(ret)); } - return ret; + return; usage: mr_msh_printf("usage: dwrite [-1|-2|-4] [-x|-d|-u|-c] \r\n"); - return MR_EINVAL; } /** * @brief Exports device MSH commands. */ +MR_MSH_CMD_EXPORT(dlist, msh_cmd_dlist, "list all devices."); +MR_MSH_CMD_EXPORT(dselect, msh_cmd_dselect, "select a device by descriptor."); MR_MSH_CMD_EXPORT(dopen, msh_cmd_dopen, "open a device."); MR_MSH_CMD_EXPORT(dclose, msh_cmd_dclose, "close a device."); -MR_MSH_CMD_EXPORT(dselect, msh_cmd_dselect, "select a device."); MR_MSH_CMD_EXPORT(dioctl, msh_cmd_dioctl, "ioctl a device."); MR_MSH_CMD_EXPORT(dread, msh_cmd_dread, "read from a device."); MR_MSH_CMD_EXPORT(dwrite, msh_cmd_dwrite, "write to a device."); diff --git a/include/components/mr_msh.h b/include/components/mr_msh.h index 37acee2..8e75859 100644 --- a/include/components/mr_msh.h +++ b/include/components/mr_msh.h @@ -17,18 +17,23 @@ extern "C" { #ifdef MR_USING_MSH +/** + * @addtogroup Msh + * @{ + */ + /** * @brief MSH command structure. */ struct mr_msh_cmd { const char *name; /**< Name */ - int (*call)(int argc, void *args); /**< Callback function */ + void (*fn)(int argc, void *args); /**< Callback function */ const char *help; /**< Help information */ }; /** - * @brief Exports a MSH command. + * @brief This macro function exports a MSH command. * * @param name The name of the command. * @param fn The callback function. @@ -65,11 +70,6 @@ struct mr_msh_cmd #define MR_MSH_COLOR_GREEN(str) str #endif /* MR_USING_MSH_PRINTF_COLOR */ -/** - * @addtogroup Msh. - * @{ - */ -int mr_msh_printf_output(const char *buf, size_t size); int mr_msh_input(char *c); int mr_msh_printf(const char *fmt, ...); void mr_msh_set_prompt(char *prompt);