diff --git a/cli.c b/cli.c index b22983b..18d4c8e 100644 --- a/cli.c +++ b/cli.c @@ -1,21 +1,25 @@ /** * @file cli.c - * Implements console command handling for the SD logger program. - * Interface-specific handling should be done in another file, this file - * abstracts it. + * Implements a generic console that can read command strings. Command + * strings are not handled in this file. + * Interface-specific (UART, SPI, etc...) handling should be done in + * another file, this file abstracts it. * * This code assumes that the connected terminal emulates a VT-100. */ #include #include +#include +#include #include "cli.h" +#include "commands.h" #define CLI_EMPTY_LINELEN -1 // Signifies an "unused" history buffer. #define CLI_PROMPT "-> " -// Static functions to handle sub cases for the CLI. +// functions to handle sub cases for the CLI. static void cli_handle_return(CLIContext *context); static void cli_handle_esc(CLIContext *context); static void cli_handle_backspace(CLIContext *context); @@ -29,13 +33,30 @@ static void move_line_index(CLIContext *context, bool forwards); void cli_context_init(CLIContext *context) { int i; context->cursor = NULL; - context->current_line = 0; + context->line_idx = 0; for (i = 0; i < CLI_BUFCNT; i++) { // Set the line length context->lines[i].len = CLI_EMPTY_LINELEN; } } +/** + * CLI Printf function. Same syntax as printf. + * @param context CLI context to print to + * @param format printf style format string + */ +void cli_printf(CLIContext *context, const char *format, ...) { + va_list args; + int num_print; + char output_buf[PRINT_BUFLEN]; + // Init variable args list. + va_start(args, format); + // Print to buffer and destroy varargs list. + num_print = vsnprintf(output_buf, PRINT_BUFLEN, format, args); + va_end(args); + context->cli_write(output_buf, num_print); +} + /** * Runs the embedded CLI for this program. The provided context exposes read * and write functions for a communication interface. @@ -51,7 +72,7 @@ void start_cli(CLIContext *context) { while (1) { // Print prompt. context->cli_write(CLI_PROMPT, sizeof(CLI_PROMPT) - 1); - current_line = &(context->lines[context->current_line]); + current_line = &(context->lines[context->line_idx]); // Initialize cursor location to start of buffer. context->cursor = current_line->line_buf; // Zero length of buffer. @@ -62,7 +83,7 @@ void start_cli(CLIContext *context) { * we actually use. */ move_line_index(context, true); - context->lines[context->current_line].len = CLI_EMPTY_LINELEN; + context->lines[context->line_idx].len = CLI_EMPTY_LINELEN; // Revert change to current line idx. move_line_index(context, false); // Read data until a LF is found. @@ -110,7 +131,7 @@ void start_cli(CLIContext *context) { * @param context: CLI context to use for this command. */ static void cli_handle_return(CLIContext *context) { - CLI_Line *current_line = &context->lines[context->current_line]; + CLI_Line *current_line = &context->lines[context->line_idx]; // Write a newline and carriage return to the console. context->cli_write("\r\n", 2); // Null terminate the command. @@ -125,10 +146,8 @@ static void cli_handle_return(CLIContext *context) { return; } move_line_index(context, true); - // TODO: handle command. - context->cli_write("Got Data:", 9); - context->cli_write(current_line->line_buf, current_line->len); - context->cli_write("\r\n", 2); + // handle command. + handle_command(context, current_line->line_buf); } /** @@ -139,7 +158,7 @@ static void cli_handle_return(CLIContext *context) { * @param context: CLI context to use */ static void cli_handle_backspace(CLIContext *context) { - CLI_Line *current_line = &context->lines[context->current_line]; + CLI_Line *current_line = &context->lines[context->line_idx]; /* * Backspace: send backspace and space to clear * character. Edit the value in the command buffer as well. @@ -167,7 +186,7 @@ static void cli_handle_backspace(CLIContext *context) { * @param context: Context escape character recieved on. */ static void cli_handle_esc(CLIContext *context) { - CLI_Line *current_line = &context->lines[context->current_line]; + CLI_Line *current_line = &context->lines[context->line_idx]; char esc_buf[2]; /** * Escape sequence. Read more characters from the @@ -193,9 +212,9 @@ static void cli_handle_esc(CLIContext *context) { * to the prior command. */ move_line_index(context, false); - if (context->lines[context->current_line].len != CLI_EMPTY_LINELEN) { + if (context->lines[context->line_idx].len != CLI_EMPTY_LINELEN) { // Update the line buffer and current line. - current_line = &(context->lines[context->current_line]); + current_line = &(context->lines[context->line_idx]); // Set cursor to end of line buffer. context->cursor = ¤t_line->line_buf[current_line->len]; // Clear line of console and write line from history. @@ -215,9 +234,9 @@ static void cli_handle_esc(CLIContext *context) { * to the next command. */ move_line_index(context, true); - if (context->lines[context->current_line].len != CLI_EMPTY_LINELEN) { + if (context->lines[context->line_idx].len != CLI_EMPTY_LINELEN) { // Update the line buffer, cursor, and current line. - current_line = &(context->lines[context->current_line]); + current_line = &(context->lines[context->line_idx]); // Set cursor to end of line buffer. context->cursor = ¤t_line->line_buf[current_line->len]; // Clear line of console and write line from history. @@ -266,14 +285,14 @@ static void move_line_index(CLIContext *context, bool forwards) { * forwards or back we are moving the index, and our modulo is constant. */ if (forwards) { - new_idx = context->current_line + 1; + new_idx = context->line_idx + 1; if (new_idx == CLI_BUFCNT) new_idx = 0; - context->current_line = new_idx; + context->line_idx = new_idx; } else { - new_idx = context->current_line - 1; + new_idx = context->line_idx - 1; if (new_idx < 0) new_idx = CLI_BUFCNT - 1; - context->current_line = new_idx; + context->line_idx = new_idx; } } \ No newline at end of file diff --git a/cli.h b/cli.h index 096ec03..9357e47 100644 --- a/cli.h +++ b/cli.h @@ -1,15 +1,20 @@ /** * @file cli.h - * Implements console command handling for the SD logger program. - * Interface-specific handling should be done in another file, this file - * abstracts it. + * Implements a generic console that can read command strings. Command + * strings are not handled in this file. + * Interface-specific (UART, SPI, etc...) handling should be done in + * another file, this file abstracts it. + * + * This code assumes that the connected terminal emulates a VT-100. */ + #ifndef CLI_H #define CLI_H /** CLI configuration parameters */ #define CLI_MAX_LINE 80 // max command length -#define CLI_HISTORY 3 // max number of past commands to store +#define CLI_HISTORY 3 // max number of past commands to store +#define PRINT_BUFLEN 80 // size of printf buffer to use. #define CLI_BUFCNT CLI_HISTORY + 2 // Used internally for CLI buffer length @@ -30,9 +35,16 @@ typedef struct { /*! line buffers */ CLI_Line lines[CLI_BUFCNT]; /*! Index of current line buffer */ - int current_line; + int line_idx; } CLIContext; +/** + * CLI Printf function. Same syntax as printf. + * @param context CLI context to print to + * @param format printf style format string + */ +void cli_printf(CLIContext *context, const char *format, ...); + /** * Initializes memory for a CLI context. * @param context: CLI context to init. diff --git a/commands.c b/commands.c new file mode 100644 index 0000000..863d837 --- /dev/null +++ b/commands.c @@ -0,0 +1,74 @@ +/** + * @file commands.c + * Implements CLI command handlers. + */ +#include "cli.h" + +typedef struct { + char *cmd_name; + int (*cmd_fxn)(CLIContext *, char**, int); + char *cmd_help; +} CmdEntry; + +#include + +/* + * Maximum number of arguments that the parser will handle. + * Includes command name. + */ +#define MAX_ARGV 8 + + +static int help(CLIContext *cxt, char **argv, int argc); + +/** + * Declaration of commands. Syntax is as follows: + * {"NAME_OF_COMMAND", command_function, "HELP_STRING"} + * The command function follows the signature of "main", but with a + * Context Parameter, ex: + * int command_function(CLIContext *ctx, char** argv, int argc) + * A return value of zero indicates success, anything else indicates failure. + */ + +const CmdEntry COMMANDS[] = { + {"help", help, "Prints help for this commandline"}, + // Add more entries here. + {NULL, NULL, NULL} +}; + + + +/** + * Handles a command, as given by the null terminated string "cmd" + * @param ctx: CLI context to print to. + * @param cmd: command string to handle. + * @return 0 on successful handling, or another value on failure. + */ +int handle_command(CLIContext *ctx, char *cmd) { + char *arguments[MAX_ARGV]; + // The parser interprets a space as a delimeter between arguments. + (void)arguments; + ctx->cli_write("This will work\r\n", 16); + cli_printf(ctx, "Hello there"); + return 0; +} + + +/** + * Help function. Prints avaliable commandline targets. + * @param argv: list of all string arguments given (first will be "help") + * @param argc: length of the argv array. + */ +static int help(CLIContext *ctx, char **argv, int argc) { + CmdEntry *entry; + if (argc == 1) { + cli_printf(ctx, "Test\n"); + entry = (CmdEntry*)&COMMANDS[0]; + while (entry->cmd_name != NULL) { + // Write command name and newline + cli_printf(ctx, "%s\n", entry->cmd_name); + entry++; + } + } + return 0; +} \ No newline at end of file diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..29940be --- /dev/null +++ b/commands.h @@ -0,0 +1,17 @@ +/** + * @file commands.h + * Implements CLI command handlers. + */ + +#ifndef COMMANDS_H +#define COMMANDS_H + +/** + * Handles a command, as given by the null terminated string "cmd" + * @param ctx: CLI context to print to. + * @param cmd: command string to handle. + * @return 0 on successful handling, or another value on failure. + */ +int handle_command(CLIContext *ctx, char *cmd); + +#endif \ No newline at end of file diff --git a/makefile b/makefile index b14c7ee..906d4a5 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ ###### CHANGE LOCATION TO YOUR CODEGEN TOOLS INSTALL DIR. UNIX PATH (no backslashes) ####### -CODEGEN_INSTALL_DIR = /home/danieldegrasse/Downloads/gcc-arm-none-eabi-4_7-2012q4 +CODEGEN_INSTALL_DIR = /usr CC = "$(CODEGEN_INSTALL_DIR)/bin/arm-none-eabi-gcc" LNK = "$(CODEGEN_INSTALL_DIR)/bin/arm-none-eabi-gcc"