X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=app%2Ftriface%2Fprotocol.c;h=08910d0426e26b85b0caaaf6c7efa11f34bb9068;hb=cb475c2071d6be7048f8c5c06485b3cd8530708c;hp=1b66c9908dd9f5b2fc3dfe1cc93c35e888a4be7c;hpb=f7c30da5c75281bd2dfba133529a7ac1fa31e6b1;p=bertos.git diff --git a/app/triface/protocol.c b/app/triface/protocol.c old mode 100755 new mode 100644 index 1b66c990..08910d04 --- a/app/triface/protocol.c +++ b/app/triface/protocol.c @@ -1,6 +1,31 @@ /** * \file * * @@ -14,32 +39,31 @@ * \author Bernardo Innocenti */ -/*#* - *#* $Log$ - *#* Revision 1.1 2006/06/01 12:29:21 marco - *#* Add first simple protocol command (version request). - *#* - *#*/ - #include "protocol.h" #include +#include #include #include #include #include #include +#include #include +//#include + +#include "cmd_ctor.h" // MAKE_CMD, REGISTER_CMD // DEBUG: set to 1 to force interactive mode #define FORCE_INTERACTIVE 1 /** * True if we are in interactive mode, false if we are in protocol mode. - * In interactive mode, commands are read through readline() (prompt, completion, - * history) without IDs, and replies/errors are sent to the serial output. + * In interactive mode, commands are read through readline() (prompt, + * completion, history) without IDs, and replies/errors are sent to the serial + * output. * In protocol mode, we implement the default protocol */ static bool interactive; @@ -51,6 +75,7 @@ static struct RLContext rl_ctx; /** * Send a NAK asking the host to send the current message again. * + * \param ser serial port handle to output to. * \param err human-readable description of the error for debug purposes. */ INLINE void NAK(Serial *ser, const char *err) @@ -62,32 +87,75 @@ INLINE void NAK(Serial *ser, const char *err) #endif } +/* + * Print args on s, with format specified in t->result_fmt. + * Return number of valid arguments or -1 in case of error. + */ +static bool protocol_reply(Serial *s, const struct CmdTemplate *t, + const parms *args) +{ + unsigned short offset = strlen(t->arg_fmt) + 1; + unsigned short nres = strlen(t->result_fmt); + + ser_printf(s, "0"); + for (unsigned short i = 0; i < nres; ++i) + { + if (t->result_fmt[i] == 'd') + { + ser_printf(s, " %ld", args[offset+i].l); + } + else if (t->result_fmt[i] == 's') + { + ser_printf(s, " %s", args[offset+i].s); + } + else + { + abort(); + } + } + ser_printf(s, "\r\n"); + return true; +} + static void protocol_parse(Serial *ser, const char *buf) { const struct CmdTemplate *templ; - parms args[8]; // FIXME FIXME!! + /* Command check. */ templ = parser_get_cmd_template(buf); - if (!templ) { - NAK(ser, "invalid command"); + ser_print(ser, "-1 Invalid command."); return; } - // Extract the arguments for the command + parms args[PARSER_MAX_ARGS]; + + /* Args Check. TODO: Handle different case. see doc/PROTOCOL . */ if (!parser_get_cmd_arguments(buf, templ, args)) { - NAK(ser, "invalid arguments"); + ser_print(ser, "-2 Invalid arguments."); return; } - // EXEC! + /* Execute. */ + if(!parser_execute_cmd(templ, args)) + { + NAK(ser, "Error in executing command."); + } + if (!protocol_reply(ser, templ, args)) + { + NAK(ser, "Invalid return format."); + } + return; } void protocol_run(Serial *ser) { - // \todo to be removed, we could probably access the serial FIFO directly + /** + * \todo to be removed, we could probably access the serial FIFO + * directly + */ static char linebuf[80]; if (!interactive) @@ -103,10 +171,13 @@ void protocol_run(Serial *ser) if (linebuf[0] == 0x1B && linebuf[1] == 0x1B) // ESC { interactive = true; - ser_printf(ser, "Entering interactive mode\r\n"); + ser_printf(ser, + "Entering interactive mode\r\n"); } else + { protocol_parse(ser, linebuf); + } } } else @@ -129,7 +200,8 @@ void protocol_run(Serial *ser) if (!strcmp(buf, "exit") || !strcmp(buf, "quit")) { rl_clear_history(&rl_ctx); - ser_printf(ser, "Leaving interactive mode...\r\n"); + ser_printf(ser, + "Leaving interactive mode...\r\n"); interactive = FORCE_INTERACTIVE; } else @@ -146,41 +218,47 @@ void protocol_run(Serial *ser) } } -static ResultCode cmd_ver(const char **str) +/* + * Commands. + * TODO: Command declarations and definitions should be in another file(s). + * Maybe we should use CMD_HUNK_TEMPLATE. + * + */ + +/* Version. Example of declaring function and passing it to MAKE_CMD. */ +static int ver_fn(const char **str) { *str = VERS_TAG; -kprintf("hello, version world!\nver=" VERS_TAG "\n"); - return RC_REPLY; -} -static ResultCode cmd_add_hunk(parms args_results[]) -{ - return cmd_ver(&args_results[0].s); + return 0; } -const struct CmdTemplate cmd_ver_template = -{ - "ver", "", "d", cmd_add_hunk -}; +MAKE_CMD(ver, "", "s", ver_fn(&args[1].s)) + +/* Sleep. Example of declaring function body directly in macro call. */ +MAKE_CMD(sleep, "d", "", +({ + timer_delay((mtime_t)args[1].l); + 0; +})) +/* Ping. */ +MAKE_CMD(ping, "", "", +({ + 0; +})) + +/* Register commands. */ static void protocol_registerCmds(void) { -// parser_register_cmd(&CMD_HUNK_TEMPLATE(quit)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(exit)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(wait)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(delay)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(SYN)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(RST)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(skip_end)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(restart)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(ver)); -// parser_register_cmd(&CMD_HUNK_TEMPLATE(power_off)); - - parser_register_cmd(&cmd_ver_template); + REGISTER_CMD(ver); + REGISTER_CMD(sleep); + REGISTER_CMD(ping); } + +/* Initialization: readline context, parser and register commands. */ void protocol_init(Serial *ser) { interactive = FORCE_INTERACTIVE; - // Initialize the readline context used for interactive mode rl_init_ctx(&rl_ctx); rl_setprompt(&rl_ctx, ">> "); rl_sethook_get(&rl_ctx, (getc_hook)ser_getchar, ser);