diff --git a/project/Core/Src/tcp_cmd.c b/project/Core/Src/tcp_cmd.c index 2524a4f..c61721c 100644 --- a/project/Core/Src/tcp_cmd.c +++ b/project/Core/Src/tcp_cmd.c @@ -32,8 +32,8 @@ static void tcp_cmd_close(struct tcp_pcb* pcb); /** * @brief This function shifts the arguments in argv and argc - * @param argc The argc pointer - * @param argv The argv pointer + * @param[in,out] argc The argc pointer + * @param[in,out] argv The argv pointer * @return The shifted argument */ static char* shift_args(int* argc, char*** argv) { @@ -48,23 +48,24 @@ static char* shift_args(int* argc, char*** argv) { /** * @brief This function converts a string to a color - * @param argc The number of arguments - * @param argv The arguments - * @param color The color to write to - * @return Returns 0 if successful, 1 if not + * @param[in] argc The number of arguments + * @param[in] argv The arguments + * @param[out] color The color to write to + * @return true The conversion failed + * @return false The conversion succeeded */ -static uint32_t str_to_color(int argc, char** argv, uint32_t* color) { +static bool str_to_color(int argc, char** argv, uint32_t* color) { if (argc == 1) { *color = (uint32_t)strtoul(argv[0], NULL, 16); *color ^= 0xff000000; - return 0; + return false; } if (argc == 3) { *color = 0xff000000; *color |= (uint32_t)strtoul(argv[0], NULL, 10) << 16; *color |= (uint32_t)strtoul(argv[1], NULL, 10) << 8; *color |= (uint32_t)strtoul(argv[2], NULL, 10); - return 0; + return false; } if (argc == 4) { *color = 0xff000000; @@ -72,215 +73,15 @@ static uint32_t str_to_color(int argc, char** argv, uint32_t* color) { *color |= (uint32_t)strtoul(argv[1], NULL, 10) << 16; *color |= (uint32_t)strtoul(argv[2], NULL, 10) << 8; *color |= (uint32_t)strtoul(argv[3], NULL, 10); - return 0; + return false; } - return 1; -} - -/** - * @brief This function is a wrapper for tcp_write and tcp_output - * @param pcb The tcp_pcb struct to write to - * @param str The string to write - */ -static void tcp_cmd_write(struct tcp_pcb* pcb, const char* str) { - tcp_write(pcb, str, strlen(str), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); - tcp_output(pcb); -} - -/** - * @brief This function prints the header of the tcp command interface - * @param pcb The tcp_pcb struct to write to - */ -static void tcp_cmd_print_header(struct tcp_pcb* pcb) { - tcp_cmd_write(pcb, " Welcome to the TCP CMD interface\n" - "(Type help for a list of the commands! exit to close)\n" - "============================================================\n" - "$>"); -} - -/** - * @brief This function prints the help text - * @param pcb The tcp_pcb struct to write to - */ -static void tcp_cmd_print_help(struct tcp_pcb* pcb) { - LOG_INFO(TAG, "Printing help"); - tcp_cmd_write(pcb, "help : shows a list of commands\n" - "clear text/images : clears the text or images on the lcd\n" - "text \"\" : puts text on the lcd\n" - "bgColor () : set the background color of the lcd\n" - "color () : set the color of the text\n" - "listFiles : shows a list with images in the filesystem\n" - "setImage : put an image on the screen\n" - "setGif : put a gif on the screen\n" - "exit : closes the connection\n"); -} - -static void tcp_cmd_clear(struct tcp_pcb* pcb, int argc, char** argv) { - if (argc == 0) { - LOG_INFO(TAG, "Clearing screen"); - lcd_clear_text(); - lcd_clear_images(); - return; - } - if (argc == 1) { - if (strcmp(argv[0], "text") == 0) { - LOG_INFO(TAG, "Clearing text"); - lcd_clear_text(); - return; - } - if (strcmp(argv[0], "images") == 0) { - LOG_INFO(TAG, "Clearing images"); - lcd_clear_images(); - return; - } - LOG_WARN(TAG, "Bad usage of clear"); - tcp_cmd_write(pcb, "Usage: clear\n"); - tcp_cmd_write(pcb, "Usage: clear text\n"); - tcp_cmd_write(pcb, "Usage: clear images\n"); - return; - } -} - -static void tcp_cmd_text(struct tcp_pcb* pcb, int argc, char** argv) { - if (argc == 1) { - LOG_INFO(TAG, "Setting text %s @ 10, 10", argv[0]); - lcd_display_text((const char*)argv[0], 10, 10, color_txt, color_bg, LCD_FONT24); - return; - } - if (argc == 3) { - LOG_INFO(TAG, "Setting text %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), - (uint32_t)strtoul(argv[2], NULL, 10)); - lcd_display_text((const char*)argv[0], (uint32_t)strtoul(argv[1], NULL, 10), - (uint32_t)strtoul(argv[2], NULL, 10), color_txt, color_bg, LCD_FONT24); - return; - } - LOG_WARN(TAG, "Bad usage of text"); - tcp_cmd_write(pcb, "Usage: text \"\"\n"); - tcp_cmd_write(pcb, "Usage: text \n"); - tcp_cmd_write(pcb, "Usage: text \"\" \n"); -} - -static void tcp_cmd_bg_color(struct tcp_pcb* pcb, int argc, char** argv) { - if (!str_to_color(argc, argv, &color_bg)) { - LOG_INFO(TAG, "Setting background color to %08lX", color_bg); - return; - } - LOG_WARN(TAG, "Bad usage of bgcolor"); - tcp_cmd_write(pcb, "Usage: bgcolor 0x\n"); - tcp_cmd_write(pcb, "Usage: bgcolor 0x\n"); - tcp_cmd_write(pcb, "Usage: bgcolor \n"); - tcp_cmd_write(pcb, "Usage: bgcolor \n"); -} - -static void tcp_cmd_color(struct tcp_pcb* pcb, int argc, char** argv) { - if (!str_to_color(argc, argv, &color_txt)) { - LOG_INFO(TAG, "Setting color to %08lX", color_txt); - return; - } - LOG_WARN(TAG, "Bad usage of color"); - tcp_cmd_write(pcb, "Usage: color 0x\n"); - tcp_cmd_write(pcb, "Usage: color 0x\n"); - tcp_cmd_write(pcb, "Usage: color \n"); - tcp_cmd_write(pcb, "Usage: color \n"); -} - -static void tcp_cmd_list_files(struct tcp_pcb* pcb, int argc, char** argv) { - UNUSED(argv); - if (argc == 0) { - LOG_INFO(TAG, "Listing files"); - void* mem = NULL; // Pointer for internal use by the llfs library - llfs_file_t* file; - while ((file = llfs_next_file(&mem, NULL)) != NULL) { - tcp_cmd_write(pcb, file->name); - tcp_cmd_write(pcb, "\n"); - } - return; - } - LOG_WARN(TAG, "Bad usage of listfiles"); - tcp_cmd_write(pcb, "Usage: listfiles\n"); - return; -} - -static void tcp_cmd_set_image(struct tcp_pcb* pcb, int argc, char** argv) { - char* ext = NULL; - if (argc >= 1) { - ext = llfs_get_filename_ext(argv[0]); - if (strcmp(ext, "bmp") != 0) { - LOG_WARN(TAG, "setimage: File is not a bmp"); - tcp_cmd_write(pcb, "File is not a bmp\n"); - return; - } - } - if (argc == 1) { - LOG_INFO(TAG, "Setting image %s @ 0, 0", argv[0]); - lcd_draw_img_from_fs(argv[0], 0, 0); - return; - } - if (argc == 3) { - LOG_INFO(TAG, "Setting image %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), - (uint32_t)strtoul(argv[2], NULL, 10)); - lcd_draw_img_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10)); - return; - } - LOG_WARN(TAG, "Bad usage of setimage"); - tcp_cmd_write(pcb, "Usage: setimage \n"); - tcp_cmd_write(pcb, "Usage: setimage \n"); -} - -static void tcp_cmd_set_gif(struct tcp_pcb* pcb, int argc, char** argv) { - char* ext = NULL; - if (argc >= 1) { - ext = llfs_get_filename_ext(argv[0]); - if (strcmp(ext, "gif") != 0) { - LOG_WARN(TAG, "setgif: File is not a gif"); - tcp_cmd_write(pcb, "File is not a gif\n"); - return; - } - } - if (argc == 1) { - LOG_INFO(TAG, "Setting gif %s @ 0, 0", argv[0]); - lcd_draw_gif_from_fs(argv[0], 0, 0); - return; - } - if (argc == 3) { - LOG_INFO(TAG, "Setting gif %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), - (uint32_t)strtoul(argv[2], NULL, 10)); - lcd_draw_gif_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10)); - return; - } - - LOG_WARN(TAG, "Bad usage of setgif"); - tcp_cmd_write(pcb, "Usage: setgif \n"); - tcp_cmd_write(pcb, "Usage: setgif \n"); -} - -static void tcp_cmd_exit(struct tcp_pcb* pcb, int argc, char** argv) { - UNUSED(argv); - if (argc == 0) { - LOG_INFO(TAG, "Closing connection"); - tcp_cmd_write(pcb, "Exiting...\n"); - lcd_clear_images(); - lcd_clear_text(); - tcp_close(pcb); - return; - } - - LOG_WARN(TAG, "Bad usage of exit"); - tcp_cmd_write(pcb, "Usage: exit\n"); -} - -static void tcp_cmd_unknown_cmd(struct tcp_pcb* pcb, char* cmd) { - LOG_WARN(TAG, "Unknown command: %s", cmd); - tcp_cmd_write(pcb, "Unknown command: "); - tcp_cmd_write(pcb, cmd); - tcp_cmd_write(pcb, "\n"); - tcp_cmd_write(pcb, "Type help for list of commands\n"); + return true; } /** * @brief This function removes the newline from a string the string can contain multiple lines - * @param str The string to remove the newline from + * @param[in,out] str The string to remove the newline from */ void tcp_cmd_remove_newline(char* str, size_t len) { size_t i = 0; @@ -295,6 +96,12 @@ void tcp_cmd_remove_newline(char* str, size_t len) { str[i] = '\0'; } +/** + * @brief This function 'removes' the leading spaces from a string + * @param[in] str The string to remove the leading spaces from + * @param[in] len The length of the string + * @return char* A pointer to the first non-space character + */ char* tcp_cmd_remove_leading_space(char* str, size_t len) { size_t i = 0; if (str == NULL || str[0] == '\0' || len == 0) { @@ -311,7 +118,7 @@ char* tcp_cmd_remove_leading_space(char* str, size_t len) { /** * @brief This function converts a string to lowercase - * @param str The string to convert + * @param[in,out] str The string to convert */ void tcp_cmd_str_tolower(char* str) { int i = 0; @@ -324,9 +131,9 @@ void tcp_cmd_str_tolower(char* str) { /** * @brief This function finds the next token in the input string * If the token is between quotes, return the whole string between quotes - * @param input The input string - * @param delimiter The delimiters to use - * @param next The next token + * @param[in] input The input string + * @param[in] delimiter The delimiters to use + * @param[in,out] next The next token * @return char* The next token */ char* tcp_cmd_get_next_token(char* input, const char* delimiters, char** next) { @@ -365,12 +172,274 @@ char* tcp_cmd_get_next_token(char* input, const char* delimiters, char** next) { return input; } +/** + * @brief This function is a wrapper for tcp_write and tcp_output + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] str The string to write + */ +static void tcp_cmd_write(struct tcp_pcb* pcb, const char* str) { + tcp_write(pcb, str, strlen(str), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); + tcp_output(pcb); +} + +/** + * @brief This function prints the header of the tcp command interface + * @param[in] pcb The tcp_pcb struct to write to + */ +static void tcp_cmd_print_header(struct tcp_pcb* pcb) { + tcp_cmd_write(pcb, " Welcome to the TCP CMD interface\n" + "(Type help for a list of the commands! exit to close)\n" + "============================================================\n" + "$>"); +} + +/** + * @brief This function prints the help text + * @param[in] pcb The tcp_pcb struct to write to + */ +static void tcp_cmd_print_help(struct tcp_pcb* pcb) { + LOG_INFO(TAG, "Printing help"); + tcp_cmd_write(pcb, "help : shows a list of commands\n" + "clear text/images : clears the text or images on the lcd\n" + "text \"\" : puts text on the lcd\n" + "bgColor () : set the background color of the lcd\n" + "color () : set the color of the text\n" + "listFiles : shows a list with images in the filesystem\n" + "setImage : put an image on the screen\n" + "setGif : put a gif on the screen\n" + "exit : closes the connection\n"); +} + +/** + * @brief This function handles the clear command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_clear(struct tcp_pcb* pcb, int argc, char** argv) { + if (argc == 0) { + LOG_INFO(TAG, "Clearing screen"); + lcd_clear_text(); + lcd_clear_images(); + return; + } + if (argc == 1) { + if (strcmp(argv[0], "text") == 0) { + LOG_INFO(TAG, "Clearing text"); + lcd_clear_text(); + return; + } + if (strcmp(argv[0], "images") == 0) { + LOG_INFO(TAG, "Clearing images"); + lcd_clear_images(); + return; + } + LOG_WARN(TAG, "Bad usage of clear"); + tcp_cmd_write(pcb, "Usage: clear\n"); + tcp_cmd_write(pcb, "Usage: clear text\n"); + tcp_cmd_write(pcb, "Usage: clear images\n"); + return; + } +} + +/** + * @brief This function handles the text command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_text(struct tcp_pcb* pcb, int argc, char** argv) { + if (argc == 1) { + LOG_INFO(TAG, "Setting text %s @ 10, 10", argv[0]); + lcd_display_text((const char*)argv[0], 10, 10, color_txt, color_bg, LCD_FONT24); + return; + } + if (argc == 3) { + LOG_INFO(TAG, "Setting text %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), + (uint32_t)strtoul(argv[2], NULL, 10)); + lcd_display_text((const char*)argv[0], (uint32_t)strtoul(argv[1], NULL, 10), + (uint32_t)strtoul(argv[2], NULL, 10), color_txt, color_bg, LCD_FONT24); + return; + } + LOG_WARN(TAG, "Bad usage of text"); + tcp_cmd_write(pcb, "Usage: text \"\"\n"); + tcp_cmd_write(pcb, "Usage: text \n"); + tcp_cmd_write(pcb, "Usage: text \"\" \n"); +} + +/** + * @brief This function handles the bgcolor command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_bg_color(struct tcp_pcb* pcb, int argc, char** argv) { + if (!str_to_color(argc, argv, &color_bg)) { + LOG_INFO(TAG, "Setting background color to %08lX", color_bg); + return; + } + LOG_WARN(TAG, "Bad usage of bgcolor"); + tcp_cmd_write(pcb, "Usage: bgcolor 0x\n"); + tcp_cmd_write(pcb, "Usage: bgcolor 0x\n"); + tcp_cmd_write(pcb, "Usage: bgcolor \n"); + tcp_cmd_write(pcb, "Usage: bgcolor \n"); +} + +/** + * @brief This function handles the color command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_color(struct tcp_pcb* pcb, int argc, char** argv) { + if (!str_to_color(argc, argv, &color_txt)) { + LOG_INFO(TAG, "Setting color to %08lX", color_txt); + return; + } + LOG_WARN(TAG, "Bad usage of color"); + tcp_cmd_write(pcb, "Usage: color 0x\n"); + tcp_cmd_write(pcb, "Usage: color 0x\n"); + tcp_cmd_write(pcb, "Usage: color \n"); + tcp_cmd_write(pcb, "Usage: color \n"); +} + +/** + * @brief This function handles the listfiles command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_list_files(struct tcp_pcb* pcb, int argc, char** argv) { + UNUSED(argv); + if (argc == 0) { + LOG_INFO(TAG, "Listing files"); + void* mem = NULL; // Pointer for internal use by the llfs library + llfs_file_t* file; + while ((file = llfs_next_file(&mem, NULL)) != NULL) { + tcp_cmd_write(pcb, file->name); + tcp_cmd_write(pcb, "\n"); + } + return; + } + LOG_WARN(TAG, "Bad usage of listfiles"); + tcp_cmd_write(pcb, "Usage: listfiles\n"); + return; +} + +/** + * @brief This function handles the setimage command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_set_image(struct tcp_pcb* pcb, int argc, char** argv) { + char* ext = NULL; + if (argc >= 1) { + ext = llfs_get_filename_ext(argv[0]); + if (strcmp(ext, "bmp") != 0) { + LOG_WARN(TAG, "setimage: File is not a bmp"); + tcp_cmd_write(pcb, "File is not a bmp\n"); + return; + } + } + if (argc == 1) { + LOG_INFO(TAG, "Setting image %s @ 0, 0", argv[0]); + lcd_draw_img_from_fs(argv[0], 0, 0); + return; + } + if (argc == 3) { + LOG_INFO(TAG, "Setting image %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), + (uint32_t)strtoul(argv[2], NULL, 10)); + lcd_draw_img_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10)); + return; + } + LOG_WARN(TAG, "Bad usage of setimage"); + tcp_cmd_write(pcb, "Usage: setimage \n"); + tcp_cmd_write(pcb, "Usage: setimage \n"); +} + +/** + * @brief This function handles the setgif command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_set_gif(struct tcp_pcb* pcb, int argc, char** argv) { + char* ext = NULL; + if (argc >= 1) { + ext = llfs_get_filename_ext(argv[0]); + if (strcmp(ext, "gif") != 0) { + LOG_WARN(TAG, "setgif: File is not a gif"); + tcp_cmd_write(pcb, "File is not a gif\n"); + return; + } + } + if (argc == 1) { + LOG_INFO(TAG, "Setting gif %s @ 0, 0", argv[0]); + lcd_draw_gif_from_fs(argv[0], 0, 0); + return; + } + if (argc == 3) { + LOG_INFO(TAG, "Setting gif %s @ %lu, %lu", argv[0], (uint32_t)strtoul(argv[1], NULL, 10), + (uint32_t)strtoul(argv[2], NULL, 10)); + lcd_draw_gif_from_fs(argv[0], (uint32_t)strtoul(argv[1], NULL, 10), (uint32_t)strtoul(argv[2], NULL, 10)); + return; + } + + LOG_WARN(TAG, "Bad usage of setgif"); + tcp_cmd_write(pcb, "Usage: setgif \n"); + tcp_cmd_write(pcb, "Usage: setgif \n"); +} + +/** + * @brief This function handles the exit command + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] argc The number of arguments + * @param[in] argv The arguments + */ +static void tcp_cmd_exit(struct tcp_pcb* pcb, int argc, char** argv) { + UNUSED(argv); + if (argc == 0) { + LOG_INFO(TAG, "Closing connection"); + tcp_cmd_write(pcb, "Exiting...\n"); + lcd_clear_images(); + lcd_clear_text(); + tcp_close(pcb); + return; + } + + LOG_WARN(TAG, "Bad usage of exit"); + tcp_cmd_write(pcb, "Usage: exit\n"); +} + +/** + * @brief This function handles unknown commands + * + * @param[in] pcb The tcp_pcb struct to write to + * @param[in] cmd The command + */ +static void tcp_cmd_unknown_cmd(struct tcp_pcb* pcb, char* cmd) { + LOG_WARN(TAG, "Unknown command: %s", cmd); + tcp_cmd_write(pcb, "Unknown command: "); + tcp_cmd_write(pcb, cmd); + tcp_cmd_write(pcb, "\n"); + tcp_cmd_write(pcb, "Type help for list of commands\n"); +} + /** * @brief This function parses the command and calls the appropriate function * - * @param pcb Pointer to the tcp_pcb struct to write to - * @param argc Count of arguments - * @param argv Array of arguments + * @param[in] pcb Pointer to the tcp_pcb struct to write to + * @param[in] argc Count of arguments + * @param[in] argv Array of arguments * @return true Connection should be closed * @return false Connection should be kept open */ @@ -423,10 +492,10 @@ static bool tcp_cmd_parser(struct tcp_pcb* pcb, int argc, char** argv) { /** * @brief This function is called when the tcp connection receives data - * @param arg The argument ptr - * @param pcb The tcp_pcb struct - * @param p The pbuf struct - * @param err The error code from the tcp stack + * @param[in] arg The argument ptr + * @param[in] pcb The tcp_pcb struct + * @param[in] p The pbuf struct + * @param[in] err The error code from the tcp stack * @return err_t ERR_OK if successful */ err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) { @@ -510,9 +579,9 @@ defer: /** * @brief This function is called when a new tcp connection is accepted - * @param arg The argument - * @param pcb The tcp_pcb struct - * @param err The error + * @param[in] arg The argument + * @param[in] pcb The tcp_pcb struct + * @param[in] err The error * @return err_t ERR_OK */ static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) { @@ -529,7 +598,7 @@ static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) { } /** * @brief This function closes the tcp connection - * @param pcb The tcp_pcb struct to close + * @param[in] pcb The tcp_pcb struct to close */ static void tcp_cmd_close(struct tcp_pcb* pcb) { tcp_arg(pcb, NULL);