summaryrefslogtreecommitdiff
path: root/ucoo/arch
diff options
context:
space:
mode:
authorNicolas Schodet2015-06-03 13:46:44 +0200
committerNicolas Schodet2019-10-07 00:44:44 +0200
commit574480980dcffbfa7cd6dbe71e88253eb4c9feba (patch)
tree5f1c1261341a7c2a56de01d8c6d0815b164be8ba /ucoo/arch
parentd415a0646e874848cd06482c5d57916cca5cff4a (diff)
Rename ucoolib modules directory from ucoolib to ucoo
Diffstat (limited to 'ucoo/arch')
-rw-r--r--ucoo/arch/Module1
-rw-r--r--ucoo/arch/arch.hh47
-rw-r--r--ucoo/arch/arch.host.cc83
-rw-r--r--ucoo/arch/arch.stm32.cc57
-rw-r--r--ucoo/arch/arch_common.arm.hh59
-rw-r--r--ucoo/arch/arch_common.hh43
-rw-r--r--ucoo/arch/arch_common.host.hh47
-rw-r--r--ucoo/arch/host/Module2
-rw-r--r--ucoo/arch/host/host.hh81
-rw-r--r--ucoo/arch/host/host.host.cc181
-rw-r--r--ucoo/arch/host/host_stream.hh54
-rw-r--r--ucoo/arch/host/host_stream.host.cc146
-rw-r--r--ucoo/arch/host/mex/Config2
-rw-r--r--ucoo/arch/host/mex/Module2
-rw-r--r--ucoo/arch/host/mex/mex.hh56
-rw-r--r--ucoo/arch/host/mex/mex_msg.hh148
-rw-r--r--ucoo/arch/host/mex/mex_msg.host.cc290
-rw-r--r--ucoo/arch/host/mex/mex_node.hh104
-rw-r--r--ucoo/arch/host/mex/mex_node.host.cc174
-rw-r--r--ucoo/arch/host/mex/mex_socket.hh59
-rw-r--r--ucoo/arch/host/mex/mex_socket.host.cc95
-rw-r--r--ucoo/arch/host/mex/socket.h39
-rw-r--r--ucoo/arch/host/mex/socket.host.c88
-rw-r--r--ucoo/arch/host/mex/test/Makefile9
-rw-r--r--ucoo/arch/host/mex/test/hub.py6
-rw-r--r--ucoo/arch/host/mex/test/test_mex.cc245
-rw-r--r--ucoo/arch/host/test/Makefile9
-rw-r--r--ucoo/arch/host/test/test_host.cc49
-rw-r--r--ucoo/arch/stm32f4/stm32f4.ld6
-rw-r--r--ucoo/arch/syscalls.cc36
-rw-r--r--ucoo/arch/syscalls.newlib.cc179
-rw-r--r--ucoo/arch/syscalls.newlib.hh35
32 files changed, 2432 insertions, 0 deletions
diff --git a/ucoo/arch/Module b/ucoo/arch/Module
new file mode 100644
index 0000000..6c23a20
--- /dev/null
+++ b/ucoo/arch/Module
@@ -0,0 +1 @@
+arch_SOURCES := arch.host.cc arch.stm32.cc syscalls.newlib.cc syscalls.cc
diff --git a/ucoo/arch/arch.hh b/ucoo/arch/arch.hh
new file mode 100644
index 0000000..e0889bd
--- /dev/null
+++ b/ucoo/arch/arch.hh
@@ -0,0 +1,47 @@
+#ifndef ucoo_arch_arch_hh
+#define ucoo_arch_arch_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+namespace ucoo {
+
+/// Initialise arch, take program arguments.
+void
+arch_init (int argc, const char **argv);
+
+/// Reset.
+void
+arch_reset ();
+
+#ifdef TARGET_host
+
+/// Retrieve program arguments.
+void
+arch_get_args (int &argc, const char **&argv);
+
+#endif
+
+} // namespace ucoo
+
+#endif // ucoo_arch_arch_hh
diff --git a/ucoo/arch/arch.host.cc b/ucoo/arch/arch.host.cc
new file mode 100644
index 0000000..1ddd6a9
--- /dev/null
+++ b/ucoo/arch/arch.host.cc
@@ -0,0 +1,83 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/arch.hh"
+#include "ucoo/common.hh"
+
+#include <cstdlib>
+#include <cstdio>
+#include <time.h>
+#include <errno.h>
+
+namespace ucoo {
+
+static int arch_stored_argc;
+static const char **arch_stored_argv;
+
+void
+arch_init (int argc, const char **argv)
+{
+ arch_stored_argc = argc;
+ arch_stored_argv = argv;
+}
+
+void
+arch_reset ()
+{
+ // Not supported.
+ halt ();
+}
+
+void
+arch_get_args (int &argc, const char **&argv)
+{
+ argc = arch_stored_argc;
+ argv = arch_stored_argv;
+}
+
+void
+halt ()
+{
+ fprintf (stderr, "halt\n");
+ abort ();
+}
+
+void
+halt_perror ()
+{
+ perror ("halt");
+ abort ();
+}
+
+void
+yield ()
+{
+ // Do a small delay.
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 100 * 1000 * 1000;
+ while (nanosleep (&ts, &ts) == -1 && errno == EINTR)
+ ;
+}
+
+} // namespace ucoo
diff --git a/ucoo/arch/arch.stm32.cc b/ucoo/arch/arch.stm32.cc
new file mode 100644
index 0000000..649091d
--- /dev/null
+++ b/ucoo/arch/arch.stm32.cc
@@ -0,0 +1,57 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/arch.hh"
+#include "ucoo/common.hh"
+
+#include <libopencm3/stm32/f4/rcc.h>
+#include <libopencm3/cm3/scb.h>
+
+namespace ucoo {
+
+void
+arch_init (int argc, const char **argv)
+{
+ rcc_clock_setup_hse_3v3 (&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
+}
+
+void
+arch_reset ()
+{
+ SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
+}
+
+void
+halt ()
+{
+ while (1)
+ ;
+}
+
+void
+halt_perror ()
+{
+ halt ();
+}
+
+} // namespace ucoo
diff --git a/ucoo/arch/arch_common.arm.hh b/ucoo/arch/arch_common.arm.hh
new file mode 100644
index 0000000..7b4abfd
--- /dev/null
+++ b/ucoo/arch/arch_common.arm.hh
@@ -0,0 +1,59 @@
+#ifndef ucoo_arch_arch_common_arm_hh
+#define ucoo_arch_arch_common_arm_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+namespace ucoo {
+
+/// Type used to save irq state.
+typedef unsigned int irq_flags_t;
+
+static inline irq_flags_t
+irq_lock (void)
+{
+ irq_flags_t flags;
+ __asm__ __volatile__ ("mrs %0, PRIMASK\n\t"
+ "cpsid i"
+ : "=r" (flags) :
+ : "memory", "cc");
+ return flags;
+}
+
+inline void
+irq_restore (irq_flags_t flags)
+{
+ __asm__ __volatile__ ("msr PRIMASK, %0"
+ : : "r" (flags)
+ : "memory", "cc");
+}
+
+inline void
+yield ()
+{
+ // Nothing, the CPU is ours!
+}
+
+} // namespace ucoo
+
+#endif // ucoo_arch_arch_common_arm_hh
diff --git a/ucoo/arch/arch_common.hh b/ucoo/arch/arch_common.hh
new file mode 100644
index 0000000..ac70e62
--- /dev/null
+++ b/ucoo/arch/arch_common.hh
@@ -0,0 +1,43 @@
+#ifndef ucoo_arch_arch_common_hh
+#define ucoo_arch_arch_common_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+#if defined (TARGET_arm)
+# include "arch_common.arm.hh"
+#elif defined (TARGET_host)
+# include "arch_common.host.hh"
+#else
+# error "not implemented for this target"
+#endif
+
+namespace ucoo {
+
+/// Give some time to other tasks when running in a tight loop.
+void
+yield ();
+
+} // namespace ucoo
+
+#endif // ucoo_arch_arch_common_hh
diff --git a/ucoo/arch/arch_common.host.hh b/ucoo/arch/arch_common.host.hh
new file mode 100644
index 0000000..0ee2553
--- /dev/null
+++ b/ucoo/arch/arch_common.host.hh
@@ -0,0 +1,47 @@
+#ifndef ucoo_arch_arch_common_host_hh
+#define ucoo_arch_arch_common_host_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+namespace ucoo {
+
+/// Type used to save irq state.
+typedef unsigned int irq_flags_t;
+
+static inline irq_flags_t
+irq_lock (void)
+{
+ // Nothing on host, there is no interrupts.
+ return 0;
+}
+
+inline void
+irq_restore (irq_flags_t)
+{
+ // Nothing on host, there is no interrupts.
+}
+
+} // namespace ucoo
+
+#endif // ucoo_arch_arch_common_host_hh
diff --git a/ucoo/arch/host/Module b/ucoo/arch/host/Module
new file mode 100644
index 0000000..2c7fead
--- /dev/null
+++ b/ucoo/arch/host/Module
@@ -0,0 +1,2 @@
+arch_host_SOURCES := host.host.cc host_stream.host.cc
+host_LIBS += -lutil
diff --git a/ucoo/arch/host/host.hh b/ucoo/arch/host/host.hh
new file mode 100644
index 0000000..f1307fa
--- /dev/null
+++ b/ucoo/arch/host/host.hh
@@ -0,0 +1,81 @@
+#ifndef ucoo_arch_host_host_hh
+#define ucoo_arch_host_host_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/host/mex/mex_node.hh"
+
+#include <string>
+#include <list>
+#include <memory>
+
+namespace ucoo {
+
+/// Host support class.
+class Host
+{
+ public:
+ /// Constructor, with default instance name.
+ Host (const std::string &default_instance_name);
+ /// Get instance name, strip a number of tail components if requested.
+ std::string get_instance (int strip = 0) const;
+ /// Get Mex node. Connect if not done yet.
+ mex::Node &get_node ();
+ /// Declare a command line option without value.
+ void add_option (char opt, const char *help);
+ /// Declare a command line option with value.
+ void add_option (char opt, const char *metavar, const char *help,
+ const std::string &default_value);
+ /// Test if option was set.
+ bool is_option_set (char opt) const;
+ /// Get value for option.
+ const std::string &get_option (char opt) const;
+ /// To be done once, parse options.
+ void parse_options ();
+ private:
+ /// Display usage message and exit.
+ void usage (int ret);
+ private:
+ /// Instance name, from default or from command line.
+ std::string instance_name_;
+ /// Mex node, or 0 if not connected yet.
+ std::auto_ptr<mex::Node> node_;
+ /// Store options definitions and values.
+ struct Option
+ {
+ const char *metavar;
+ const char *help;
+ bool set;
+ std::string value;
+ };
+ typedef std::map<char, Option> Options;
+ Options options_;
+ /// Program name, used for messages.
+ const char *program_name_;
+ /// Option parsing is done.
+ bool option_parsed_;
+};
+
+} // namespace ucoo
+
+#endif // ucoo_arch_host_host_hh
diff --git a/ucoo/arch/host/host.host.cc b/ucoo/arch/host/host.host.cc
new file mode 100644
index 0000000..9ccc0d1
--- /dev/null
+++ b/ucoo/arch/host/host.host.cc
@@ -0,0 +1,181 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "host.hh"
+
+#include "ucoo/arch/arch.hh"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <unistd.h>
+
+namespace ucoo {
+
+Host::Host (const std::string &default_instance_name)
+ : program_name_ ("program"), option_parsed_ (false)
+{
+ add_option ('i', "NAME", "instance name", default_instance_name);
+ add_option ('h', "display this help message");
+}
+
+std::string
+Host::get_instance (int strip) const
+{
+ assert (strip >= 0);
+ std::string instance = get_option ('i');
+ if (strip)
+ {
+ std::string::size_type end = std::string::npos;
+ do
+ {
+ end = instance.rfind (':', end - 1);
+ if (end == std::string::npos)
+ end = 0;
+ } while (end != 0 && --strip);
+ instance.erase (end);
+ }
+ return instance;
+}
+
+mex::Node &
+Host::get_node ()
+{
+ if (!node_.get ())
+ node_.reset (new mex::Node);
+ return *node_;
+}
+
+void
+Host::add_option (char opt, const char *help)
+{
+ Option o;
+ o.metavar = 0;
+ o.help = help;
+ o.set = false;
+ if (!options_.insert (Options::value_type (opt, o)).second)
+ assert_unreachable ();
+}
+
+void
+Host::add_option (char opt, const char *metavar, const char *help,
+ const std::string &default_value)
+{
+ Option o;
+ o.metavar = metavar;
+ o.help = help;
+ o.set = false;
+ o.value = default_value;
+ if (!options_.insert (Options::value_type (opt, o)).second)
+ assert_unreachable ();
+}
+
+bool
+Host::is_option_set (char opt) const
+{
+ assert (option_parsed_);
+ Options::const_iterator i = options_.find (opt);
+ assert (i != options_.end ());
+ return i->second.set;
+}
+
+const std::string &
+Host::get_option (char opt) const
+{
+ assert (option_parsed_);
+ Options::const_iterator i = options_.find (opt);
+ assert (i != options_.end ());
+ return i->second.value;
+}
+
+void
+Host::parse_options ()
+{
+ // Get program arguments.
+ int argc;
+ const char **argv;
+ arch_get_args (argc, argv);
+ // Save program name.
+ const char *slash = std::strrchr (argv[0], '/');
+ program_name_ = slash ? slash + 1 : argv[0];
+ // Parse.
+ std::string getoptdesc;
+ for (Options::const_iterator i = options_.begin ();
+ i != options_.end (); ++i)
+ {
+ getoptdesc.push_back (i->first);
+ if (i->second.metavar)
+ getoptdesc.push_back (':');
+ }
+ int c;
+ const char *getoptdescs = getoptdesc.c_str ();
+ char **getopt_argv = const_cast<char **> (argv);
+ while ((c = getopt (argc, getopt_argv, getoptdescs)) != -1)
+ {
+ if (c == '?')
+ usage (1);
+ else
+ {
+ Options::iterator i = options_.find (c);
+ assert (i != options_.end ());
+ i->second.set = true;
+ if (i->second.metavar)
+ i->second.value = optarg;
+ }
+ }
+ if (optind != argc)
+ {
+ fprintf (stderr, "%s: too many arguments\n", argv[0]);
+ usage (1);
+ }
+ option_parsed_ = true;
+ if (is_option_set ('h'))
+ usage (0);
+}
+
+void
+Host::usage (int ret)
+{
+ FILE *out = ret == 0 ? stdout : stderr;
+ fprintf (out, "Usage: %s [options...]\n\nOptions:\n", program_name_);
+ size_t max_meta = 0;
+ for (Options::const_iterator i = options_.begin ();
+ i != options_.end (); ++i)
+ {
+ if (i->second.metavar)
+ max_meta = std::max (max_meta,
+ std::strlen (i->second.metavar) + 1);
+ }
+ for (Options::const_iterator i = options_.begin ();
+ i != options_.end (); ++i)
+ {
+ const Option &o = i->second;
+ fprintf (out, " -%c %-*s %s\n", i->first,
+ static_cast<int> (max_meta),
+ o.metavar ? o.metavar : "", o.help);
+ }
+ exit (ret);
+}
+
+} // namespace ucoo
diff --git a/ucoo/arch/host/host_stream.hh b/ucoo/arch/host/host_stream.hh
new file mode 100644
index 0000000..4aebdbf
--- /dev/null
+++ b/ucoo/arch/host/host_stream.hh
@@ -0,0 +1,54 @@
+#ifndef ucoo_arch_host_stream_hh
+#define ucoo_arch_host_stream_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/intf/stream.hh"
+
+namespace ucoo {
+
+class HostStream : public Stream
+{
+ public:
+ /// Default constructor, use stdin/stdout.
+ HostStream ();
+ /// PTY constructor, will make a link to PTY at the given name.
+ HostStream (const char *name);
+ /// Close if needed.
+ ~HostStream ();
+ /// See Stream::block.
+ void block (bool block = true);
+ /// See Stream::read.
+ int read (char *buf, int count);
+ /// See Stream::write.
+ int write (const char *buf, int count);
+ /// See Stream::poll.
+ int poll ();
+ private:
+ /// Input and output file descriptors.
+ int fdi_, fdo_;
+};
+
+} // namespace ucoo
+
+#endif // ucoo_arch_host_stream_hh
diff --git a/ucoo/arch/host/host_stream.host.cc b/ucoo/arch/host/host_stream.host.cc
new file mode 100644
index 0000000..d971862
--- /dev/null
+++ b/ucoo/arch/host/host_stream.host.cc
@@ -0,0 +1,146 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "host_stream.hh"
+
+#include "ucoo/common.hh"
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pty.h>
+#include <fcntl.h>
+#include <errno.h>
+
+namespace ucoo {
+
+/// Setup non canonical mode.
+static void
+setup_raw (int fd)
+{
+ struct termios tc;
+ tcgetattr (fd, &tc);
+ tc.c_iflag &= ~(IGNPAR | PARMRK | ISTRIP | IGNBRK | BRKINT | IGNCR |
+ ICRNL | INLCR | IXON | IXOFF | IXANY | IMAXBEL);
+ tc.c_iflag |= INPCK;
+ tc.c_oflag &= ~(OPOST);
+ tc.c_cflag &= ~(HUPCL | CSTOPB | PARENB | PARODD | CSIZE);
+ tc.c_cflag |= CS8 | CLOCAL | CREAD;
+ tc.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN | NOFLSH | TOSTOP);
+ tc.c_cc[VTIME] = 0;
+ tc.c_cc[VMIN] = 1;
+ tcflush (fd, TCIFLUSH);
+ tcsetattr (fd, TCSANOW, &tc);
+}
+
+HostStream::HostStream ()
+ : fdi_ (0), fdo_ (1)
+{
+}
+
+HostStream::HostStream (const char *name)
+ : fdi_ (-1), fdo_ (-1)
+{
+ int fd, slave_fd, r;
+ // Open and unlock pt.
+ if (openpty (&fd, &slave_fd, 0, 0, 0) == -1
+ || grantpt (fd) == -1
+ || unlockpt (fd) == -1)
+ halt_perror ();
+ // Make a link to the slave pts.
+ unlink (name);
+ const char *slave_name = ptsname (fd);
+ assert (slave_name);
+ r = symlink (slave_name, name);
+ assert_perror (r != -1);
+ // Make slave raw.
+ setup_raw (slave_fd);
+ // Use as both in and out.
+ fdi_ = fdo_ = fd;
+ // slave_fd is left open.
+}
+
+HostStream::~HostStream ()
+{
+ if (fdi_ != -1 && fdi_ != 0)
+ close (fdi_);
+ if (fdo_ != -1 && fdo_ != 1 && fdo_ != fdi_)
+ close (fdo_);
+}
+
+void
+HostStream::block (bool block)
+{
+ Stream::block (block);
+ // Do not care to use non blocking on output for host. However, if
+ // fdi_ == fdo_, this will change input and output.
+ int r = fcntl (fdi_, F_SETFL, block ? 0 : O_NONBLOCK);
+ assert_perror (r != -1);
+}
+
+int
+HostStream::read (char *buf, int count)
+{
+ int r = ::read (fdi_, buf, count);
+ if (r == 0)
+ return -2;
+ if (r == -1 && errno == EAGAIN)
+ return 0;
+ assert_perror (r != -1);
+ return r;
+}
+
+int
+HostStream::write (const char *buf, int count)
+{
+ int writen = 0;
+ while (writen < count)
+ {
+ int r = ::write (fdo_, buf + writen, count - writen);
+ if (r == -1 && errno == EAGAIN)
+ break;
+ assert_perror (r != -1);
+ writen += r;
+ }
+ return writen;
+}
+
+int
+HostStream::poll ()
+{
+ fd_set fds;
+ struct timeval tv;
+ int r;
+ // Use select to poll.
+ FD_ZERO (&fds);
+ FD_SET (fdi_, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ r = select (FD_SETSIZE, &fds, 0, 0, &tv);
+ // Check result.
+ assert_perror (r != -1);
+ return r;
+}
+
+} // namespace ucoo
diff --git a/ucoo/arch/host/mex/Config b/ucoo/arch/host/mex/Config
new file mode 100644
index 0000000..de679f0
--- /dev/null
+++ b/ucoo/arch/host/mex/Config
@@ -0,0 +1,2 @@
+[arch/host/mex]
+default_address = "localhost", "2442"
diff --git a/ucoo/arch/host/mex/Module b/ucoo/arch/host/mex/Module
new file mode 100644
index 0000000..941482b
--- /dev/null
+++ b/ucoo/arch/host/mex/Module
@@ -0,0 +1,2 @@
+arch_host_mex_SOURCES := mex_msg.host.cc mex_node.host.cc mex_socket.host.cc \
+ socket.host.c
diff --git a/ucoo/arch/host/mex/mex.hh b/ucoo/arch/host/mex/mex.hh
new file mode 100644
index 0000000..9e6ca09
--- /dev/null
+++ b/ucoo/arch/host/mex/mex.hh
@@ -0,0 +1,56 @@
+#ifndef ucoo_arch_host_mex_mex_hh
+#define ucoo_arch_host_mex_mex_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+namespace ucoo {
+namespace mex {
+
+/// Message type identifiers.
+enum mtype_t
+{
+ /// IDLE message, sent by nodes to the hub to signal it had handled all
+ /// messages. It can have an optional parameter: the date at which the
+ /// node will not be idle anymore.
+ MTYPE_IDLE = 0,
+ /// DATE message, sent by the hub to the nodes to update the current date
+ /// value, sent by a node to request the current date (useful at startup).
+ MTYPE_DATE = 1,
+ /// REQ (request) message, sent from a node to other nodes to request a
+ /// response message.
+ MTYPE_REQ = 2,
+ /// RSP (response) message, response to a REQ message, only sent to the
+ /// requesting node.
+ MTYPE_RSP = 3,
+ /// RES (reserve) message, sent to the hub to request a message type, sent
+ /// to a node with the allocated message type.
+ MTYPE_RES = 4,
+ /// First unreserved message identifier, to be used by user messages.
+ MTYPE_USER_MIN = 0x20,
+};
+
+} // namespace mex
+} // namespace ucoo
+
+#endif // ucoo_arch_host_mex_mex_hh
diff --git a/ucoo/arch/host/mex/mex_msg.hh b/ucoo/arch/host/mex/mex_msg.hh
new file mode 100644
index 0000000..6aca09d
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_msg.hh
@@ -0,0 +1,148 @@
+#ifndef ucoo_arch_host_mex_mex_msg_hh
+#define ucoo_arch_host_mex_mex_msg_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/common.hh"
+
+#include "ucoo/arch/host/mex/mex.hh"
+
+#include <vector>
+
+namespace ucoo {
+namespace mex {
+
+class MsgPusher;
+class MsgPoper;
+class MsgReader;
+class MsgWriter;
+
+/// Mex message.
+///
+/// Format used for payload push and pop:
+/// - b: 8 bits.
+/// - h: 16 bits.
+/// - l: 32 bits.
+/// Uppercase is used for unsigned.
+class Msg
+{
+ public:
+ /// New message with the given MTYPE.
+ explicit Msg (mtype_t mtype);
+ /// Read a new message.
+ explicit Msg (MsgReader &reader);
+ /// Write a message.
+ void write (MsgWriter &writer);
+ /// Add data to the message payload. FMT string describes the provided
+ /// data. Return a pusher which will do the actual push, using the
+ /// operator<<.
+ MsgPusher push (const char *fmt);
+ /// Add data to the message payload from a buffer.
+ void push (const char *buffer, int size);
+ /// Extract data from the message payload. FMT string describes the
+ /// requested data. Return a poper which will do the actual pop, using
+ /// the operator>>.
+ MsgPoper pop (const char *fmt);
+ /// Pop buffer of given size. Data is kept valid as long as this object
+ /// is alive.
+ const char *pop (int size);
+ /// Encapsulate a message in another one, adding header data. Return a
+ /// pusher which will do the actual header data push, using the
+ /// operator<<.
+ MsgPusher encapsulate (mtype_t mtype, const char *fmt);
+ /// Decapsulate a message from payload. The current payload becomes the
+ /// full message.
+ void decapsulate ();
+ /// Get remaining length.
+ int len () const;
+ /// Get message type.
+ mtype_t mtype () const { return mtype_; }
+ private:
+ /// Message payload, not including message type.
+ std::vector<char> payload_;
+ /// Unused space at head of payload.
+ int head_skip_;
+ /// Message type.
+ mtype_t mtype_;
+};
+
+/// Helper used to push data to message.
+class MsgPusher
+{
+ public:
+ /// Push an integer.
+ MsgPusher &operator<< (int32_t v);
+ /// Push an unsigned integer, used when an int is not enough.
+ MsgPusher &operator<< (uint32_t v);
+ private:
+ MsgPusher (std::vector<char>::iterator out, const char *fmt);
+ void push (int64_t v);
+ private:
+ friend class Msg;
+ std::vector<char>::iterator out_;
+ const char *fmt_;
+};
+
+/// Helper used to pop data from message.
+class MsgPoper
+{
+ public:
+ /// Pop for each supported types.
+ MsgPoper &operator>> (int32_t &v);
+ MsgPoper &operator>> (uint32_t &v);
+ MsgPoper &operator>> (int16_t &v);
+ MsgPoper &operator>> (uint16_t &v);
+ MsgPoper &operator>> (int8_t &v);
+ MsgPoper &operator>> (uint8_t &v);
+ private:
+ MsgPoper (std::vector<char>::const_iterator in, const char *fmt);
+ uint32_t pop_bytes (int bytes);
+ int64_t pop (int bits, bool sign);
+ private:
+ friend class Msg;
+ std::vector<char>::const_iterator in_;
+ const char *fmt_;
+};
+
+/// Abstract Msg reader.
+class MsgReader
+{
+ public:
+ /// Get message size.
+ virtual int size () = 0;
+ /// Read message bytes to provided buffer.
+ virtual void read (char *buf) = 0;
+};
+
+/// Abstract Msg writer.
+class MsgWriter
+{
+ public:
+ /// Write COUNT bytes from provided buffer.
+ virtual void write (const char *buf, int count) = 0;
+};
+
+} // namespace mex
+} // namespace ucoo
+
+#endif // ucoo_arch_host_mex_mex_msg_hh
diff --git a/ucoo/arch/host/mex/mex_msg.host.cc b/ucoo/arch/host/mex/mex_msg.host.cc
new file mode 100644
index 0000000..5876e22
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_msg.host.cc
@@ -0,0 +1,290 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#define __STDC_LIMIT_MACROS 1
+#include "mex_msg.hh"
+
+namespace ucoo {
+namespace mex {
+
+const int default_head_skip = 3;
+
+/// Compute needed size to store given format.
+static int
+calcsize (const char *fmt)
+{
+ int size = 0;
+ for (; *fmt; fmt++)
+ {
+ switch (*fmt)
+ {
+ case 'l':
+ case 'L':
+ size += 4;
+ break;
+ case 'h':
+ case 'H':
+ size += 2;
+ break;
+ case 'b':
+ case 'B':
+ size += 1;
+ break;
+ }
+ }
+ return size;
+}
+
+Msg::Msg (mtype_t mtype)
+ : head_skip_ (default_head_skip),
+ mtype_ (mtype)
+{
+ payload_.resize (head_skip_);
+}
+
+Msg::Msg (MsgReader &reader)
+ : head_skip_ (default_head_skip),
+ mtype_ (MTYPE_IDLE)
+{
+ int size = reader.size ();
+ payload_.resize (head_skip_ - 1 + size);
+ reader.read (&payload_.front () + head_skip_ - 1);
+ mtype_ = static_cast<mtype_t> (payload_[head_skip_ - 1]);
+}
+
+void
+Msg::write (MsgWriter &writer)
+{
+ assert (head_skip_ >= 1);
+ payload_[head_skip_ - 1] = static_cast<int> (mtype_);
+ writer.write (&payload_.front () + head_skip_ - 1,
+ payload_.size () - head_skip_ + 1);
+}
+
+MsgPusher
+Msg::push (const char *fmt)
+{
+ int push_index = payload_.size ();
+ payload_.resize (push_index + calcsize (fmt));
+ return MsgPusher (payload_.begin () + push_index, fmt);
+}
+
+void
+Msg::push (const char *buffer, int size)
+{
+ payload_.insert (payload_.end (), buffer, buffer + size);
+}
+
+MsgPoper
+Msg::pop (const char *fmt)
+{
+ int pop_size = calcsize (fmt);
+ assert (pop_size <= (int) payload_.size () - head_skip_);
+ int pop_index = head_skip_;
+ head_skip_ += pop_size;
+ return MsgPoper (payload_.begin () + pop_index, fmt);
+}
+
+const char *
+Msg::pop (int size)
+{
+ assert (size <= (int) payload_.size () - head_skip_);
+ const char *r = &payload_.front () + head_skip_;
+ head_skip_ += size;
+ return r;
+}
+
+MsgPusher
+Msg::encapsulate (mtype_t mtype, const char *fmt)
+{
+ int head_size = calcsize (fmt) + 1;
+ assert (head_size <= head_skip_);
+ payload_[head_skip_ - 1] = static_cast<int> (mtype_);
+ mtype_ = mtype;
+ head_skip_ -= head_size;
+ return MsgPusher (payload_.begin () + head_skip_, fmt);
+}
+
+void
+Msg::decapsulate ()
+{
+ assert (1 <= payload_.size () - head_skip_);
+ mtype_ = static_cast<mtype_t> (payload_[head_skip_]);
+ head_skip_++;
+}
+
+int
+Msg::len () const
+{
+ return payload_.size () - head_skip_;
+}
+
+MsgPusher &
+MsgPusher::operator<< (int32_t v)
+{
+ push (v);
+ return *this;
+}
+
+MsgPusher &
+MsgPusher::operator<< (uint32_t v)
+{
+ push (v);
+ return *this;
+}
+
+MsgPusher::MsgPusher (std::vector<char>::iterator out, const char *fmt)
+ : out_ (out),
+ fmt_ (fmt)
+{
+}
+
+void
+MsgPusher::push (int64_t v)
+{
+ switch (*fmt_)
+ {
+ case 'l':
+ assert (v >= INT32_MIN && v <= INT32_MAX);
+ break;
+ case 'L':
+ assert (v >= 0 && v <= UINT32_MAX);
+ break;
+ case 'h':
+ assert (v >= INT16_MIN && v <= INT16_MAX);
+ break;
+ case 'H':
+ assert (v >= 0 && v <= UINT16_MAX);
+ break;
+ case 'b':
+ assert (v >= INT8_MIN && v <= INT8_MAX);
+ break;
+ case 'B':
+ assert (v >= 0 && v <= UINT8_MAX);
+ break;
+ default:
+ assert (0);
+ }
+ switch (*fmt_)
+ {
+ case 'l':
+ case 'L':
+ *out_++ = v >> 24;
+ *out_++ = v >> 16;
+ case 'h':
+ case 'H':
+ *out_++ = v >> 8;
+ case 'b':
+ case 'B':
+ *out_++ = v >> 0;
+ }
+ fmt_++;
+}
+
+MsgPoper &
+MsgPoper::operator>> (int32_t &v)
+{
+ v = pop (31, true);
+ return *this;
+}
+
+MsgPoper &
+MsgPoper::operator>> (uint32_t &v)
+{
+ v = pop (32, false);
+ return *this;
+}
+
+MsgPoper &
+MsgPoper::operator>> (int16_t &v)
+{
+ v = pop (15, true);
+ return *this;
+}
+
+MsgPoper &
+MsgPoper::operator>> (uint16_t &v)
+{
+ v = pop (16, false);
+ return *this;
+}
+
+MsgPoper &
+MsgPoper::operator>> (int8_t &v)
+{
+ v = pop (7, true);
+ return *this;
+}
+
+MsgPoper &
+MsgPoper::operator>> (uint8_t &v)
+{
+ v = pop (8, false);
+ return *this;
+}
+
+MsgPoper::MsgPoper (std::vector<char>::const_iterator in, const char *fmt)
+ : in_ (in),
+ fmt_ (fmt)
+{
+}
+
+uint32_t
+MsgPoper::pop_bytes (int bytes)
+{
+ uint32_t r = 0;
+ while (bytes--)
+ r = r << 8 | static_cast<unsigned char> (*in_++);
+ return r;
+}
+
+int64_t
+MsgPoper::pop (int bits, bool sign)
+{
+ switch (*fmt_++)
+ {
+ case 'l':
+ assert (bits >= 31 && sign);
+ return static_cast<int32_t> (pop_bytes (4));
+ case 'L':
+ assert (bits >= 32);
+ return static_cast<uint32_t> (pop_bytes (4));
+ case 'h':
+ assert (bits >= 15 && sign);
+ return static_cast<int16_t> (pop_bytes (2));
+ case 'H':
+ assert (bits >= 16);
+ return static_cast<uint16_t> (pop_bytes (2));
+ case 'b':
+ assert (bits >= 7 && sign);
+ return static_cast<int8_t> (pop_bytes (1));
+ case 'B':
+ assert (bits >= 8);
+ return static_cast<uint8_t> (pop_bytes (1));
+ default:
+ assert_unreachable ();
+ }
+}
+
+} // namespace mex
+} // namespace ucoo
diff --git a/ucoo/arch/host/mex/mex_node.hh b/ucoo/arch/host/mex/mex_node.hh
new file mode 100644
index 0000000..103deea
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_node.hh
@@ -0,0 +1,104 @@
+#ifndef ucoo_arch_host_mex_mex_node_hh
+#define ucoo_arch_host_mex_mex_node_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/common.hh"
+#include "mex_msg.hh"
+#include "mex_socket.hh"
+
+#include <memory>
+#include <map>
+#include <string>
+#include <tr1/functional>
+
+namespace ucoo {
+namespace mex {
+
+/// Mex node, singleton.
+class Node
+{
+ public:
+ /// Message handler type.
+ typedef std::tr1::function<void (Node &, Msg &)> Handler;
+ public:
+ /// Connect to mex hub.
+ Node ();
+ /// Wait forever.
+ void wait ();
+ /// Wait until date is reached.
+ void wait (uint32_t date);
+ /// Return current date.
+ uint32_t date () const { return date_; }
+ /// Send a message.
+ void send (Msg &msg);
+ /// Send a request and return response.
+ std::auto_ptr<Msg> request (Msg &msg);
+ /// Send a response while handling a request.
+ void response (Msg &msg);
+ /// Reserve a message type.
+ mtype_t reserve (const std::string &name);
+ /// Register a handler for a message type.
+ void handler_register (mtype_t mtype, Handler handler);
+ /// Register a handler for a message type, member function version.
+ template<class T>
+ void handler_register (mtype_t mtype, T &obj,
+ void (T::*handler) (Node &, Msg &))
+ {
+ using namespace std::tr1::placeholders;
+ handler_register (mtype, std::tr1::bind (handler, &obj, _1, _2));
+ }
+ /// Register a handler for a message type, member function version,
+ /// without Node parameter.
+ template<class T>
+ void handler_register (mtype_t mtype, T &obj,
+ void (T::*handler) (Msg &))
+ {
+ using namespace std::tr1::placeholders;
+ handler_register (mtype, std::tr1::bind (handler, &obj, _2));
+ }
+ private:
+ /// Receive one message.
+ std::auto_ptr<Msg> recv ();
+ /// Dispatch message to the right handler.
+ void dispatch (Msg &msg);
+ /// Handle an incomming DATE message.
+ void handle_date (Msg &msg);
+ /// Handle an incomming REQ message.
+ void handle_req (Msg &msg);
+ private:
+ /// Connection to hub.
+ Socket socket_;
+ /// Current date.
+ uint32_t date_;
+ /// When handling a request, this is the request identifier, else -1.
+ int req_;
+ /// Registered handlers.
+ typedef std::map<mtype_t, Handler> Handlers;
+ Handlers handlers_;
+};
+
+} // namespace mex
+} // namespace ucoo
+
+#endif // ucoo_arch_host_mex_mex_node_hh
diff --git a/ucoo/arch/host/mex/mex_node.host.cc b/ucoo/arch/host/mex/mex_node.host.cc
new file mode 100644
index 0000000..f6f7c98
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_node.host.cc
@@ -0,0 +1,174 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "mex_node.hh"
+
+#include <cstring>
+
+namespace ucoo {
+namespace mex {
+
+Node::Node ()
+ : date_ (0),
+ req_ (-1)
+{
+ // Connect.
+ socket_.connect ();
+ // Setup default handlers.
+ handler_register (MTYPE_DATE, *this, &Node::handle_date);
+ handler_register (MTYPE_REQ, *this, &Node::handle_req);
+ // Synchronise with the hub.
+ bool sync = false;
+ while (!sync)
+ {
+ std::auto_ptr<Msg> msg = recv ();
+ if (msg->mtype () == MTYPE_DATE)
+ sync = true;
+ dispatch (*msg);
+ }
+}
+
+void
+Node::wait ()
+{
+ while (1)
+ {
+ // Signal IDLE state.
+ Msg idle (MTYPE_IDLE);
+ send (idle);
+ // Receive and dispatch messages.
+ std::auto_ptr<Msg> msg = recv ();
+ dispatch (*msg);
+ }
+}
+
+void
+Node::wait (uint32_t date)
+{
+ while (date_ != date)
+ {
+ // Signal IDLE state.
+ Msg idle (MTYPE_IDLE);
+ idle.push ("L") << date;
+ send (idle);
+ // Receive and dispatch messages.
+ std::auto_ptr<Msg> msg = recv ();
+ dispatch (*msg);
+ }
+}
+
+void
+Node::send (Msg &msg)
+{
+ msg.write (socket_);
+}
+
+std::auto_ptr<Msg>
+Node::request (Msg &msg)
+{
+ // Send request.
+ msg.encapsulate (MTYPE_REQ, "B") << 0;
+ send (msg);
+ // Wait for response.
+ std::auto_ptr<Msg> rsp;
+ rsp = recv ();
+ while (rsp->mtype () != MTYPE_RSP)
+ {
+ dispatch (*rsp);
+ rsp = recv ();
+ }
+ // Eat unused request identifier.
+ rsp->pop ("B");
+ rsp->decapsulate ();
+ return rsp;
+}
+
+void
+Node::response (Msg &msg)
+{
+ assert (req_ != -1);
+ msg.encapsulate (MTYPE_RSP, "B") << req_;
+ send (msg);
+ req_ = -1;
+}
+
+mtype_t
+Node::reserve (const std::string &name)
+{
+ // Send request.
+ Msg msg (MTYPE_RES);
+ msg.push (name.data (), name.size ());
+ send (msg);
+ // Wait for response.
+ std::auto_ptr<Msg> rsp;
+ rsp = recv ();
+ while (rsp->mtype () != MTYPE_RES)
+ {
+ dispatch (*rsp);
+ rsp = recv ();
+ }
+ // Return allocated message type.
+ int mtype;
+ rsp->pop ("B") >> mtype;
+ return static_cast<mtype_t> (mtype);
+}
+
+void
+Node::handler_register (mtype_t mtype, Handler handler)
+{
+ std::pair<Handlers::iterator, bool> r =
+ handlers_.insert (Handlers::value_type (mtype, handler));
+ assert (r.second);
+}
+
+std::auto_ptr<Msg>
+Node::recv ()
+{
+ return std::auto_ptr<Msg> (new Msg (socket_));
+}
+
+void
+Node::dispatch (Msg &msg)
+{
+ Handlers::const_iterator it = handlers_.find (msg.mtype ());
+ if (it != handlers_.end ())
+ it->second (*this, msg);
+}
+
+void
+Node::handle_date (Msg &msg)
+{
+ msg.pop ("L") >> date_;
+}
+
+void
+Node::handle_req (Msg &msg)
+{
+ msg.pop ("B") >> req_;
+ msg.decapsulate ();
+ dispatch (msg);
+ req_ = -1;
+}
+
+} // namespace mex
+} // namespace ucoo
diff --git a/ucoo/arch/host/mex/mex_socket.hh b/ucoo/arch/host/mex/mex_socket.hh
new file mode 100644
index 0000000..915e1b9
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_socket.hh
@@ -0,0 +1,59 @@
+#ifndef ucoo_arch_host_mex_mex_socket_hh
+#define ucoo_arch_host_mex_mex_socket_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "mex_msg.hh"
+
+namespace ucoo {
+namespace mex {
+
+/// Mex socket, able to read and write messages.
+class Socket : public MsgReader, public MsgWriter
+{
+ public:
+ /// Default constructor.
+ Socket () : fd_ (-1), read_size_ (-1) { }
+ /// Destructor, close the connection.
+ ~Socket ();
+ /// Connect to Mex hub.
+ void connect ();
+ /// See MsgReader::size.
+ int size ();
+ /// See MsgReader::read.
+ void read (char *buf);
+ /// See MsgWriter::write.
+ void write (const char *buf, int count);
+ private:
+ /// File descriptor to open socket, or -1 if not open.
+ int fd_;
+ /// Size of the next message to be read, or -1 if not known yet.
+ int read_size_;
+ /// This socket sequence number.
+ int seq_;
+};
+
+} // namespace mex
+} // namespace ucoo
+
+#endif // ucoo_arch_host_mex_mex_socket_hh
diff --git a/ucoo/arch/host/mex/mex_socket.host.cc b/ucoo/arch/host/mex/mex_socket.host.cc
new file mode 100644
index 0000000..41a6e01
--- /dev/null
+++ b/ucoo/arch/host/mex/mex_socket.host.cc
@@ -0,0 +1,95 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "mex_socket.hh"
+
+#include "ucoo/common.hh"
+
+#include "config/arch/host/mex.hh"
+#include "socket.h"
+
+#include <unistd.h>
+#include <cstdlib>
+
+namespace ucoo {
+namespace mex {
+
+Socket::~Socket ()
+{
+ if (fd_ != -1)
+ close (fd_);
+}
+
+void
+Socket::connect ()
+{
+ fd_ = socket_client UCOO_CONFIG_ARCH_HOST_MEX_DEFAULT_ADDRESS;
+}
+
+int
+Socket::size ()
+{
+ uint8_t header[3];
+ int r = ::read (fd_, header, sizeof (header));
+ assert_perror (r != -1);
+ if (r == 0)
+ exit (0);
+ else
+ {
+ assert (r == sizeof (header));
+ read_size_ = (header[0] << 8) | header[1];
+ seq_ = header[2];
+ return read_size_;
+ }
+}
+
+void
+Socket::read (char *buf)
+{
+ assert (fd_ != -1);
+ assert (read_size_ > 0);
+ int r = ::read (fd_, buf, read_size_);
+ assert_perror (r != -1);
+ assert (r == read_size_);
+ read_size_ = -1;
+}
+
+void
+Socket::write (const char *buf, int count)
+{
+ assert (fd_ != -1);
+ assert (read_size_ == -1);
+ uint8_t header[3];
+ header[0] = count >> 8;
+ header[1] = count;
+ header[2] = seq_;
+ int r = ::write (fd_, header, sizeof (header));
+ assert_perror (r != -1);
+ assert (r == sizeof (header));
+ r = ::write (fd_, buf, count);
+ assert_perror (r != -1);
+ assert (r == count);
+}
+
+} // namespace mex
+} // namespace ucoo
diff --git a/ucoo/arch/host/mex/socket.h b/ucoo/arch/host/mex/socket.h
new file mode 100644
index 0000000..f8fc348
--- /dev/null
+++ b/ucoo/arch/host/mex/socket.h
@@ -0,0 +1,39 @@
+#ifndef ucoo_arch_host_mex_socket_h
+#define ucoo_arch_host_mex_socket_h
+/* ucoolib - Microcontroller object oriented library. {{{
+ *
+ * Copyright (C) 2012 Nicolas Schodet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * }}} */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Create and connect a client socket. */
+int
+socket_client (const char *addr, const char *port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ucoo_arch_host_mex_socket_h */
diff --git a/ucoo/arch/host/mex/socket.host.c b/ucoo/arch/host/mex/socket.host.c
new file mode 100644
index 0000000..d202192
--- /dev/null
+++ b/ucoo/arch/host/mex/socket.host.c
@@ -0,0 +1,88 @@
+/* imported from mysock library and modified for ucoolib.
+ * mysock library - client functions. {{{
+ *
+ * Copyright (C) 2001 Nicolas Schodet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * }}} */
+#include "socket.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+int
+socket_client (const char *addr, const char *port)
+{
+ int s;
+ struct sockaddr_in saddr;
+ struct servent *port_info;
+ struct hostent *host_info;
+ unsigned short int iport;
+ unsigned int iaddr;
+ iport = htons (atoi (port));
+ if (!iport)
+ {
+ port_info = getservbyname (port, "tcp");
+ if (!port_info)
+ {
+ fprintf (stderr, "Service %s unknown\n", port);
+ exit (EXIT_FAILURE);
+ }
+ iport = port_info->s_port;
+ }
+ iaddr = inet_addr (addr);
+ if (iaddr == INADDR_NONE)
+ {
+ host_info = gethostbyname (addr);
+ if (!host_info)
+ {
+ fprintf (stderr, "Host %s unknown\n", addr);
+ exit (EXIT_FAILURE);
+ }
+ iaddr = * (int *) host_info->h_addr;
+ }
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = iaddr;
+ saddr.sin_port = iport;
+ s = socket (AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ perror ("socket");
+ exit (EXIT_FAILURE);
+ }
+ int on = 1;
+ if (setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof (on))
+ < 0)
+ {
+ perror ("setsockopt (NODELAY)");
+ exit (EXIT_FAILURE);
+ }
+ if (connect (s, (struct sockaddr *) &saddr, sizeof (saddr)) < 0)
+ {
+ perror ("connect");
+ exit (EXIT_FAILURE);
+ }
+ return s;
+}
diff --git a/ucoo/arch/host/mex/test/Makefile b/ucoo/arch/host/mex/test/Makefile
new file mode 100644
index 0000000..d54907c
--- /dev/null
+++ b/ucoo/arch/host/mex/test/Makefile
@@ -0,0 +1,9 @@
+BASE = ../../../../..
+
+TARGETS = host
+host_PROGS = test_mex
+test_mex_SOURCES = test_mex.cc
+
+MODULES =
+
+include $(BASE)/build/top.mk
diff --git a/ucoo/arch/host/mex/test/hub.py b/ucoo/arch/host/mex/test/hub.py
new file mode 100644
index 0000000..31dcec1
--- /dev/null
+++ b/ucoo/arch/host/mex/test/hub.py
@@ -0,0 +1,6 @@
+# Hub for test.
+from mex.hub import Hub
+def log (x):
+ print x
+h = Hub (min_clients = 2, log = log)
+h.wait ()
diff --git a/ucoo/arch/host/mex/test/test_mex.cc b/ucoo/arch/host/mex/test/test_mex.cc
new file mode 100644
index 0000000..d7834a9
--- /dev/null
+++ b/ucoo/arch/host/mex/test/test_mex.cc
@@ -0,0 +1,245 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/host/mex/mex_msg.hh"
+#include "ucoo/arch/host/mex/mex_node.hh"
+#include "ucoo/arch/arch.hh"
+#include "ucoo/common.hh"
+
+#include <cstdio>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+using namespace ucoo::mex;
+
+/// Global error number, should be zero at end of test.
+static int error;
+
+/// Helper function, print a buffer.
+static void
+printbuf (const char *head, const char *buf, int count)
+{
+ printf ("%s:", head);
+ for (int i = 0; i < count; i++)
+ printf (" %02x", (unsigned char) buf[i]);
+ printf ("\n");
+}
+
+/// Helper function, check for equality.
+static void
+check (int64_t a, int64_t b, const char *name = NULL)
+{
+ printf ("%s: %Lx\n", name ? name : "pop", a);
+ if (a != b)
+ {
+ printf (" expected: %Lx\n", b);
+ error++;
+ }
+}
+
+/// Test writer, will check what is written and display it.
+class TestWriter : public MsgWriter
+{
+ const char *exbuf_;
+ int excount_;
+ public:
+ template<int count>
+ TestWriter (const char (&buf)[count])
+ : exbuf_ (buf), excount_ (count) { }
+ void write (const char *buf, int count)
+ {
+ printbuf ("write", buf, count);
+ if (count != excount_ || memcmp (buf, exbuf_, count) != 0)
+ {
+ printbuf (" expected", exbuf_, excount_);
+ error++;
+ }
+ }
+};
+
+/// Test reader, will return a predefined message and display it.
+class TestReader : public MsgReader
+{
+ const char *buf_;
+ int count_;
+ public:
+ template<int count>
+ TestReader (const char (&buf)[count])
+ : buf_ (buf), count_ (count) { }
+ int size () { return count_; }
+ void read (char *buf)
+ {
+ printbuf ("read", buf_, count_);
+ memcpy (buf, buf_, count_);
+ }
+};
+
+/// Test message class.
+void
+test_msg ()
+{
+ {
+ Msg m (MTYPE_DATE);
+ const char w1b[] = { 0x01 };
+ TestWriter w1 (w1b);
+ m.write (w1);
+ m.push ("BHl") << 1 << 2 << 3;
+ m.push ("\x04\x05", 2);
+ const char w2b[] = { 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
+ 0x04, 0x05 };
+ TestWriter w2 (w2b);
+ m.write (w2);
+ }
+ {
+ uint32_t ua, ub, uc;
+ int32_t a, b, c;
+ const char rb[] = { 0x01, 0xff, 0xfe, 0xfd, 0xfc, 1, 2, 3, 4 };
+ TestReader r (rb);
+ Msg m (r);
+ check (m.mtype (), 1, "mtype");
+ check (m.len (), 8, "len");
+ m.pop ("BBH") >> ua >> ub >> uc;
+ check (ua, 0xff); check (ub, 0xfe); check (uc, 0xfdfc);
+ m.pop ("BBH") >> ua >> ub >> uc;
+ check (ua, 1); check (ub, 2); check (uc, 0x304);
+ m = Msg (r);
+ m.pop ("bbh") >> a >> b >> c;
+ check (a, -1); check (b, -2); check (c, -0x204);
+ m.pop ("bbh") >> a >> b >> c;
+ check (a, 1); check (b, 2); check (c, 0x304);
+ m = Msg (r);
+ m.pop ("LL") >> ua >> ub;
+ check (ua, 0xfffefdfc); check (ub, 0x01020304);
+ m = Msg (r);
+ m.pop ("ll") >> a >> b;
+ check (a, -0x010204); check (b, 0x01020304);
+ m = Msg (r);
+ const char *s;
+ s = m.pop (8);
+ printbuf ("pop", s, 8);
+ if (memcmp (s, &rb[1], 8) != 0)
+ {
+ printbuf (" expected", &rb[1], 8);
+ error++;
+ }
+ }
+ {
+ Msg m (static_cast<mtype_t> (0x20));
+ m.push ("bb") << 1 << 2;
+ m.encapsulate (static_cast<mtype_t> (0x21), "b") << 5;
+ check (m.mtype (), 0x21, "mtype");
+ check (m.len (), 4, "len");
+ const char w1b[] = { 0x21, 0x05, 0x20, 0x01, 0x02 };
+ TestWriter w1 (w1b);
+ m.write (w1);
+ m.pop ("b");
+ m.decapsulate ();
+ check (m.mtype (), 0x20, "mtype");
+ check (m.len (), 2, "len");
+ }
+}
+
+void
+test_node_1 ()
+{
+ Node node;
+ mtype_t hello_mtype, world_mtype;
+ hello_mtype = node.reserve ("hello");
+ world_mtype = node.reserve ("world");
+ node.wait (42);
+ Msg hello (hello_mtype);
+ hello.push ("l") << 42;
+ node.send (hello);
+ Msg world (world_mtype);
+ world.push ("bh") << 12 << 5678;
+ std::auto_ptr<Msg> resp (node.request (world));
+ int sum;
+ resp->pop ("l") >> sum;
+ ucoo::assert (sum == 12 + 5678);
+ node.wait (42 * 2);
+}
+
+void
+test_node_2_handle_hello (Node &, Msg &msg)
+{
+ int pass;
+ msg.pop ("l") >> pass;
+ ucoo::assert (pass == 42);
+ printf ("hello\n");
+}
+
+void
+test_node_2_handle_world (Node &node, Msg &msg)
+{
+ int a, b;
+ msg.pop ("bh") >> a >> b;
+ printf ("world\n");
+ Msg resp (msg.mtype ());
+ resp.push ("l") << a + b;
+ node.response (resp);
+}
+
+void
+test_node_2 ()
+{
+ Node node;
+ mtype_t hello_mtype, world_mtype;
+ hello_mtype = node.reserve ("hello");
+ world_mtype = node.reserve ("world");
+ node.handler_register (hello_mtype, test_node_2_handle_hello);
+ node.handler_register (world_mtype, test_node_2_handle_world);
+ node.wait ();
+}
+
+/// Test node operation, need a Mex hub to work.
+void
+test_node ()
+{
+ int pid;
+ pid = fork ();
+ ucoo::assert_perror (pid != -1);
+ if (pid)
+ {
+ test_node_1 ();
+ int status;
+ waitpid (pid, &status, 0);
+ }
+ else
+ {
+ test_node_2 ();
+ ucoo::assert_unreachable ();
+ }
+}
+
+int
+main (int argc, const char **argv)
+{
+ ucoo::arch_init (argc, argv);
+ test_msg ();
+ test_node ();
+ printf ("%s\n", error ? "FAIL" : "PASS");
+ return error ? 1 : 0;
+}
diff --git a/ucoo/arch/host/test/Makefile b/ucoo/arch/host/test/Makefile
new file mode 100644
index 0000000..9a329a3
--- /dev/null
+++ b/ucoo/arch/host/test/Makefile
@@ -0,0 +1,9 @@
+BASE = ../../../..
+
+TARGETS = host
+host_PROGS = test_host
+test_host_SOURCES = test_host.cc
+
+MODULES =
+
+include $(BASE)/build/top.mk
diff --git a/ucoo/arch/host/test/test_host.cc b/ucoo/arch/host/test/test_host.cc
new file mode 100644
index 0000000..645836a
--- /dev/null
+++ b/ucoo/arch/host/test/test_host.cc
@@ -0,0 +1,49 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/host/host.hh"
+#include "ucoo/arch/arch.hh"
+
+#include <cstdio>
+#include <cstdlib>
+
+int
+main (int argc, const char **argv)
+{
+ ucoo::arch_init (argc, argv);
+ ucoo::Host host ("test_host");
+ host.add_option ('c', "connect to mex hub");
+ host.add_option ('p', "FOO", "print FOO", "Hello world!");
+ host.add_option ('s', "STRIP", "print striped instance", "");
+ host.parse_options ();
+ puts (host.get_option ('p').c_str ());
+ if (host.is_option_set ('s'))
+ {
+ const std::string &strips = host.get_option ('s');
+ int strip = atoi (strips.c_str ()); // Quick'n dirty convertion.
+ puts (host.get_instance (strip).c_str ());
+ }
+ if (host.is_option_set ('c'))
+ host.get_node ();
+ return 0;
+}
diff --git a/ucoo/arch/stm32f4/stm32f4.ld b/ucoo/arch/stm32f4/stm32f4.ld
new file mode 100644
index 0000000..ceef7af
--- /dev/null
+++ b/ucoo/arch/stm32f4/stm32f4.ld
@@ -0,0 +1,6 @@
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+INCLUDE libopencm3_stm32f4.ld
diff --git a/ucoo/arch/syscalls.cc b/ucoo/arch/syscalls.cc
new file mode 100644
index 0000000..b35ac5a
--- /dev/null
+++ b/ucoo/arch/syscalls.cc
@@ -0,0 +1,36 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+namespace __gnu_cxx {
+
+/// Replaces the default verbose terminate handler.
+/// Avoids the inclusion of code to inpect C++ objects.
+void
+__verbose_terminate_handler ()
+{
+ while (1)
+ ;
+}
+
+} //namespace __gnu_cxx
diff --git a/ucoo/arch/syscalls.newlib.cc b/ucoo/arch/syscalls.newlib.cc
new file mode 100644
index 0000000..abdd75f
--- /dev/null
+++ b/ucoo/arch/syscalls.newlib.cc
@@ -0,0 +1,179 @@
+/* ucoolib - Microcontroller object oriented library. {{{
+ *
+ * Copyright (C) 2012 Nicolas Schodet
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * }}} */
+#include "ucoo/common.hh"
+#include "syscalls.newlib.hh"
+
+#include <reent.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+ucoo::Stream *ucoo::syscalls_streams[3];
+
+/** This is needed by C++ ABI, this simple definition will do. See:
+ * http://lists.debian.org/debian-gcc/2003/07/msg00057.html */
+void *__dso_handle = (void*) &__dso_handle;
+
+/** This function is called when a pure virtual function is called. This is
+ * needed by linker because when a abstract class constructor or destructor is
+ * called, object is not complete. Replace the one provided by the toolchain
+ * to avoid including the world. */
+extern "C" void
+__cxa_pure_virtual (void)
+{
+ ucoo::halt ();
+}
+
+/** Increase program data space. */
+extern "C" void *
+_sbrk_r (struct _reent *ptr, int incr)
+{
+ extern char end; /* Defined in linker script. */
+ static char *heap_end;
+ char *prev_heap_end;
+ if (heap_end == 0)
+ heap_end = &end;
+ prev_heap_end = heap_end;
+ heap_end += incr;
+ return (void *) prev_heap_end;
+}
+
+/** Exit program, endless loop to stop program, to be improved. */
+extern "C" void
+_exit (int n)
+{
+ ucoo::halt ();
+}
+
+/** Close a file, unimplemented. */
+extern "C" int
+_close_r (struct _reent *ptr, int fd)
+{
+ return -1;
+}
+
+/** Status of open file, consider all files as character devices. */
+extern "C" int
+_fstat_r (struct _reent *ptr, int fd, struct stat *st)
+{
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+/** Get PID, minimal implementation. */
+extern "C" int
+_getpid_r (struct _reent *ptr)
+{
+ return 1;
+}
+
+/** Whether file is a terminal, consider this is always true. */
+extern "C" int
+_isatty_r (struct _reent *ptr, int fd)
+{
+ return 1;
+}
+
+/** Send a signal, no process, no signal. */
+extern "C" int
+_kill_r (struct _reent *ptr, int pid, int sig)
+{
+ ptr->_errno = EINVAL;
+ return -1;
+}
+
+/** Set position in a file, no-op. */
+extern "C" off_t
+_lseek_r (struct _reent *ptr, int fd, off_t pos, int whence)
+{
+ return 0;
+}
+
+/** Open a file, unimplemented. */
+extern "C" int
+_open_r (struct _reent *ptr, const char *file, int flags, int mode)
+{
+ return -1;
+}
+
+/** Read from file. */
+extern "C" int
+_read_r (struct _reent *ptr, int fd, void *buf, size_t cnt)
+{
+ if (fd == 0)
+ {
+ if (ucoo::syscalls_streams[0])
+ {
+ ucoo::Stream &s = *ucoo::syscalls_streams[0];
+ int r = s.read (reinterpret_cast<char *> (buf), cnt);
+ switch (r)
+ {
+ case -2:
+ return 0;
+ case -1:
+ ptr->_errno = EIO;
+ return -1;
+ case 0:
+ ptr->_errno = EAGAIN;
+ return -1;
+ default:
+ return r;
+ }
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ ptr->_errno = EBADF;
+ return -1;
+ }
+}
+
+/** Write to file. */
+extern "C" int
+_write_r (struct _reent *ptr, int fd, const void *buf, size_t cnt)
+{
+ if ((fd == 1 || fd == 2) && ucoo::syscalls_streams[fd])
+ {
+ ucoo::Stream &s = *ucoo::syscalls_streams[fd];
+ int r = s.write (reinterpret_cast<const char *> (buf), cnt);
+ switch (r)
+ {
+ case -1:
+ ptr->_errno = EIO;
+ return -1;
+ case 0:
+ ptr->_errno = EAGAIN;
+ return -1;
+ default:
+ return r;
+ }
+ }
+ else
+ {
+ ptr->_errno = EBADF;
+ return -1;
+ }
+}
+
diff --git a/ucoo/arch/syscalls.newlib.hh b/ucoo/arch/syscalls.newlib.hh
new file mode 100644
index 0000000..af4ff98
--- /dev/null
+++ b/ucoo/arch/syscalls.newlib.hh
@@ -0,0 +1,35 @@
+#ifndef ucoo_arch_syscalls_newlib_hh
+#define ucoo_arch_syscalls_newlib_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/intf/stream.hh"
+
+namespace ucoo {
+
+// Streams used as stdin, stdout and stderr.
+extern Stream *syscalls_streams[3];
+
+} // namespace ucoo
+
+#endif // ucoo_arch_syscalls_newlib_hh