/*#*
*#* $Log$
+ *#* Revision 1.2 2006/06/01 12:29:21 marco
+ *#* Add first simple protocol command (version request).
+ *#*
*#* Revision 1.1 2006/05/18 00:41:47 bernie
*#* New triface devlib application.
*#*
/** Baud-rate for the kdebug console */
#define CONFIG_KDEBUG_BAUDRATE 38400
+/** Serial port number for kdebug console */
+#define CONFIG_KDEBUG_PORT 0
+
+
/**
* printf()-style formatter configuration.
*
#define CONFIG_SER_DEFBAUDRATE 0
/** Enable ser_gets() and ser_gets_echo() */
- #define CONFIG_SER_GETS 0
+ #define CONFIG_SER_GETS 1
/** Enable second serial port in emulator. */
#define CONFIG_EMUL_UART1 0
/// Enable watchdog timer.
#define CONFIG_WATCHDOG 0
+/// Enable internal parser commands.
+#define CONFIG_INTERNAL_COMMANDS 0
+
#endif /* APPCONFIG_TRIFACE_H */
--- /dev/null
+/**
+ * \file
+ * <!--
+ * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
+ * -->
+ *
+ * \brief Implementation of the command protocol between the board and the host
+ *
+ *
+ * \version $Id$
+ *
+ * \author Giovanni Bajo <rasky@develer.com>
+ * \author Marco Benelli <marco@develer.com>
+ * \author Bernardo Innocenti <bernie@develer.com>
+ */
+
+/*#*
+ *#* $Log$
+ *#* Revision 1.1 2006/06/01 12:29:21 marco
+ *#* Add first simple protocol command (version request).
+ *#*
+ *#*/
+
+#include "protocol.h"
+
+#include <drv/ser.h>
+#include <mware/readline.h>
+#include <mware/parser.h>
+#include <cfg/compiler.h>
+#include <cfg/debug.h>
+#include <verstag.h>
+
+#include <string.h>
+
+
+// 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 protocol mode, we implement the default protocol
+ */
+static bool interactive;
+
+/// Readline context, used for interactive mode.
+static struct RLContext rl_ctx;
+
+
+/**
+ * Send a NAK asking the host to send the current message again.
+ *
+ * \param err human-readable description of the error for debug purposes.
+ */
+INLINE void NAK(Serial *ser, const char *err)
+{
+#ifdef _DEBUG
+ ser_printf(ser, "NAK \"%s\"\r\n", err);
+#else
+ ser_printf(ser, "NAK\r\n");
+#endif
+}
+
+static void protocol_parse(Serial *ser, const char *buf)
+{
+ const struct CmdTemplate *templ;
+ parms args[8]; // FIXME FIXME!!
+
+ templ = parser_get_cmd_template(buf);
+
+ if (!templ)
+ {
+ NAK(ser, "invalid command");
+ return;
+ }
+
+ // Extract the arguments for the command
+ if (!parser_get_cmd_arguments(buf, templ, args))
+ {
+ NAK(ser, "invalid arguments");
+ return;
+ }
+
+ // EXEC!
+}
+
+void protocol_run(Serial *ser)
+{
+ // \todo to be removed, we could probably access the serial FIFO directly
+ static char linebuf[80];
+
+ if (!interactive)
+ {
+ ser_gets(ser, linebuf, sizeof(linebuf));
+
+ // reset serial port error anyway
+ ser_setstatus(ser, 0);
+
+ // check message minimum length
+ if (linebuf[0])
+ {
+ if (linebuf[0] == 0x1B && linebuf[1] == 0x1B) // ESC
+ {
+ interactive = true;
+ ser_printf(ser, "Entering interactive mode\r\n");
+ }
+ else
+ protocol_parse(ser, linebuf);
+ }
+ }
+ else
+ {
+ const char *buf;
+
+ /*
+ * Read a line from serial. We use a temporary buffer
+ * because otherwise we would have to extract a message
+ * from the port immediately: there might not be any
+ * available, and one might get free while we read
+ * the line. We also add a fake ID at the start to
+ * fool the parser.
+ */
+ buf = rl_readline(&rl_ctx);
+
+ if (buf && buf[0] != '\0')
+ {
+ // exit special case to immediately change serial input
+ if (!strcmp(buf, "exit") || !strcmp(buf, "quit"))
+ {
+ rl_clear_history(&rl_ctx);
+ ser_printf(ser, "Leaving interactive mode...\r\n");
+ interactive = FORCE_INTERACTIVE;
+ }
+ else
+ {
+ //TODO: remove sequence numbers
+ linebuf[0] = '0';
+ linebuf[1] = ' ';
+
+ strncpy(linebuf + 2, buf, sizeof(linebuf) - 3);
+ linebuf[sizeof(linebuf) - 1] = '\0';
+ protocol_parse(ser, linebuf);
+ }
+ }
+ }
+}
+
+static ResultCode cmd_ver(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);
+}
+const struct CmdTemplate cmd_ver_template =
+{
+ "ver", "", "d", cmd_add_hunk
+};
+
+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);
+}
+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);
+ rl_sethook_put(&rl_ctx, (putc_hook)ser_putchar, ser);
+ rl_sethook_match(&rl_ctx, parser_rl_match, NULL);
+
+ parser_init();
+
+ protocol_registerCmds();
+}
--- /dev/null
+/**
+ * \file
+ * <!--
+ * Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2001, 2002, 2003 by Bernardo Innocenti <bernie@codewiz.org>
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief Declare application version strings
+ */
+#ifndef DEVLIB_VERSTAG_H
+#define DEVLIB_VERSTAG_H
+
+#ifndef ARCH_CONFIG_H
+ #include "cfg/arch_config.h"
+#endif
+
+#define APP_NAME "Triface"
+#define APP_DESCRIPTION "Trinity Interface Board"
+#define APP_AUTHOR "Develer"
+#define APP_COPYRIGHT "Copyright 2006 Develer (http://www.develer.com/)"
+
+#define VERS_MAJOR 0
+#define VERS_MINOR 1
+#define VERS_REV 0
+#define VERS_LETTER ""
+
+/*!
+ * If _SNAPSHOT is defined, \c VERS_TAG contains the build date
+ * date instead of a numeric version string.
+ */
+//#define _SNAPSHOT
+
+#ifdef _DEBUG
+ #define VERS_DBG "D"
+#else
+ #define VERS_DBG ""
+#endif
+
+#define __STRINGIZE(x) #x
+#define _STRINGIZE(x) __STRINGIZE(x)
+
+/*! Build application version string (i.e.: "1.7.0") */
+#define MAKE_VERS(maj,min,rev) _STRINGIZE(maj) "." _STRINGIZE(min) "." _STRINGIZE(rev) VERS_LETTER VERS_DBG
+#ifdef _SNAPSHOT
+ #define VERS_TAG "snapshot" " " __DATE__ " " __TIME__ " " VERS_LETTER " " VERS_DBG
+#else
+ #define VERS_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV)
+#endif
+
+/*! Build application version string suitable for MS windows resource files (i.e.: "1, 7, 0, 1") */
+#define MAKE_RCVERS(maj,min,rev,bld) _STRINGIZE(maj) ", " _STRINGIZE(min) ", " _STRINGIZE(rev) ", " _STRINGIZE(bld)
+#define RCVERSION_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV)
+
+/*! The revision string (contains VERS_TAG) */
+extern const char vers_tag[];
+
+/*! Sequential build number (contains VERS_BUILD) */
+extern const int vers_build_nr;
+//extern const char vers_build_str[];
+
+/*! Hostname of the machine used to build this binary (contains VERS_HOST) */
+extern const char vers_host[];
+
+#endif /* DEVLIB_VERSTAG_H */