diff --git a/lib/c/2006/cppmacros.h b/lib/c/2006/cppmacros.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3e446b0a76d4e3218d9146dc929473ebd68f9c0
--- /dev/null
+++ b/lib/c/2006/cppmacros.h
@@ -0,0 +1,8 @@
+// C Preprocessor macros.
+#ifndef CPP_MACROS_H
+#define CPP_MACROS_H
+
+#define X_EMPTY(mac) var ## 1
+#define EMPTY(mac) X_EMPTY(mac)	// Returns 1 if macro mac is empty.
+
+#endif
diff --git a/lib/c/2006/labcomm2006.c b/lib/c/2006/labcomm2006.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ffce30b2446dd71de957ce40bb409888e43c94e
--- /dev/null
+++ b/lib/c/2006/labcomm2006.c
@@ -0,0 +1,262 @@
+/*
+  labcomm.c -- runtime for handling encoding and decoding of
+               labcomm samples.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef LABCOMM_COMPAT
+  #include LABCOMM_COMPAT
+#else
+  #include <stdio.h>
+  #include <strings.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "labcomm.h"
+#include "labcomm_private.h"
+#include "labcomm_ioctl.h"
+#include "labcomm_dynamic_buffer_writer.h"
+
+#define LABCOMM_VERSION "LabComm2006"
+
+/* Unwrapping reader/writer functions */
+#define UNWRAP_ac(rw, ac, ...) ac
+#define UNWRAP(func, ...)	     \
+  while (1) {								\
+    if (UNWRAP_ac(__VA_ARGS__)->action->func) {				\
+      return UNWRAP_ac(__VA_ARGS__)->action->func(__VA_ARGS__); }	\
+    if (UNWRAP_ac(__VA_ARGS__)->next == NULL) { return -ENOSYS; }	\
+    UNWRAP_ac( __VA_ARGS__) = UNWRAP_ac(__VA_ARGS__)->next;		\
+  }
+
+int labcomm_reader_alloc(struct labcomm_reader *r, 
+                         struct labcomm_reader_action_context *action_context, 
+                         char *labcomm_version)
+{
+  UNWRAP(alloc, r, action_context, labcomm_version);
+}
+
+int labcomm_reader_free(struct labcomm_reader *r, 
+                        struct labcomm_reader_action_context *action_context)
+{
+  UNWRAP(free, r, action_context);
+}
+
+int labcomm_reader_start(struct labcomm_reader *r, 
+                         struct labcomm_reader_action_context *action_context,
+			 int local_index, int remote_index,
+			 struct labcomm_signature *signature,
+			 void *value)
+{
+  UNWRAP(start, r, action_context, local_index, remote_index, signature, value);
+}
+
+int labcomm_reader_end(struct labcomm_reader *r, 
+                       struct labcomm_reader_action_context *action_context)
+{
+  UNWRAP(end, r, action_context);
+}
+
+int labcomm_reader_fill(struct labcomm_reader *r, 
+                        struct labcomm_reader_action_context *action_context)
+{
+  UNWRAP(fill, r, action_context);
+}
+
+int labcomm_reader_ioctl(struct labcomm_reader *r, 
+                         struct labcomm_reader_action_context *action_context,
+                         int local_index, int remote_index,
+                         struct labcomm_signature *signature, 
+                         uint32_t ioctl_action, va_list args)
+{
+  UNWRAP(ioctl, r, action_context, 
+	 local_index, remote_index, signature, ioctl_action, args);
+}
+
+int labcomm_writer_alloc(struct labcomm_writer *w, 
+                         struct labcomm_writer_action_context *action_context, 
+                         char *labcomm_version)
+{
+  UNWRAP(alloc, w, action_context, labcomm_version);
+}
+
+int labcomm_writer_free(struct labcomm_writer *w, 
+                        struct labcomm_writer_action_context *action_context)
+{
+  UNWRAP(free, w, action_context);
+}
+
+int labcomm_writer_start(struct labcomm_writer *w, 
+                         struct labcomm_writer_action_context *action_context,
+                         int index, struct labcomm_signature *signature,
+                         void *value)
+{
+  UNWRAP(start, w, action_context, index, signature, value);
+}
+
+int labcomm_writer_end(struct labcomm_writer *w, 
+                       struct labcomm_writer_action_context *action_context)
+{
+  UNWRAP(end, w, action_context);
+} 
+
+int labcomm_writer_flush(struct labcomm_writer *w, 
+                         struct labcomm_writer_action_context *action_context)
+{
+  UNWRAP(flush, w, action_context);
+} 
+
+int labcomm_writer_ioctl(struct labcomm_writer *w, 
+                         struct labcomm_writer_action_context *action_context, 
+                         int index, 
+                         struct labcomm_signature *signature, 
+                         uint32_t ioctl_action, va_list args)
+{
+  UNWRAP(ioctl, w, action_context, index, signature, ioctl_action, args);
+} 
+
+#undef UNWRAP
+#undef UNWRAP_ac
+
+
+
+
+static const char *labcomm_error_string[] = { 
+#define LABCOMM_ERROR(name, description) description ,
+#include "labcomm_error.h"
+#undef LABCOMM_ERROR
+};
+static const int labcomm_error_string_count = (sizeof(labcomm_error_string) / 
+					       sizeof(labcomm_error_string[0]));
+
+
+const char *labcomm_error_get_str(enum labcomm_error error_id)
+{
+  const char *error_str = NULL;
+  // Check if this is a known error ID.
+  if (error_id < labcomm_error_string_count) {
+    error_str = labcomm_error_string[error_id];
+  }
+  return error_str;
+}
+
+void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...)
+{
+#ifndef LABCOMM_NO_STDIO
+  const char *err_msg = labcomm_error_get_str(error_id); // The final string to print.
+  if (err_msg == NULL) {
+    err_msg = "Error with an unknown error ID occured.";
+  }
+  fprintf(stderr, "%s\n", err_msg);
+
+ if (nbr_va_args > 0) {
+   va_list arg_pointer;
+   va_start(arg_pointer, nbr_va_args);
+
+   fprintf(stderr, "%s\n", "Extra info {");
+   char *print_format = va_arg(arg_pointer, char *);
+   vfprintf(stderr, print_format, arg_pointer);
+   fprintf(stderr, "}\n");
+
+   va_end(arg_pointer);
+ } 
+#else
+ ; // If labcomm can't be compiled with stdio the user will have to make an own error callback functionif he/she needs error reporting.
+#endif
+}
+
+
+
+#if 0
+static void dump(void *p, int size, int first, int last)
+{
+  int i, j;
+
+  printf("%d %d (%p): ", first, last, p);
+  for (i = first ; i < last ; i++) {
+    for (j = 0 ; j < size ; j++) {
+      printf("%2.2d", ((char*)p)[(i-first)*size + j]);
+    }
+    printf(" ");
+  }
+  printf("\n");
+}
+#endif
+
+void *labcomm_signature_array_ref(struct labcomm_memory *memory,
+				  int *first, int *last, void **data,
+				  int size, int index)
+{
+  if (*first == 0 && *last == 0) {
+    *first = index;
+    *last = index + 1;
+    *data = labcomm_memory_alloc(memory, 0, size);
+    if (*data) { 
+      memset(*data, 0, size); 
+    }
+  } else if (index < *first || *last <= index) {
+    void *old_data = *data;
+    int old_first = *first;
+    int old_last = *last;
+    int n;
+    *first = (index<old_first)?index:old_first;
+    *last = (old_last<=index)?index+1:old_last;
+    n = (*last - *first);
+    *data = labcomm_memory_alloc(memory, 0, n * size);
+    if (*data) {
+      memset(*data, 0, n * size);
+      memcpy(*data + (old_first - *first) * size, 
+	     old_data, 
+	     (old_last - old_first) * size);
+    }
+//    dump(old_data, size, old_first, old_last);
+    labcomm_memory_free(memory, 0, old_data);
+  }
+  if (*data) {
+//    dump(*data, size, *first, *last);
+    return *data + (index - *first) * size;
+  } else {
+    return NULL;
+  }
+}
+
+static int local_index = 0x40;
+
+void labcomm_set_local_index(struct labcomm_signature *signature)
+{
+  if (signature->index != 0) {
+    labcomm_error_fatal_global(LABCOMM_ERROR_SIGNATURE_ALREADY_SET,
+			       "%s", signature->name);
+  }
+  signature->index = local_index;
+  local_index++;
+}
+
+int labcomm_get_local_index(struct labcomm_signature *signature)
+{
+  if (signature->index == 0) {
+    labcomm_error_fatal_global(LABCOMM_ERROR_SIGNATURE_NOT_SET,
+			       "%s", signature->name);
+  }
+  return signature->index;
+}
diff --git a/lib/c/2006/labcomm2006.h b/lib/c/2006/labcomm2006.h
new file mode 100644
index 0000000000000000000000000000000000000000..b83cdf85faa6dc4890d489ec915b5329090993a9
--- /dev/null
+++ b/lib/c/2006/labcomm2006.h
@@ -0,0 +1,143 @@
+/*
+  labcomm.h -- user interface for handling encoding and decoding of
+               labcomm samples.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_H_
+#define _LABCOMM_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "labcomm_error.h"
+#include "labcomm_scheduler.h"
+
+/* Forward declaration */
+struct labcomm_encoder;
+struct labcomm_decoder;
+
+/*
+ * Signature entry
+ */
+struct labcomm_signature {
+  int type;
+  char *name;
+  int (*encoded_size)(struct labcomm_signature *, void *); // void * == encoded_sample *
+  int size;
+  unsigned char *signature; 
+  int index;
+#ifdef LABCOMM_EXPERIMENTAL_CACHED_ENCODED_SIZE
+  int cached_encoded_size; // -1 if not initialized or type is variable size
+#endif
+};
+
+/*
+ * Error handling.
+ */
+
+/* The callback prototype for error handling.
+ * First parameter is the error ID.
+ * The second paramters is the number of va_args that comes after this 
+ * one. If none it should be 0.
+ * Optionaly other paramters can be supplied depending on what is needed 
+ * for this error ID.
+ */
+typedef void (*labcomm_error_handler_callback)(enum labcomm_error error_id, 
+					       size_t nbr_va_args, ...); 
+
+/* Default error handler, prints message to stderr. 
+ * Extra info about the error can be supplied as char* as VA-args. Especially user defined errors should supply a describing string. if nbr_va_args > 1 the first variable argument must be a printf format string and the possibly following arguments are passed as va_args to vprintf. 
+ */
+void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...);
+
+/* Register a callback for the error handler for this encoder. */
+void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback);
+
+/* Register a callback for the error handler for this decoder. */
+void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback);
+
+/* Get a string describing the supplied standrad labcomm error. */
+const char *labcomm_error_get_str(enum labcomm_error error_id);
+
+typedef int (*labcomm_handle_new_datatype_callback)(
+  struct labcomm_decoder *decoder,
+  struct labcomm_signature *sig);
+
+void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d,
+		labcomm_handle_new_datatype_callback on_new_datatype);
+
+/*
+ * Dynamic memory handling
+ *   lifetime == 0     memory that will live for as long as the 
+ *                     encoder/decoder or that are allocated/deallocated 
+ *                     during the communication setup phase
+ *   otherwise         memory will live for approximately this number of
+ *                     sent/received samples
+ */
+struct labcomm_memory;
+
+void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, size_t size);
+void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, 
+			     void *ptr, size_t size);
+void labcomm_memory_free(struct labcomm_memory *m, int lifetime, void *ptr);
+
+/*
+ * Decoder
+ */
+struct labcomm_reader;
+
+struct labcomm_decoder *labcomm_decoder_new(
+  struct labcomm_reader *reader,
+  struct labcomm_error_handler *error,
+  struct labcomm_memory *memory,
+  struct labcomm_scheduler *scheduler);
+void labcomm_decoder_free(
+  struct labcomm_decoder *decoder);
+int labcomm_decoder_decode_one(
+  struct labcomm_decoder *decoder);
+void labcomm_decoder_run(
+  struct labcomm_decoder *decoder);
+
+/* See labcomm_ioctl.h for predefined ioctl_action values */
+int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, 
+			  uint32_t ioctl_action,
+			  ...);
+
+/*
+ * Encoder
+ */
+struct labcomm_writer;
+
+struct labcomm_encoder *labcomm_encoder_new(
+  struct labcomm_writer *writer,
+  struct labcomm_error_handler *error,
+  struct labcomm_memory *memory,
+  struct labcomm_scheduler *scheduler);
+void labcomm_encoder_free(
+  struct labcomm_encoder *encoder);
+
+/* See labcomm_ioctl.h for predefined ioctl_action values */
+int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, 
+			  uint32_t ioctl_action,
+			  ...);
+
+#define LABCOMM_VOID ((void*)1)
+
+#endif
diff --git a/lib/c/2006/labcomm2006_compat_arm_cortexm3.h b/lib/c/2006/labcomm2006_compat_arm_cortexm3.h
new file mode 100644
index 0000000000000000000000000000000000000000..512ad3633fa0bd29e9bbd7c4db22ea8881da95b3
--- /dev/null
+++ b/lib/c/2006/labcomm2006_compat_arm_cortexm3.h
@@ -0,0 +1,5 @@
+#ifndef ARM_CORTEXM3_CODESOURCERY
+#error "ARM_CORTEXM3_CODESOURCERY" not defined
+#endif
+
+#include <machine/endian.h>
diff --git a/lib/c/2006/labcomm2006_compat_osx.h b/lib/c/2006/labcomm2006_compat_osx.h
new file mode 100644
index 0000000000000000000000000000000000000000..1219f3f54bf8864db9ecb4a4f8fd0c915916034e
--- /dev/null
+++ b/lib/c/2006/labcomm2006_compat_osx.h
@@ -0,0 +1,28 @@
+#ifndef __APPLE__
+#error "__APPLE__" not defined
+#endif
+
+#ifndef LABCOMM_COMPAT_OSX
+#define LABCOMM_COMPAT_OSX
+
+#include <machine/endian.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <mach/clock.h>
+#include <mach/mach.h>
+
+#define CLOCK_REALTIME 0
+static inline void clock_gettime(int garbage, struct timespec *ts)
+{
+  (void) garbage;
+  clock_serv_t cclock;
+  mach_timespec_t mts;
+  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+  clock_get_time(cclock, &mts);
+  mach_port_deallocate(mach_task_self(), cclock);
+  ts->tv_sec = mts.tv_sec;
+  ts->tv_nsec = mts.tv_nsec;
+}
+
+#endif
diff --git a/lib/c/2006/labcomm2006_compat_vxworks.h b/lib/c/2006/labcomm2006_compat_vxworks.h
new file mode 100644
index 0000000000000000000000000000000000000000..f05ee787d334e27dd32ef03bd0ff84b3c2cea086
--- /dev/null
+++ b/lib/c/2006/labcomm2006_compat_vxworks.h
@@ -0,0 +1,12 @@
+#ifndef  __VXWORKS__
+#error "__VXWORKS__" not defined
+#endif
+
+#if (CPU == PPC603)
+  #undef _LITTLE_ENDIAN
+#endif
+
+#if (CPU == PENTIUM4)
+  #undef _BIG_ENDIAN
+#endif
+
diff --git a/lib/c/2006/labcomm2006_decoder.c b/lib/c/2006/labcomm2006_decoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..0a491641d0cb749d6714a7cd7d456f5c80aa9406
--- /dev/null
+++ b/lib/c/2006/labcomm2006_decoder.c
@@ -0,0 +1,426 @@
+/*
+  labcomm_decoder.c -- runtime for handling decoding of labcomm samples.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#define LABCOMM_VERSION "LabComm2006"
+
+#include <errno.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+#include "labcomm_ioctl.h"
+#include "labcomm_dynamic_buffer_writer.h"
+
+struct sample_entry {
+  int remote_index;
+  struct labcomm_signature *signature;
+  labcomm_decoder_function decode;
+  labcomm_handler_function handler;
+  void *context;
+};
+
+struct labcomm_decoder {
+  struct labcomm_reader *reader;
+  int reader_allocated;
+  struct labcomm_error_handler *error;
+  struct labcomm_memory *memory;
+  struct labcomm_scheduler *scheduler;
+  labcomm_error_handler_callback on_error;
+  labcomm_handle_new_datatype_callback on_new_datatype;
+  LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
+  LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
+};
+
+struct labcomm_decoder *labcomm_decoder_new(
+  struct labcomm_reader *reader,
+  struct labcomm_error_handler *error,
+  struct labcomm_memory *memory,
+  struct labcomm_scheduler *scheduler)
+{
+  struct labcomm_decoder *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
+  if (result) {
+    result->reader = reader;
+    result->reader->decoder = result;
+    result->reader->data = 0;
+    result->reader->data_size = 0;
+    result->reader->count = 0;
+    result->reader->pos = 0;
+    result->reader->error = 0;
+    result->reader_allocated = 0;
+    result->error = error;
+    result->memory = memory;
+    result->scheduler = scheduler;
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
+  }
+  return result;
+}
+
+void labcomm_decoder_free(struct labcomm_decoder* d)
+{
+  struct labcomm_memory *memory = d->memory;
+
+  labcomm_reader_free(d->reader, d->reader->action_context);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry);
+  LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int);
+  labcomm_memory_free(memory, 0, d);
+}
+
+static int collect_flat_signature(
+  struct labcomm_decoder *decoder,
+  struct labcomm_writer *writer)
+{
+  int result, type;
+
+  type = labcomm_read_packed32(decoder->reader); 
+  result = decoder->reader->error;
+  if (result < 0) { goto out; }
+  if (type >= LABCOMM_USER) {
+    decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
+			"Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type);
+  } else {
+    labcomm_write_packed32(writer, type); 
+    switch (type) {
+      case LABCOMM_ARRAY: {
+	int dimensions, i;
+
+	dimensions = labcomm_read_packed32(decoder->reader);
+	labcomm_write_packed32(writer, dimensions);
+	for (i = 0 ; i < dimensions ; i++) {
+	  int n = labcomm_read_packed32(decoder->reader);
+	  labcomm_write_packed32(writer, n);
+	}
+	result = collect_flat_signature(decoder, writer);
+	if (result < 0) { goto out; }
+      } break;
+      case LABCOMM_STRUCT: {
+	int fields, i;
+
+	fields = labcomm_read_packed32(decoder->reader); 
+	labcomm_write_packed32(writer, fields); 
+	for (i = 0 ; i < fields ; i++) {
+	  char *name = labcomm_read_string(decoder->reader);
+	  labcomm_write_string(writer, name);
+	  labcomm_memory_free(decoder->memory, 1, name);
+	  result = collect_flat_signature(decoder, writer);
+	  if (result < 0) { goto out; }
+	}
+      } break;
+      case LABCOMM_BOOLEAN:
+      case LABCOMM_BYTE:
+      case LABCOMM_SHORT:
+      case LABCOMM_INT:
+      case LABCOMM_LONG:
+      case LABCOMM_FLOAT:
+      case LABCOMM_DOUBLE:
+      case LABCOMM_STRING: {
+      } break;
+      default: {
+	result = -ENOSYS;
+        decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
+				"Implement %s (2) for type 0x%x...\n", __FUNCTION__, type);
+      } break;
+    }
+  }
+out:
+  return result;
+}
+
+static int writer_ioctl(struct labcomm_writer *writer,
+			uint32_t action,
+			...)
+{
+  int result;
+  va_list va;
+
+  if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
+    result = -EINVAL;
+    goto out;
+  }
+  
+  va_start(va, action);
+  result = labcomm_writer_ioctl(writer, writer->action_context, 
+				0, NULL, action, va);
+  va_end(va);
+out:
+  return result;
+}
+
+static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind)
+{
+  int result;
+
+  /* TODO: should the labcomm_dynamic_buffer_writer be 
+     a permanent part of labcomm_decoder? */
+  struct labcomm_writer_action_context action_context = {
+    .next = NULL,
+    .action = labcomm_dynamic_buffer_writer_action,
+    .context = NULL
+  };
+  struct labcomm_writer writer = {
+    .action_context = &action_context,
+    .memory = d->memory,
+    .data = NULL,
+    .data_size = 0,
+    .count = 0,
+    .pos = 0,
+    .error = 0,
+  };
+  struct labcomm_signature signature, *local_signature;
+  int remote_index, local_index, err;
+  
+  local_signature = NULL;
+  local_index = 0;
+  labcomm_writer_alloc(&writer, writer.action_context, "");
+  labcomm_writer_start(&writer, writer.action_context, 0, NULL, NULL);
+  remote_index = labcomm_read_packed32(d->reader);
+  signature.name = labcomm_read_string(d->reader);
+  signature.type = kind;
+  collect_flat_signature(d, &writer);
+  labcomm_writer_end(&writer, writer.action_context);
+  err = writer_ioctl(&writer, 
+		     LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
+		     &signature.size);
+  if (err < 0) {
+    fprintf(stderr, "Failed to get size: %s\n", strerror(-err));
+    result = -ENOENT;
+    goto free_signature_name;
+  }
+  err = writer_ioctl(&writer, 
+		     LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
+		     &signature.signature);
+  if (err < 0) {
+    fprintf(stderr, "Failed to get pointer: %s\n", strerror(-err));
+    result = -ENOENT;
+    goto free_signature_name;
+  }
+  {
+    int i;
+
+    labcomm_scheduler_data_lock(d->scheduler);
+    LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) {
+      struct sample_entry *s;
+      int *remote_to_local;
+      
+      result = -ENOENT;
+      s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
+				      d->local,  struct sample_entry, i);
+      if (s->signature &&
+	  s->signature->type == signature.type &&
+	  s->signature->size == signature.size &&
+	  strcmp(s->signature->name, signature.name) == 0 &&
+	  memcmp((void*)s->signature->signature, (void*)signature.signature,
+	       signature.size) == 0) {
+	s->remote_index = remote_index;
+	local_signature = s->signature;
+	local_index = i;
+	remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+						      d->remote_to_local, int,
+						      remote_index);
+	*remote_to_local = i;
+	result = remote_index;
+	break;
+      }
+    }
+    labcomm_scheduler_data_unlock(d->scheduler);
+    if (local_signature) {
+      labcomm_reader_start(d->reader, d->reader->action_context,
+			   local_index, remote_index, local_signature,
+			   NULL);
+      labcomm_reader_end(d->reader, d->reader->action_context);
+    }
+  }
+#if 0
+  if (! entry) {
+    /* Unknown datatype, bail out */
+    d->on_new_datatype(d, &signature);
+    result = -ENOENT;
+  } else if (entry->index && entry->index != remote_index) {
+    d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5, 
+		"%s(): index mismatch '%s' (id=0x%x != 0x%x)\n", 
+		__FUNCTION__, signature.name, entry->index, remote_index);
+    result = -ENOENT;
+#endif
+free_signature_name:
+  labcomm_memory_free(d->memory, 0, signature.name);
+  labcomm_writer_free(&writer, writer.action_context);
+  return result;
+}
+
+struct call_handler_context {
+  struct labcomm_reader *reader;
+  int local_index;
+  int remote_index;
+  struct labcomm_signature *signature;
+  labcomm_handler_function handler;
+  void *context;
+};
+
+static void call_handler(void *value, void *context)
+{
+  struct call_handler_context *wrap = context;
+
+  if (wrap->reader->error >= 0) {
+    labcomm_reader_start(wrap->reader, wrap->reader->action_context,
+			 wrap->local_index, wrap->remote_index, wrap->signature,
+			 value);
+    wrap->handler(value, wrap->context);
+    labcomm_reader_end(wrap->reader, wrap->reader->action_context);
+  }
+}
+
+static void reader_alloc(struct labcomm_decoder *d)
+{
+  if (!d->reader_allocated) {
+    d->reader_allocated = 1;
+    labcomm_reader_alloc(d->reader, d->reader->action_context,
+			 LABCOMM_VERSION);
+  }
+}
+
+int labcomm_decoder_decode_one(struct labcomm_decoder *d)
+{
+  int result, remote_index;
+
+  reader_alloc(d);
+  remote_index = labcomm_read_packed32(d->reader);
+  if (d->reader->error < 0) {
+    result = d->reader->error;
+    goto out;
+  }
+  if (remote_index == LABCOMM_TYPEDEF || remote_index == LABCOMM_SAMPLE) {
+    result = decode_typedef_or_sample(d, remote_index); 
+  } else {
+    int *local_index;
+    struct call_handler_context wrap = {
+      .reader = d->reader,
+      .remote_index = remote_index,
+      .signature = NULL,
+      .handler = NULL,
+      .context = NULL,
+    };
+    labcomm_decoder_function do_decode = NULL;
+
+    labcomm_scheduler_data_lock(d->scheduler);
+    local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+					      d->remote_to_local, int,
+					      remote_index);
+    if (*local_index != 0) {
+      struct sample_entry *entry;
+
+      entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+					  d->local, struct sample_entry,
+					  *local_index);
+      wrap.local_index = *local_index;
+      wrap.signature = entry->signature;
+      wrap.handler = entry->handler;
+      wrap.context = entry->context;
+      do_decode = entry->decode;
+      result = *local_index;
+    }
+    labcomm_scheduler_data_unlock(d->scheduler);
+    if (do_decode) {
+      do_decode(d->reader, call_handler, &wrap);
+      if (d->reader->error < 0) {
+	result = d->reader->error;
+      }
+    } else {
+      result = -ENOENT;
+    }
+  }
+out:
+  return result;
+}
+
+void labcomm_decoder_run(struct labcomm_decoder *d)
+{
+  while (labcomm_decoder_decode_one(d) > 0) {
+  }
+}
+
+int labcomm_decoder_ioctl(struct labcomm_decoder *d, 
+			  uint32_t action,
+			  ...)
+{
+  int result;  
+  va_list va;
+    
+  va_start(va, action);
+  result = labcomm_reader_ioctl(d->reader, 
+				d->reader->action_context,
+				0, 0, NULL, action, va);
+  va_end(va);
+  return result;
+}
+
+int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d, 
+				   struct labcomm_signature *signature,
+				   uint32_t action, va_list va)
+{
+  int result;
+  int local_index, remote_index;
+
+  local_index = labcomm_get_local_index(signature);
+  labcomm_scheduler_data_lock(d->scheduler);
+  remote_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+					     d->local,
+					     struct sample_entry,
+					     local_index)->remote_index;
+  labcomm_scheduler_data_unlock(d->scheduler);
+  result = labcomm_reader_ioctl(d->reader, d->reader->action_context,
+				local_index, remote_index, 
+				signature, action, va);
+  return result;
+}
+
+int labcomm_internal_decoder_register(
+  struct labcomm_decoder *d,
+  struct labcomm_signature *signature,
+  labcomm_decoder_function decode, 
+  labcomm_handler_function handler,
+  void *context)
+{
+  int local_index;
+  struct sample_entry *entry;
+ 
+  reader_alloc(d);
+  local_index = labcomm_get_local_index(signature);
+  if (local_index <= 0) { goto out; }
+  labcomm_reader_start(d->reader, d->reader->action_context,
+		       local_index, 0, signature,
+		       NULL);
+  labcomm_reader_end(d->reader, d->reader->action_context);
+
+  labcomm_scheduler_data_lock(d->scheduler);
+  entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
+				      d->local, struct sample_entry,
+				      local_index);
+  if (entry == NULL) { local_index = -ENOMEM; goto unlock; }
+  entry->remote_index = 0;
+  entry->signature = signature;
+  entry->decode = decode;
+  entry->handler = handler;
+  entry->context = context;
+unlock:
+  labcomm_scheduler_data_unlock(d->scheduler);
+out:
+  return local_index;
+}
+
diff --git a/lib/c/2006/labcomm2006_default_error_handler.c b/lib/c/2006/labcomm2006_default_error_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..61e04dd6d5153f360b4564364c3b37ee67a171af
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_error_handler.c
@@ -0,0 +1,24 @@
+/*
+  test_default_error_handler.c -- LabComm default error handler
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm.h"
+
+struct labcomm_error_handler *labcomm_default_error_handler = NULL;
diff --git a/lib/c/2006/labcomm2006_default_error_handler.h b/lib/c/2006/labcomm2006_default_error_handler.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cd642a9e2f986f31ce085d6fc775fa8d7312fb2
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_error_handler.h
@@ -0,0 +1,24 @@
+/*
+  test_default_error_handler.h -- LabComm default error handler
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm.h"
+
+extern struct labcomm_error_handler *labcomm_default_error_handler;
diff --git a/lib/c/2006/labcomm2006_default_memory.c b/lib/c/2006/labcomm2006_default_memory.c
new file mode 100644
index 0000000000000000000000000000000000000000..d6b13c52621352a3658e2ce51d20b9e4d92b7274
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_memory.c
@@ -0,0 +1,49 @@
+/*
+  test_default_memory.c -- LabComm default memory allocator
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+
+void *default_alloc(struct labcomm_memory *m, int lifetime, size_t size)
+{
+  return malloc(size);
+}
+
+void *default_realloc(struct labcomm_memory *m, int lifetime, 
+		      void *ptr, size_t size)
+{
+  return realloc(ptr, size);
+}
+
+void default_free(struct labcomm_memory *m, int lifetime, void *ptr)
+{
+  free(ptr);
+}
+
+struct labcomm_memory memory = {
+  .alloc = default_alloc,
+  .realloc = default_realloc,
+  .free = default_free,
+  .context = NULL
+};
+
+struct labcomm_memory *labcomm_default_memory = &memory;
diff --git a/lib/c/2006/labcomm2006_default_memory.h b/lib/c/2006/labcomm2006_default_memory.h
new file mode 100644
index 0000000000000000000000000000000000000000..09112099de57360fccb9897ab1a7926830df60b8
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_memory.h
@@ -0,0 +1,27 @@
+/*
+  test_default_memory.h -- LabComm default memory allocator
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+
+extern struct labcomm_memory *labcomm_default_memory;
+
diff --git a/lib/c/2006/labcomm2006_default_scheduler.c b/lib/c/2006/labcomm2006_default_scheduler.c
new file mode 100644
index 0000000000000000000000000000000000000000..a567b61ebddd8a6d611e020dede1c927b09fd28e
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_scheduler.c
@@ -0,0 +1,109 @@
+/*
+  test_default_scheduler.c -- LabComm default scheduler
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "labcomm_default_scheduler.h"
+#include "labcomm_scheduler.h"
+#include "labcomm_scheduler_private.h"
+
+static int scheduler_free(struct labcomm_scheduler *s)
+{
+  fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__,
+	  "not implemented");
+  exit(1);
+  return 0;
+}
+ 
+static int scheduler_writer_lock(struct labcomm_scheduler *s)
+{
+  return 0;
+}
+ 
+static int scheduler_writer_unlock(struct labcomm_scheduler *s)
+{
+  return 0;
+}
+
+static int scheduler_data_lock(struct labcomm_scheduler *s)
+{
+  return 0;
+}
+ 
+static int scheduler_data_unlock(struct labcomm_scheduler *s)
+{
+  return 0;
+}
+
+static struct labcomm_time *scheduler_now(struct labcomm_scheduler *s)
+{
+  fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__,
+	  "not implemented");
+  exit(1);
+  return NULL;
+}
+ 
+static int scheduler_sleep(struct labcomm_scheduler *s,
+			   struct labcomm_time *t)
+{
+  fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__,
+	  "not implemented");
+  exit(1);
+  return 0;
+}
+
+static int scheduler_wakeup(struct labcomm_scheduler *s)
+{
+  fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__,
+	  "not implemented");
+  exit(1);
+  return 0;
+}
+
+static int scheduler_enqueue(struct labcomm_scheduler *s,
+			     uint32_t delay,
+			     void (*deferred)(void *context),
+			     void *context)
+{
+  fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__,
+	  "not implemented");
+  exit(1);
+  return 0;
+}
+
+static const struct labcomm_scheduler_action scheduler_action = {
+  .free = scheduler_free,
+  .writer_lock = scheduler_writer_lock,
+  .writer_unlock = scheduler_writer_unlock,
+  .data_lock = scheduler_data_lock,
+  .data_unlock = scheduler_data_unlock,
+  .now = scheduler_now,
+  .sleep = scheduler_sleep,
+  .wakeup = scheduler_wakeup,
+  .enqueue = scheduler_enqueue  
+};
+
+static struct labcomm_scheduler scheduler = {
+  .action = &scheduler_action,
+  .context = NULL
+};
+
+struct labcomm_scheduler *labcomm_default_scheduler = &scheduler;
diff --git a/lib/c/2006/labcomm2006_default_scheduler.h b/lib/c/2006/labcomm2006_default_scheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..923ea20f26fe8c587dc0c97447592b738a4b0b8b
--- /dev/null
+++ b/lib/c/2006/labcomm2006_default_scheduler.h
@@ -0,0 +1,24 @@
+/*
+  test_default_scheduler.h -- LabComm default scheduler
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm.h"
+
+extern struct labcomm_scheduler *labcomm_default_scheduler;
diff --git a/lib/c/2006/labcomm2006_dynamic_buffer_writer.c b/lib/c/2006/labcomm2006_dynamic_buffer_writer.c
new file mode 100644
index 0000000000000000000000000000000000000000..3a7425d9643cd1b24d71ccb4804cdfd6bdbddd3e
--- /dev/null
+++ b/lib/c/2006/labcomm2006_dynamic_buffer_writer.c
@@ -0,0 +1,156 @@
+/*
+  labcomm_dynamic_buffer_writer.c -- LabComm dynamic memory writer.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+#include "labcomm_ioctl.h"
+#include "labcomm_dynamic_buffer_writer.h"
+
+static int dyn_alloc(struct labcomm_writer *w, 
+		     struct labcomm_writer_action_context *action_context,
+		     char *labcomm_version)
+{
+  w->data_size = 1000;
+  w->count = w->data_size;
+  w->data = labcomm_memory_alloc(w->memory, 1, w->data_size);
+  if (w->data == NULL) {
+    w->error = -ENOMEM;
+  }
+  w->pos = 0;
+
+  return w->error;
+}
+
+static int dyn_free(struct labcomm_writer *w, 
+		    struct labcomm_writer_action_context *action_context)
+{
+  labcomm_memory_free(w->memory, 1, w->data);
+  w->data = 0;
+  w->data_size = 0;
+  w->count = 0;
+  w->pos = 0;
+  labcomm_memory_free(w->memory, 0, action_context->context);
+  return 0;
+}
+
+static int dyn_start(struct labcomm_writer *w, 
+		     struct labcomm_writer_action_context *action_context,
+		     int index,
+		     struct labcomm_signature *signature,
+		     void *value)
+{
+  void *tmp;
+
+  w->data_size = 1000;
+  w->count = w->data_size;
+  tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size);
+  if (tmp != NULL) {
+    w->data = tmp;
+    w->error = 0;
+  } else {
+    w->error = -ENOMEM;
+  }
+  w->pos = 0;
+
+  return w->error;
+}
+
+static int dyn_end(struct labcomm_writer *w, 
+		   struct labcomm_writer_action_context *action_context)
+{
+  return 0;
+}
+
+static int dyn_flush(struct labcomm_writer *w, 
+		     struct labcomm_writer_action_context *action_context)
+{
+  void *tmp;
+
+  w->data_size += 1000;
+  w->count = w->data_size;
+  tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size);
+  if (tmp != NULL) {
+    w->data = tmp;
+    w->error = 0;
+  } else {
+    /* Old pointer in w->data still valid */
+    w->error = -ENOMEM;
+  }
+
+  return w->error; 
+}
+
+static int dyn_ioctl(struct labcomm_writer *w, 
+		     struct labcomm_writer_action_context *action_context, 
+		     int signature_index,
+		     struct labcomm_signature *signature,
+		     uint32_t action, va_list arg)
+{
+  int result = -ENOTSUP;
+  switch (action) {
+    case LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN: {
+      int *value = va_arg(arg, int*);
+      *value = w->pos;
+      result = 0;
+    } break;
+    case LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER: {
+      void **value = va_arg(arg, void**);
+      *value = w->data;
+      result = 0;
+    } break;
+  }
+  return result;
+}
+
+static const struct labcomm_writer_action action = {
+  .alloc = dyn_alloc,
+  .free = dyn_free,
+  .start = dyn_start,
+  .end = dyn_end,
+  .flush = dyn_flush,
+  .ioctl = dyn_ioctl
+};
+const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action = 
+  &action;
+
+struct labcomm_writer *labcomm_dynamic_buffer_writer_new(
+  struct labcomm_memory *memory)
+{
+  struct result {
+    struct labcomm_writer writer;
+    struct labcomm_writer_action_context action_context;
+  } *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
+  if (result != NULL) {
+    result->action_context.next = NULL;
+    result->action_context.context = result;
+    result->action_context.action = &action;
+    result->writer.action_context = &result->action_context;
+    result->writer.memory = memory;
+    return &result->writer;
+  }
+  return NULL;
+}
+
diff --git a/lib/c/2006/labcomm2006_dynamic_buffer_writer.h b/lib/c/2006/labcomm2006_dynamic_buffer_writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..53a65d42c878dea278f78f7572774658c86d6fe0
--- /dev/null
+++ b/lib/c/2006/labcomm2006_dynamic_buffer_writer.h
@@ -0,0 +1,32 @@
+/*
+  labcomm_dynamic_buffer_writer.h -- LabComm dynamic memory writer.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
+#define _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_
+
+#include "labcomm.h"
+
+extern const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action;
+
+struct labcomm_writer *labcomm_dynamic_buffer_writer_new(
+  struct labcomm_memory *memory);
+
+#endif
diff --git a/lib/c/2006/labcomm2006_encoder.c b/lib/c/2006/labcomm2006_encoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..47e6320d7101988afa02c6bf29a429796557f0bc
--- /dev/null
+++ b/lib/c/2006/labcomm2006_encoder.c
@@ -0,0 +1,167 @@
+/*
+  labcomm_encoder.c -- handling encoding of labcomm samples.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#define LABCOMM_VERSION "LabComm2006"
+
+#include <errno.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
+#include "labcomm_ioctl.h"
+
+struct labcomm_encoder {
+  struct labcomm_writer *writer;
+  struct labcomm_error_handler *error;
+  struct labcomm_memory *memory;
+  struct labcomm_scheduler *scheduler;
+  LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
+};
+
+struct labcomm_encoder *labcomm_encoder_new(
+  struct labcomm_writer *writer,
+  struct labcomm_error_handler *error,
+  struct labcomm_memory *memory,
+  struct labcomm_scheduler *scheduler)
+{
+  struct labcomm_encoder *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
+  if (result) {
+    result->writer = writer;
+    result->writer->encoder = result;
+    result->writer->data = NULL;
+    result->writer->data_size = 0;
+    result->writer->count = 0;
+    result->writer->pos = 0;
+    result->writer->error = 0;
+    result->error = error;
+    result->memory = memory;
+    result->scheduler = scheduler;
+    LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
+    labcomm_writer_alloc(result->writer,
+			 result->writer->action_context, LABCOMM_VERSION);
+  }
+  return result;
+}
+
+void labcomm_encoder_free(struct labcomm_encoder* e)
+{
+  struct labcomm_memory *memory = e->memory;
+
+  labcomm_writer_free(e->writer, e->writer->action_context);
+  LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int);
+  labcomm_memory_free(memory, 0, e);
+}
+
+int labcomm_internal_encoder_register(
+  struct labcomm_encoder *e,
+  struct labcomm_signature *signature,
+  labcomm_encoder_function encode)
+{
+  int result = -EINVAL;
+  int index, *done, err, i;
+
+  index = labcomm_get_local_index(signature);
+  labcomm_scheduler_writer_lock(e->scheduler);
+  if (signature->type != LABCOMM_SAMPLE) { goto out; }
+  if (index <= 0) { goto out; }
+  done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, int, index);
+  if (*done) { goto out; }
+  *done = 1;	
+  err = labcomm_writer_start(e->writer, e->writer->action_context, 
+			     index, signature, NULL);
+  if (err == -EALREADY) { result = 0; goto out; }
+  if (err != 0) { result = err; goto out; }
+  labcomm_write_packed32(e->writer, signature->type);
+  labcomm_write_packed32(e->writer, index);
+  labcomm_write_string(e->writer, signature->name);
+  for (i = 0 ; i < signature->size ; i++) {
+    if (e->writer->pos >= e->writer->count) {
+      labcomm_writer_flush(e->writer, e->writer->action_context);
+    }
+    e->writer->data[e->writer->pos] = signature->signature[i];
+    e->writer->pos++;
+  }
+  labcomm_writer_end(e->writer, e->writer->action_context);
+  result = e->writer->error;
+out:
+  labcomm_scheduler_writer_unlock(e->scheduler);
+  return result;
+}
+
+int labcomm_internal_encode(
+  struct labcomm_encoder *e,
+  struct labcomm_signature *signature,
+  labcomm_encoder_function encode,
+  void *value)
+{
+  int result;
+  int index;
+
+  index = labcomm_get_local_index(signature);
+  labcomm_scheduler_writer_lock(e->scheduler);
+  result = labcomm_writer_start(e->writer, e->writer->action_context, 
+				index, signature, value);
+  if (result == -EALREADY) { result = 0; goto no_end; }
+  if (result != 0) { goto out; }
+  result = labcomm_write_packed32(e->writer, index);
+  if (result != 0) { goto out; }
+  result = encode(e->writer, value);
+out:
+  labcomm_writer_end(e->writer, e->writer->action_context);
+no_end:
+  labcomm_scheduler_writer_unlock(e->scheduler);
+  return result;
+}
+
+int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, 
+			  uint32_t action,
+			  ...)
+{
+  int result;
+  va_list va;
+  
+  if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
+    result = -EINVAL;
+    goto out;
+  }
+  
+  va_start(va, action);
+  result = labcomm_writer_ioctl(encoder->writer, 
+			       encoder->writer->action_context,
+			       0, NULL, action, va);
+  va_end(va);
+
+out:
+  return result;
+}
+
+int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
+				   struct labcomm_signature *signature,
+				   uint32_t action, va_list va)
+{
+  int result = -ENOTSUP;
+  int index;
+
+  index = labcomm_get_local_index(signature);
+  result = labcomm_writer_ioctl(encoder->writer, 
+				encoder->writer->action_context, 
+				index, signature, action, va);
+  return result;
+}
diff --git a/lib/c/2006/labcomm2006_error.c b/lib/c/2006/labcomm2006_error.c
new file mode 100644
index 0000000000000000000000000000000000000000..278c5f3549f4df229bba97cde7fa08bd89e12ea3
--- /dev/null
+++ b/lib/c/2006/labcomm2006_error.c
@@ -0,0 +1,32 @@
+/*
+  labcomm_error.c -- labcomm error handling
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "labcomm_error.h"
+ 
+void labcomm_error_fatal_global(enum labcomm_error error,
+				char *format,
+				...)
+{
+  fprintf(stderr, "Fatal error %d\n", error);
+  exit(1);
+}
diff --git a/lib/c/2006/labcomm2006_error.h b/lib/c/2006/labcomm2006_error.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd124c96fe80b4bec7c95d8e087fa89d052424be
--- /dev/null
+++ b/lib/c/2006/labcomm2006_error.h
@@ -0,0 +1,68 @@
+/*
+  labcomm_error.h -- labcomm error declarations
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LABCOMM_ERROR_H__
+#define __LABCOMM_ERROR_H__
+
+enum labcomm_error {
+#define LABCOMM_ERROR(name, description) name ,
+#include "labcomm_error.h"
+#undef LABCOMM_ERROR
+};
+
+struct labcomm_error_handler;
+
+void labcomm_error_warning(struct labcomm_error_handler *e,
+			   enum labcomm_error,
+			   char *format,
+			   ...);
+			 
+void labcomm_error_fatal_global(enum labcomm_error error,
+				char *format,
+				...);
+			 
+#endif
+
+#ifdef LABCOMM_ERROR
+
+LABCOMM_ERROR(LABCOMM_ERROR_SIGNATURE_ALREADY_SET, 
+	      "Signature has already been set")
+LABCOMM_ERROR(LABCOMM_ERROR_SIGNATURE_NOT_SET, 
+	      "Signature has not been set")
+
+LABCOMM_ERROR(LABCOMM_ERROR_ENC_NO_REG_SIGNATURE, 
+	      "Encoder has no registration for this signature")
+LABCOMM_ERROR(LABCOMM_ERROR_ENC_BUF_FULL,
+	      "The labcomm buffer is full")
+LABCOMM_ERROR(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE,
+	      "Decoder: Unknown datatype")
+LABCOMM_ERROR(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 
+	      "Decoder: index mismatch")
+LABCOMM_ERROR(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND,
+	      "Decoder: type not found")
+LABCOMM_ERROR(LABCOMM_ERROR_UNIMPLEMENTED_FUNC,
+	      "This function is not yet implemented")
+LABCOMM_ERROR(LABCOMM_ERROR_MEMORY,
+	      "Could not allocate memory")
+LABCOMM_ERROR(LABCOMM_ERROR_USER_DEF,     
+	      "User defined error")
+
+#endif
diff --git a/lib/c/2006/labcomm2006_fd_reader.c b/lib/c/2006/labcomm2006_fd_reader.c
new file mode 100644
index 0000000000000000000000000000000000000000..e397c84401a27a59aec74da39e37cedbf111e7f5
--- /dev/null
+++ b/lib/c/2006/labcomm2006_fd_reader.c
@@ -0,0 +1,141 @@
+/*
+  labcomm_fd_reader.c -- LabComm reader for Unix file descriptors.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "labcomm_private.h"
+#include "labcomm_fd_reader.h"
+
+#define BUFFER_SIZE 2048
+
+struct labcomm_fd_reader {
+  struct labcomm_reader reader;
+  struct labcomm_reader_action_context action_context;
+  int fd;
+  int close_fd_on_free;
+};
+
+static int fd_alloc(struct labcomm_reader *r,
+		    struct labcomm_reader_action_context *action_context, 
+		    char *version)
+{
+  int result = 0;
+  
+  r->count = 0;
+  r->pos = 0;
+  r->data = labcomm_memory_alloc(r->memory, 0, BUFFER_SIZE);
+  if (! r->data) {
+    r->data_size = 0;
+    result = -ENOMEM;
+  } else {
+
+    r->data_size = BUFFER_SIZE;
+    result = r->data_size;
+    if (version && version[0]) {
+      char *tmp;
+      
+      tmp = labcomm_read_string(r);
+      if (strcmp(tmp, version) != 0) {
+	result = -EINVAL;
+      } else {
+	result = r->data_size;
+      }
+      labcomm_memory_free(r->memory, 1, tmp);
+    }
+  }
+  return result;
+}
+
+static int fd_free(struct labcomm_reader *r, 
+		   struct labcomm_reader_action_context *action_context)
+{
+  struct labcomm_fd_reader *fd_reader = action_context->context;
+  struct labcomm_memory *memory = r->memory;
+
+  labcomm_memory_free(memory, 0, r->data);
+  r->data = 0;
+  r->data_size = 0;
+  r->count = 0;
+  r->pos = 0;
+
+  if (fd_reader->close_fd_on_free) {
+    close(fd_reader->fd);
+  }
+  labcomm_memory_free(memory, 0, fd_reader);
+
+  return 0;
+}
+
+static int fd_fill(struct labcomm_reader *r, 
+		   struct labcomm_reader_action_context *action_context)
+{
+  int result = 0;
+  struct labcomm_fd_reader *fd_reader = action_context->context;
+
+  if (r->pos < r->count) {
+    result = r->count - r->pos;
+  } else {
+    int err;
+    
+    r->pos = 0;
+    err = read(fd_reader->fd, r->data, r->data_size);
+    if (err <= 0) {
+      r->count = 0;
+      r->error = -EPIPE;
+      result = -EPIPE;
+    } else {
+      r->count = err;
+      result = r->count - r->pos;
+    }
+  }
+  return result;
+}
+
+static const struct labcomm_reader_action action = {
+  .alloc = fd_alloc,
+  .free = fd_free,
+  .start = NULL,
+  .fill = fd_fill,
+  .end = NULL,
+  .ioctl = NULL
+};
+
+struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free)
+{
+  struct labcomm_fd_reader *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
+  if (result == NULL) {
+    return NULL;
+  } else {
+    result->action_context.next = NULL;
+    result->action_context.action = &action;
+    result->action_context.context = result;
+    result->reader.action_context = &result->action_context;
+    result->reader.memory = memory;
+    result->fd = fd;
+    result->close_fd_on_free = close_fd_on_free;
+    return &result->reader;
+  }
+}
diff --git a/lib/c/2006/labcomm2006_fd_reader.h b/lib/c/2006/labcomm2006_fd_reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..b04aa8ed5515ccb5caf3571fd05adf0fdfc294f0
--- /dev/null
+++ b/lib/c/2006/labcomm2006_fd_reader.h
@@ -0,0 +1,31 @@
+/*
+  labcomm_fd_reader.c -- a reader for unix style file-descriptors
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_FD_READER_H_
+#define _LABCOMM_FD_READER_H_
+
+#include "labcomm.h"
+
+struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free);
+
+#endif
+
diff --git a/lib/c/2006/labcomm2006_fd_writer.c b/lib/c/2006/labcomm2006_fd_writer.c
new file mode 100644
index 0000000000000000000000000000000000000000..acf6934ad7c50eec43dba087b8d863e045ac4703
--- /dev/null
+++ b/lib/c/2006/labcomm2006_fd_writer.c
@@ -0,0 +1,147 @@
+/*
+  labcomm_fd_writer.c -- LabComm writer for Unix file descriptors.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "labcomm_private.h"
+#include "labcomm_fd_writer.h"
+
+#define BUFFER_SIZE 2048
+
+struct labcomm_fd_writer {
+  struct labcomm_writer writer;
+  struct labcomm_writer_action_context action_context;
+  int fd;
+  int close_fd_on_free;
+};
+
+static int fd_flush(struct labcomm_writer *w, 
+		    struct labcomm_writer_action_context *action_context);
+
+static int fd_alloc(struct labcomm_writer *w, 
+		    struct labcomm_writer_action_context *action_context, 
+		    char *version)
+{
+  w->data = labcomm_memory_alloc(w->memory, 0, BUFFER_SIZE);
+  if (! w->data) {
+    w->error = -ENOMEM;
+    w->data_size = 0;
+    w->count = 0;
+    w->pos = 0;
+  } else {
+    w->data_size = BUFFER_SIZE;
+    w->count = BUFFER_SIZE;
+    w->pos = 0;
+    if (version && version[0]) {
+      labcomm_write_string(w, version);
+      fd_flush(w, action_context);
+    }
+  }
+
+  return w->error;
+}
+
+static int fd_free(struct labcomm_writer *w, 
+		   struct labcomm_writer_action_context *action_context)
+{
+  struct labcomm_fd_writer *fd_writer = action_context->context;
+  struct labcomm_memory *memory = w->memory;
+
+  labcomm_memory_free(memory, 0, w->data);
+  w->data = 0;
+  w->data_size = 0;
+  w->count = 0;
+  w->pos = 0;
+
+  if (fd_writer->close_fd_on_free) {
+    close(fd_writer->fd);
+  }
+  labcomm_memory_free(memory, 0, fd_writer);
+  return 0;
+}
+
+static int fd_start(struct labcomm_writer *w, 
+		    struct labcomm_writer_action_context *action_context,
+		    int index,
+		    struct labcomm_signature *signature,
+		    void *value)
+{
+  w->pos = 0;
+  
+  return w->error;
+}
+
+static int fd_flush(struct labcomm_writer *w, 
+		    struct labcomm_writer_action_context *action_context)
+{
+  struct labcomm_fd_writer *fd_context = action_context->context;
+  int start, err;
+  
+  start = 0;
+  err = 0;
+  while (start < w->pos) {
+    err = write(fd_context->fd, &w->data[start], w->pos - start);
+    if (err <= 0) {
+      break;
+    }
+    start = start + err;
+  }
+  if (err < 0) {
+    w->error = -errno;
+  } else if (err == 0) {
+    w->error = -EINVAL;
+  }
+  w->pos = 0;
+   
+  return w->error;
+}
+
+static const struct labcomm_writer_action action = {
+  .alloc = fd_alloc,
+  .free = fd_free,
+  .start = fd_start,
+  .end = fd_flush,
+  .flush = fd_flush,
+  .ioctl = NULL
+};
+
+struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory,
+					     int fd, int close_fd_on_free)
+{
+  struct labcomm_fd_writer *result;
+
+  result = labcomm_memory_alloc(memory, 0, sizeof(*result));
+  if (result == NULL) {
+    return NULL;
+  } else {
+    result->action_context.next = NULL;
+    result->action_context.action = &action;
+    result->action_context.context = result;
+    result->writer.action_context = &result->action_context;
+    result->writer.memory = memory;
+    result->fd = fd;
+    result->close_fd_on_free = close_fd_on_free;
+    return &result->writer;
+  }
+}
diff --git a/lib/c/2006/labcomm2006_fd_writer.h b/lib/c/2006/labcomm2006_fd_writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..e89b5e7198c1d7822f276d23801baf9a889ce4f2
--- /dev/null
+++ b/lib/c/2006/labcomm2006_fd_writer.h
@@ -0,0 +1,31 @@
+/*
+  labcomm_fd_writer.c -- a writer for unix style file-descriptors
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_FD_WRITER_H_
+#define _LABCOMM_FD_WRITER_H_
+
+#include "labcomm.h"
+
+struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory,
+					     int fd, int close_on_free);
+
+#endif
+
diff --git a/lib/c/2006/labcomm2006_ioctl.h b/lib/c/2006/labcomm2006_ioctl.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ebf6531d4000ebfb2392a547eaf1f2a1f589b80
--- /dev/null
+++ b/lib/c/2006/labcomm2006_ioctl.h
@@ -0,0 +1,110 @@
+/*
+  labcomm_ioctl.h -- labcomm ioctl declarations
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LABCOMM_IOCTL_H__
+#define __LABCOMM_IOCTL_H__
+
+#include "labcomm.h"
+
+/*
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |   |                         |               |               |  
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  | |   |                         |               |
+ *  | |   |                         |               +- number    (8)
+ *  | |   |                         +----------------- type      (8)
+ *  | |   +------------------------------------------- size      (13)
+ *  | +----------------------------------------------- direction (2)
+ *  +------------------------------------------------- signature (1)
+ *  
+ * type 0-31     are reserved for labcomm library use
+ */
+
+
+#define LABCOMM_IOC_NRBITS      8
+#define LABCOMM_IOC_TYPEBITS    8
+#define LABCOMM_IOC_SIZEBITS   13
+#define LABCOMM_IOC_DIRBITS     2
+#define LABCOMM_IOC_SIGBITS     1
+#define LABCOMM_IOC_NRMASK     ((1 << LABCOMM_IOC_NRBITS)-1)
+#define LABCOMM_IOC_TYPEMASK   ((1 << LABCOMM_IOC_TYPEBITS)-1)
+#define LABCOMM_IOC_SIZEMASK   ((1 << LABCOMM_IOC_SIZEBITS)-1)
+#define LABCOMM_IOC_DIRMASK    ((1 << LABCOMM_IOC_DIRBITS)-1)
+#define LABCOMM_IOC_SIGMASK    ((1 << LABCOMM_IOC_SIGBITS)-1)
+#define LABCOMM_IOC_NRSHIFT    0
+#define LABCOMM_IOC_TYPESHIFT  (LABCOMM_IOC_NRSHIFT+LABCOMM_IOC_NRBITS)
+#define LABCOMM_IOC_SIZESHIFT  (LABCOMM_IOC_TYPESHIFT+LABCOMM_IOC_TYPEBITS)
+#define LABCOMM_IOC_DIRSHIFT   (LABCOMM_IOC_SIZESHIFT+LABCOMM_IOC_SIZEBITS)
+#define LABCOMM_IOC_SIGSHIFT   (LABCOMM_IOC_DIRSHIFT+LABCOMM_IOC_DIRBITS)
+
+#define LABCOMM_IOC_NOSIG       0U
+#define LABCOMM_IOC_USESIG      1U
+
+#define LABCOMM_IOC_NONE        0U
+#define LABCOMM_IOC_WRITE       1U
+#define LABCOMM_IOC_READ        2U
+
+#define LABCOMM_IOC(signature,dir,type,nr,size)	  \
+  (((signature) << LABCOMM_IOC_SIGSHIFT) |	  \
+   ((dir)       << LABCOMM_IOC_DIRSHIFT) |	  \
+   ((size)      << LABCOMM_IOC_SIZESHIFT) |	  \
+   ((type)      << LABCOMM_IOC_TYPESHIFT) |	  \
+   ((nr)        << LABCOMM_IOC_NRSHIFT))	  
+
+#define LABCOMM_IOC_SIG(nr) \
+  (((nr) >> LABCOMM_IOC_SIGSHIFT) & LABCOMM_IOC_SIGMASK)
+#define LABCOMM_IOC_DIR(nr) \
+  (((nr) >> LABCOMM_IOC_DIRSHIFT) & LABCOMM_IOC_DIRMASK)
+#define LABCOMM_IOC_SIZE(nr) \
+  (((nr) >> LABCOMM_IOC_SIZESHIFT) & LABCOMM_IOC_SIZEMASK)
+#define LABCOMM_IOC_TYPE(nr) \
+  (((nr) >> LABCOMM_IOC_TYPESHIFT) & LABCOMM_IOC_TYPEMASK)
+#define LABCOMM_IOC_NR(nr) \
+  (((nr) >> LABCOMM_IOC_NRSHIFT) & LABCOMM_IOC_NRMASK)
+
+#define LABCOMM_IO(type,nr)						\
+  LABCOMM_IOC(LABCOMM_IOC_NOSIG,LABCOMM_IOC_NONE,type,nr,0)
+#define LABCOMM_IOR(type,nr,size)					\
+  LABCOMM_IOC(LABCOMM_IOC_NOSIG,LABCOMM_IOC_READ,type,nr,sizeof(size))
+/* FIXME: add flag to differentiate between size and nargs */
+#define LABCOMM_IORN(type,nr,nargs)					\
+  LABCOMM_IOC(LABCOMM_IOC_NOSIG,LABCOMM_IOC_READ,type,nr,nargs)
+#define LABCOMM_IOW(type,nr,size)					\
+  LABCOMM_IOC(LABCOMM_IOC_NOSIG,LABCOMM_IOC_WRITE,type,nr,sizeof(size))
+#define LABCOMM_IOWN(type,nr,nargs)					\
+  LABCOMM_IOC(LABCOMM_IOC_NOSIG,LABCOMM_IOC_WRITE,type,nr,nargs)
+#define LABCOMM_IOS(type,nr)					\
+  LABCOMM_IOC(LABCOMM_IOC_USESIG,LABCOMM_IOC_READ,type,nr,0)
+#define LABCOMM_IOSR(type,nr,size)					\
+  LABCOMM_IOC(LABCOMM_IOC_USESIG,LABCOMM_IOC_READ,type,nr,sizeof(size))
+#define LABCOMM_IOSRN(type,nr,nargs)					\
+  LABCOMM_IOC(LABCOMM_IOC_USESIG,LABCOMM_IOC_READ,type,nr,nargs)
+#define LABCOMM_IOSW(type,nr,size)					\
+  LABCOMM_IOC(LABCOMM_IOC_USESIG,LABCOMM_IOC_WRITE,type,nr,sizeof(size))
+#define LABCOMM_IOSWN(type,nr,nargs)					\
+  LABCOMM_IOC(LABCOMM_IOC_USESIG,LABCOMM_IOC_WRITE,type,nr,nargs)
+
+#define LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN \
+  LABCOMM_IOR(0,1,int)
+#define LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER \
+  LABCOMM_IOR(0,2,void*)
+
+#endif
diff --git a/lib/c/2006/labcomm2006_memory.c b/lib/c/2006/labcomm2006_memory.c
new file mode 100644
index 0000000000000000000000000000000000000000..62bc9ac5a3f81ef496f836509cf4e7f8e8bb81cf
--- /dev/null
+++ b/lib/c/2006/labcomm2006_memory.c
@@ -0,0 +1,40 @@
+/*
+  labcomm_memory.c -- dynamic memory handlig dispatcher
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "labcomm_private.h"
+
+void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, 
+			   size_t size) 
+{
+  return m->alloc(m, lifetime, size);
+}
+
+void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, 
+			     void *ptr, size_t size) 
+{
+  return m->realloc(m, lifetime, ptr, size);
+}
+
+void labcomm_memory_free(struct labcomm_memory *m, int lifetime, 
+			 void *ptr)
+{
+  m->free(m, lifetime, ptr);
+}
diff --git a/lib/c/2006/labcomm2006_private.h b/lib/c/2006/labcomm2006_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6db4c155f375c28b856e3c4eeaef3e150894f8c
--- /dev/null
+++ b/lib/c/2006/labcomm2006_private.h
@@ -0,0 +1,522 @@
+/*
+  labcomm_private.h -- semi private declarations for handling encoding and 
+                       decoding of labcomm samples.
+
+  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_PRIVATE_H_
+#define _LABCOMM_PRIVATE_H_
+
+#ifdef LABCOMM_COMPAT
+  #include LABCOMM_COMPAT
+#else
+  #include <endian.h>
+  #include <stdio.h>
+#endif
+
+#include <stdint.h>
+//#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "labcomm.h"
+
+/*
+ * Predeclared aggregate type indices
+ */
+#define LABCOMM_TYPEDEF  0x01
+#define LABCOMM_SAMPLE   0x02
+#define LABCOMM_ARRAY    0x10
+#define LABCOMM_STRUCT   0x11
+
+/*
+ * Predeclared primitive type indices
+ */
+#define LABCOMM_BOOLEAN  0x20 
+#define LABCOMM_BYTE     0x21
+#define LABCOMM_SHORT    0x22
+#define LABCOMM_INT      0x23
+#define LABCOMM_LONG     0x24
+#define LABCOMM_FLOAT    0x25
+#define LABCOMM_DOUBLE   0x26
+#define LABCOMM_STRING   0x27
+
+/*
+ * Start index for user defined types
+ */
+#define LABCOMM_USER     0x80
+
+/*
+ * Macro to automagically call constructors in modules compiled 
+ * with the labcomm compiler. If __attribute__((constructor)) is
+ * not supported, these calls has to be done first in main program.
+ */
+#ifndef LABCOMM_CONSTRUCTOR
+#define LABCOMM_CONSTRUCTOR __attribute__((constructor))
+#endif
+
+/*
+ * Semi private dynamic memory declarations
+ */
+
+struct labcomm_memory {
+  void *(*alloc)(struct labcomm_memory *m, int lifetime, size_t size);
+  void *(*realloc)(struct labcomm_memory *m, int lifetime, 
+		   void *ptr, size_t size);
+  void (*free)(struct labcomm_memory *m, int lifetime, void *ptr);
+  void *context;
+};
+
+/*
+ * Semi private decoder declarations
+ */
+typedef void (*labcomm_handler_function)(void *value, void *context);
+
+typedef void (*labcomm_decoder_function)(
+  struct labcomm_reader *r,
+  labcomm_handler_function handler,
+  void *context);
+
+struct labcomm_reader_action_context;
+
+struct labcomm_reader_action {
+  /* 'alloc' is called at the first invocation of 'labcomm_decoder_decode_one' 
+     on the decoder containing the reader. If 'labcomm_version' != NULL
+     and non-empty the transport layer may use it to ensure that
+     compatible versions are used.
+
+     Returned value:
+       >  0    Number of bytes allocated for buffering
+       <= 0    Error
+  */
+  int (*alloc)(struct labcomm_reader *r, 
+	       struct labcomm_reader_action_context *action_context, 
+	       char *labcomm_version);
+  /* 'free' returns the resources claimed by 'alloc' and might have other
+     reader specific side-effects as well.
+
+     Returned value:
+       == 0    Success
+       != 0    Error
+  */
+  int (*free)(struct labcomm_reader *r, 
+	      struct labcomm_reader_action_context *action_context);
+  /* 'start' is called at the following instances:
+     1. When a sample is registered 
+          (local_index != 0, remote_index == 0, value == NULL)
+     2. When a sample definition is received 
+          (local_index != 0, remote_index != 0, value == NULL)
+     3. When a sample is received
+          (local_index != 0, remote_index != 0, value != NULL)
+   */
+  int (*start)(struct labcomm_reader *r, 
+	       struct labcomm_reader_action_context *action_context,
+	       int local_index, int remote_index,
+	       struct labcomm_signature *signature,
+	       void *value);
+  int (*end)(struct labcomm_reader *r, 
+	     struct labcomm_reader_action_context *action_context);
+  int (*fill)(struct labcomm_reader *r, 
+	      struct labcomm_reader_action_context *action_context);
+  int (*ioctl)(struct labcomm_reader *r, 
+	       struct labcomm_reader_action_context *action_context,
+	       int local_index, int remote_index,
+	       struct labcomm_signature *signature, 
+	       uint32_t ioctl_action, va_list args);
+};
+
+struct labcomm_reader_action_context {
+  struct labcomm_reader_action_context *next;
+  const struct labcomm_reader_action *action;
+  void *context;  
+};
+
+struct labcomm_reader {
+  struct labcomm_reader_action_context *action_context;
+  struct labcomm_memory *memory;
+  /* The following fields are initialized by labcomm_decoder_new */
+  struct labcomm_decoder *decoder;
+  unsigned char *data;
+  int data_size;
+  int count;
+  int pos;
+  int error;
+};
+
+int labcomm_reader_alloc(struct labcomm_reader *r, 
+			 struct labcomm_reader_action_context *action_context, 
+			 char *labcomm_version);
+int labcomm_reader_free(struct labcomm_reader *r, 
+			struct labcomm_reader_action_context *action_context);
+int labcomm_reader_start(struct labcomm_reader *r, 
+			 struct labcomm_reader_action_context *action_context,
+			 int local_index, int remote_index,
+			 struct labcomm_signature *signature,
+			 void *value);
+int labcomm_reader_end(struct labcomm_reader *r, 
+		       struct labcomm_reader_action_context *action_context);
+int labcomm_reader_fill(struct labcomm_reader *r, 
+			struct labcomm_reader_action_context *action_context);
+int labcomm_reader_ioctl(struct labcomm_reader *r, 
+			 struct labcomm_reader_action_context *action_context,
+			 int local_index, int remote_index,
+			 struct labcomm_signature *signature, 
+			 uint32_t ioctl_action, va_list args);
+
+/*
+ * Non typesafe registration function to be called from
+ * generated labcomm_decoder_register_* functions.
+ */
+int labcomm_internal_decoder_register(
+  struct labcomm_decoder *d, 
+  struct labcomm_signature *s, 
+  labcomm_decoder_function decoder,
+  labcomm_handler_function handler,
+  void *context);
+
+int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, 
+				   struct labcomm_signature *signature,
+				   uint32_t ioctl_action, va_list args);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define LABCOMM_DECODE(name, type)					\
+  static inline type labcomm_read_##name(struct labcomm_reader *r) {	\
+    type result; int i;							\
+    for (i = sizeof(type) - 1 ; i >= 0 ; i--) {				\
+      if (r->pos >= r->count) {						\
+	labcomm_reader_fill(r, r->action_context);			\
+	if (r->error < 0) {						\
+	  return 0;							\
+	}								\
+      }									\
+      ((unsigned char*)(&result))[i] = r->data[r->pos];			\
+      r->pos++;								\
+    }									\
+    return result;							\
+  }
+
+#else
+
+#define LABCOMM_DECODE(name, type)					\
+  static inline type labcomm_read_##name(struct labcomm_reader *r) {	\
+    type result; int i;							\
+    for (i = 0 ; i < sizeof(type) ; i++) {				\
+      if (r->pos >= r->count) {						\
+	labcomm_reader_fille(r, r->action_context);			\
+	if (r->error < 0) {						\
+	  return 0;							\
+	}								\
+      }									\
+      ((unsigned char*)(&result))[i] = r->data[r->pos];			\
+      r->pos++;								\
+    }									\
+    return result;							\
+  }
+
+#endif
+
+LABCOMM_DECODE(boolean, unsigned char)
+LABCOMM_DECODE(byte, unsigned char)
+LABCOMM_DECODE(short, short)
+LABCOMM_DECODE(int, int)
+LABCOMM_DECODE(long, long long)
+LABCOMM_DECODE(float, float)
+LABCOMM_DECODE(double, double)
+
+//compatibility with 2013 version
+#define labcomm_read_packed32 labcomm_read_int
+
+#if 0
+static inline unsigned int labcomm_read_packed32(struct labcomm_reader *r)
+{
+  unsigned int result = 0;
+  
+  while (1) {
+    unsigned char tmp;
+
+    if (r->pos >= r->count) {	
+      labcomm_reader_fill(r, r->action_context);
+      if (r->error != 0) {
+	goto out;
+      }
+    }
+    tmp = r->data[r->pos];
+    r->pos++;
+    result = (result << 7) | (tmp & 0x7f);
+    if ((tmp & 0x80) == 0) { 
+      break; 
+    }
+  }
+out:
+  return result;
+}
+#endif 
+
+static inline char *labcomm_read_string(struct labcomm_reader *r)
+{
+  char *result = NULL;
+  int length, pos; 
+  
+  length = labcomm_read_packed32(r);
+  result = labcomm_memory_alloc(r->memory, 1, length + 1);
+  for (pos = 0 ; pos < length ; pos++) {
+    if (r->pos >= r->count) {	
+      labcomm_reader_fill(r, r->action_context);
+      if (r->error < 0) {
+	goto out;
+      }
+    }
+    result[pos] = r->data[r->pos];
+    r->pos++;
+  }
+out:
+  result[pos] = 0;
+  return result;
+}
+
+/*
+ * Semi private encoder declarations
+ */
+typedef int (*labcomm_encoder_function)(struct labcomm_writer *,
+					void *value);
+struct labcomm_writer_action_context;
+
+struct labcomm_writer_action {
+  int (*alloc)(struct labcomm_writer *w, 
+	       struct labcomm_writer_action_context *action_context, 
+	       char *labcomm_version);
+  int (*free)(struct labcomm_writer *w, 
+	      struct labcomm_writer_action_context *action_context);
+  /* 'start' is called right before a sample is to be sent. In the 
+     case of a sample or typedef, 'value' == NULL.
+
+     Returned value:
+       == 0          Success -> continue sending the sample
+       == -EALREADY  Success -> silently skip sending the sample,
+                                'end' will not be called
+       < 0           Error
+   */
+  int (*start)(struct labcomm_writer *w, 
+	       struct labcomm_writer_action_context *action_context,
+	       int index, struct labcomm_signature *signature,
+	       void *value);
+  int (*end)(struct labcomm_writer *w, 
+	     struct labcomm_writer_action_context *action_context);
+  int (*flush)(struct labcomm_writer *w, 
+	       struct labcomm_writer_action_context *action_context); 
+  int (*ioctl)(struct labcomm_writer *w, 
+	       struct labcomm_writer_action_context *action_context, 
+	       int index, struct labcomm_signature *signature, 
+	       uint32_t ioctl_action, va_list args);
+};
+
+struct labcomm_writer_action_context {
+  struct labcomm_writer_action_context *next;
+  const struct labcomm_writer_action *action;
+  void *context;  
+};
+
+struct labcomm_writer {
+  struct labcomm_writer_action_context *action_context;
+  struct labcomm_memory *memory;
+  /* The following fields are initialized by labcomm_encoder_new */
+  struct labcomm_encoder *encoder;
+  unsigned char *data;
+  int data_size;
+  int count;
+  int pos;
+  int error;
+};
+
+int labcomm_writer_alloc(struct labcomm_writer *w, 
+			 struct labcomm_writer_action_context *action_context, 
+			 char *labcomm_version);
+int labcomm_writer_free(struct labcomm_writer *w, 
+			struct labcomm_writer_action_context *action_context);
+int labcomm_writer_start(struct labcomm_writer *w, 
+			 struct labcomm_writer_action_context *action_context,
+			 int index, struct labcomm_signature *signature,
+			 void *value);
+int labcomm_writer_end(struct labcomm_writer *w, 
+		       struct labcomm_writer_action_context *action_context);
+int labcomm_writer_flush(struct labcomm_writer *w, 
+			 struct labcomm_writer_action_context *action_context); 
+int labcomm_writer_ioctl(struct labcomm_writer *w, 
+			 struct labcomm_writer_action_context *action_context, 
+			 int index, struct labcomm_signature *signature, 
+			 uint32_t ioctl_action, va_list args);
+
+int labcomm_internal_encoder_register(
+  struct labcomm_encoder *encoder, 
+  struct labcomm_signature *signature, 
+  labcomm_encoder_function encode);
+
+int labcomm_internal_encode(
+  struct labcomm_encoder *encoder, 
+  struct labcomm_signature *signature, 
+  labcomm_encoder_function encode,
+  void *value);
+
+int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
+				   struct labcomm_signature *signature,
+				   uint32_t ioctl_action, va_list args);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define LABCOMM_ENCODE(name, type)					\
+  static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
+    int i;								\
+    for (i = sizeof(type) - 1 ; i >= 0 ; i--) {				\
+      if (w->pos >= w->count) { /*buffer is full*/			\
+        int err;							\
+	err = labcomm_writer_flush(w, w->action_context);		\
+	if (err != 0) { return err; }					\
+      }									\
+      w->data[w->pos] = ((unsigned char*)(&data))[i];			\
+      w->pos++;								\
+    }									\
+    return 0;								\
+  }
+
+#else
+
+#define LABCOMM_ENCODE(name, type)					\
+  static inline int labcomm_write_##name(struct labcomm_writer *w, type data) { \
+    int i;								\
+    for (i = 0 ; i < sizeof(type) ; i++) {				\
+      if (w->pos >= w->count) {						\
+        int err;							\
+	err = labcomm_writer_flush(w, w->action_context);		\
+	if (err != 0) { return err; }					\
+      }									\
+      w->data[w->pos] = ((unsigned char*)(&data))[i];			\
+      w->pos++;								\
+    }									\
+    return 0;								\
+  }
+
+#endif
+
+LABCOMM_ENCODE(boolean, unsigned char)
+LABCOMM_ENCODE(byte, unsigned char)
+LABCOMM_ENCODE(short, short)
+LABCOMM_ENCODE(int, int)
+LABCOMM_ENCODE(long, long long)
+LABCOMM_ENCODE(float, float)
+LABCOMM_ENCODE(double, double)
+
+#define labcomm_write_packed32 labcomm_write_int
+
+#if 0
+static inline int labcomm_write_packed32(struct labcomm_writer *w, 
+					 unsigned int data)
+{
+  unsigned char tmp[5];
+  int i;
+  
+  for (i = 0 ; i == 0 || data ; i++, data = (data >> 7)) {
+    tmp[i] = data & 0x7f;
+  }
+  for (i = i - 1 ; i >= 0 ; i--) {
+    if (w->pos >= w->count) {					
+      int err;
+      err = labcomm_writer_flush(w, w->action_context);	
+      if (err != 0) { return err; }
+    }
+    w->data[w->pos++] = tmp[i] | (i?0x80:0x00);
+  }
+  return 0;
+}
+#endif
+
+static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
+{
+  int length, i, err; 
+
+  length = strlen((char*)s);
+  err = labcomm_write_packed32(w, length);
+  if (err != 0) { return err; }
+  for (i = 0 ; i < length ; i++) {
+    if (w->pos >= w->count) {	
+      int err;
+      err = labcomm_writer_flush(w, w->action_context);	
+      if (err != 0) { return err; }
+    }
+    w->data[w->pos] = s[i];
+    w->pos++;
+  }
+  return 0;
+}
+
+/* Size of packed32 variable is 4 as we use int*/
+static inline int labcomm_size_packed32(unsigned int data)
+{
+  return 4;
+}
+
+/*
+ * Macros for handling arrays indexed by signature index
+ */
+
+#define LABCOMM_SIGNATURE_ARRAY_DEF(name, kind)	\
+  struct {					\
+    int first;					\
+    int last;					\
+    kind *data;					\
+  } name
+
+#define LABCOMM_SIGNATURE_ARRAY_DEF_INIT(name, kind)		\
+  LABCOMM_SIGNATURE_ARRAY_DEF(name, kind) = { 0, 0, NULL }
+
+#define LABCOMM_SIGNATURE_ARRAY_INIT(name, kind)		\
+  name.first = 0; name.last = 0; name.data = NULL;		\
+  name.data = (kind *)name.data; /* typechecking no-op */
+
+#define LABCOMM_SIGNATURE_ARRAY_FREE(memory, name, kind)	\
+  if (name.data) { labcomm_memory_free(memory, 0, name.data); }	\
+  name.data = (kind *)NULL; /* typechecking */
+
+void *labcomm_signature_array_ref(struct labcomm_memory * memory,
+				  int *first, int *last, void **data,
+				  int size, int index);
+/*
+ * NB: the pointer returned by LABCOMM_SIGNATURE_ARRAY_REF might be
+ *     rendered invalid by a subsequent call to LABCOMM_SIGNATURE_ARRAY_REF
+ *     on the same SIGNATURE_ARRAY, so make sure not to use the result if 
+ *     any other code might have made a call to LABCOMM_SIGNATURE_ARRAY_REF
+ *     on the same SIGNATURE_ARRAY.
+ */
+#define LABCOMM_SIGNATURE_ARRAY_REF(memory, name, kind, index)		\
+  (name.data = (kind *)name.data, /* typechecking no-op */		\
+   (kind *)(labcomm_signature_array_ref(memory,				\
+					&name.first, &name.last,	\
+					(void **)&name.data,		\
+					sizeof(kind), index)))
+
+#define LABCOMM_SIGNATURE_ARRAY_FOREACH(name, kind, var)		\
+  for (name.data = (kind *)name.data, /* typechecking no-op */		\
+       var = name.first ; var < name.last ; var++)
+
+/* Give signature a free local index, this may not be used concurrently */
+void labcomm_set_local_index(struct labcomm_signature *signature);
+
+/* Get the local index for a signature */
+int labcomm_get_local_index(struct labcomm_signature *s);
+
+#endif
diff --git a/lib/c/2006/labcomm2006_pthread_scheduler.c b/lib/c/2006/labcomm2006_pthread_scheduler.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9b516a3b41af1ccfada40a9da50958299758a6e
--- /dev/null
+++ b/lib/c/2006/labcomm2006_pthread_scheduler.c
@@ -0,0 +1,394 @@
+/*
+  labcomm_pthread_scheduler.c -- labcomm pthread based task coordination
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#define _POSIX_C_SOURCE (200112L)
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include "labcomm.h"
+#include "labcomm_scheduler.h"
+#include "labcomm_scheduler_private.h"
+#include "labcomm_pthread_scheduler.h"
+
+#ifdef LABCOMM_COMPAT
+  #include LABCOMM_COMPAT
+#endif 
+
+struct pthread_time {
+  struct labcomm_time time;
+  struct labcomm_memory *memory;
+  struct timespec abstime;
+};
+
+struct pthread_deferred {
+  struct pthread_deferred *next;
+  struct pthread_deferred *prev;
+  struct timespec when;
+  void (*action)(void *context);
+  void *context;
+};
+
+struct pthread_scheduler {
+  struct labcomm_scheduler scheduler;
+  struct labcomm_memory *memory;
+  int wakeup;
+  pthread_mutex_t writer_mutex;
+  pthread_mutex_t data_mutex;
+  pthread_cond_t data_cond;
+  int running_deferred;
+  struct pthread_deferred deferred;
+  struct pthread_deferred deferred_with_delay;
+};
+
+static struct labcomm_time_action time_action;
+
+static int queue_empty(struct pthread_deferred *queue)
+{
+  return queue->next == queue;
+}
+
+static void timespec_add_usec(struct timespec *t, uint32_t usec)
+{
+  time_t sec = usec / 1000000;
+  long nsec = (usec % 1000000) * 1000;
+  
+  t->tv_nsec += nsec;
+  t->tv_sec += sec + t->tv_nsec / 1000000000;
+  t->tv_nsec %= 1000000000;
+}
+
+static int timespec_compare(struct timespec *t1, struct timespec *t2)
+{
+  if (t1->tv_sec == t2->tv_sec && t1->tv_nsec == t2->tv_nsec) {
+    return 0;
+  } else if (t1->tv_sec == 0 && t1->tv_nsec == 0) {
+    /* t1 is at end of time */
+    return 1;
+  } else  if (t2->tv_sec == 0 && t2->tv_nsec == 0) {
+    /* t2 is at end of time */
+    return -1;
+  } else if (t1->tv_sec < t2->tv_sec) {
+    return -1;
+  } else if (t1->tv_sec == t2->tv_sec) {
+    if (t1->tv_nsec < t2->tv_nsec) {
+      return -1;
+    } else if (t1->tv_nsec == t2->tv_nsec) {
+      return 0;
+    } else {
+      return 1;
+    }
+  } else {
+    return 1;
+  }
+}
+
+static struct labcomm_time *time_new(struct labcomm_memory *memory)
+{
+  struct pthread_time *time;
+
+  time = labcomm_memory_alloc(memory, 0, sizeof(*time));
+  if (time == NULL) {
+    return NULL;
+  } else {
+    time->time.action = &time_action;
+    time->time.context = time;
+    time->memory = memory;
+    clock_gettime(CLOCK_REALTIME, &time->abstime);
+    return &time->time;
+  }
+}
+
+static int time_free(struct labcomm_time *t)
+{
+  struct pthread_time *time = t->context;
+  struct labcomm_memory *memory = time->memory;
+  
+  labcomm_memory_free(memory, 0, time);
+  
+  return 0;
+}
+ 
+static int time_add_usec(struct labcomm_time *t, uint32_t usec)
+{
+  struct pthread_time *time = t->context;
+
+  timespec_add_usec(&time->abstime, usec);
+
+  return 0;
+}
+
+static struct labcomm_time_action time_action = {
+  .free = time_free,
+  .add_usec = time_add_usec
+};
+
+static int run_action(struct pthread_scheduler *scheduler,
+		      struct pthread_deferred *element)
+{
+  /* Called with data_lock held */
+  element->prev->next = element->next;
+  element->next->prev = element->prev;
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+  element->action(element->context);
+  labcomm_memory_free(scheduler->memory, 1, element);
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  return 0;
+}
+
+static int run_deferred(struct pthread_scheduler *scheduler)
+{
+  /* Called with data_lock held */
+  if (scheduler->running_deferred) { goto out; }
+  scheduler->running_deferred = 1;
+  while (!queue_empty(&scheduler->deferred)) {
+    run_action(scheduler, scheduler->deferred.next);
+  }
+  if (!queue_empty(&scheduler->deferred_with_delay)) {
+    struct timespec now;
+
+    clock_gettime(CLOCK_REALTIME, &now);
+    while (timespec_compare(&scheduler->deferred_with_delay.next->when,
+			    &now) <= 0) {
+      run_action(scheduler, scheduler->deferred_with_delay.next);
+    }
+  }
+  scheduler->running_deferred = 0;
+out:
+  return 0;
+}
+
+static int scheduler_free(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+  struct labcomm_memory *memory = scheduler->memory;
+  
+  labcomm_memory_free(memory, 0, scheduler);
+
+  return 0;
+}
+ 
+static int scheduler_writer_lock(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  run_deferred(scheduler);  /* Run deferred tasks before taking lock */
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+  if (pthread_mutex_lock(&scheduler->writer_mutex) != 0) {
+    return -errno;
+  }
+  return 0;
+}
+ 
+static int scheduler_writer_unlock(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  if (pthread_mutex_unlock(&scheduler->writer_mutex) != 0) {
+    return -errno;
+  }
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  run_deferred(scheduler);  /* Run deferred tasks after releasing lock */
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+  
+  return 0;
+}
+
+static int scheduler_data_lock(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  if (pthread_mutex_lock(&scheduler->data_mutex) != 0) {
+    perror("Failed to lock data_mutex");
+    exit(1);
+  }
+  return 0;
+}
+ 
+static int scheduler_data_unlock(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  if (pthread_mutex_unlock(&scheduler->data_mutex) != 0) {
+    perror("Failed to unlock data_mutex");
+    exit(1);
+  }
+  
+  return 0;
+}
+
+static struct labcomm_time *scheduler_now(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  return time_new(scheduler->memory);
+}
+ 
+static int scheduler_sleep(struct labcomm_scheduler *s,
+			   struct labcomm_time *t)
+{
+  struct pthread_scheduler *scheduler = s->context;
+  struct pthread_time *time = t?t->context:NULL;
+
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  while (1) {
+    struct timespec *wakeup, now;
+
+    /* Run deferred tasks before sleeping */
+    run_deferred(scheduler);
+    
+    clock_gettime(CLOCK_REALTIME, &now);
+    if (scheduler->wakeup ||
+	(time && timespec_compare(&time->abstime, &now) <= 0)) {
+      /* Done waiting */
+      scheduler->wakeup = 0;
+      break;
+    }
+    wakeup = NULL;
+    if (!queue_empty(&scheduler->deferred_with_delay)) {
+      wakeup = &scheduler->deferred_with_delay.next->when;
+      if (time && timespec_compare(&time->abstime, wakeup) < 0) {
+	wakeup = &time->abstime;
+      }
+    } else if (time) {
+      wakeup = &time->abstime;
+    }
+ 
+    if (wakeup) {
+      pthread_cond_timedwait(&scheduler->data_cond, 
+			     &scheduler->data_mutex, 
+			     wakeup);
+    } else {
+      pthread_cond_wait(&scheduler->data_cond, 
+			&scheduler->data_mutex);
+    }
+  }
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+  
+  return 0;
+}
+
+static int scheduler_wakeup(struct labcomm_scheduler *s)
+{
+  struct pthread_scheduler *scheduler = s->context;
+
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  scheduler->wakeup = 1;
+  pthread_cond_signal(&scheduler->data_cond);
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+  return 0;
+}
+
+static int scheduler_enqueue(struct labcomm_scheduler *s,
+			     uint32_t delay,
+			     void (*deferred)(void *context),
+			     void *context)
+{
+  struct pthread_scheduler *scheduler = s->context;
+  int result = 0;
+  struct pthread_deferred *element, *insert_before;
+
+  element = labcomm_memory_alloc(scheduler->memory, 1, sizeof(*element));
+  if (element == NULL) {
+    result = -ENOMEM;
+    goto out;
+  }
+  
+  element->action = deferred;
+  element->context = context;
+  labcomm_scheduler_data_lock(&scheduler->scheduler);
+  if (delay == 0) {
+    insert_before = &scheduler->deferred;
+  } else {
+    clock_gettime(CLOCK_REALTIME, &element->when);
+    timespec_add_usec(&element->when, delay);
+    for (insert_before = scheduler->deferred_with_delay.next ; 
+	 timespec_compare(&element->when, &insert_before->when) >= 0 ;
+	 insert_before = insert_before->next) {
+    }
+  }
+  element->next = insert_before;
+  element->prev = insert_before->prev;
+  element->prev->next = element;
+  element->next->prev = element;
+  pthread_cond_signal(&scheduler->data_cond);
+  labcomm_scheduler_data_unlock(&scheduler->scheduler);
+
+out:
+  return result;
+}
+
+static const struct labcomm_scheduler_action scheduler_action = {
+  .free = scheduler_free,
+  .writer_lock = scheduler_writer_lock,
+  .writer_unlock = scheduler_writer_unlock,
+  .data_lock = scheduler_data_lock,
+  .data_unlock = scheduler_data_unlock,
+  .now = scheduler_now,
+  .sleep = scheduler_sleep,
+  .wakeup = scheduler_wakeup,
+  .enqueue = scheduler_enqueue  
+};
+
+struct labcomm_scheduler *labcomm_pthread_scheduler_new(
+  struct labcomm_memory *memory)
+{
+  struct labcomm_scheduler *result = NULL;
+  struct pthread_scheduler *scheduler;
+
+  scheduler = labcomm_memory_alloc(memory, 0, sizeof(*scheduler));
+  if (scheduler == NULL) {
+    goto out;
+  } else {
+    scheduler->scheduler.action = &scheduler_action;
+    scheduler->scheduler.context = scheduler;
+    scheduler->wakeup = 0;
+    scheduler->memory = memory;
+    if (pthread_mutex_init(&scheduler->writer_mutex, NULL) != 0) {
+      goto free_scheduler;
+    }
+     if (pthread_mutex_init(&scheduler->data_mutex, NULL) != 0) {
+       goto destroy_writer_mutex;
+    }
+    if (pthread_cond_init(&scheduler->data_cond, NULL) != 0) {
+      goto destroy_data_mutex;
+    }
+    scheduler->running_deferred = 0;
+    scheduler->deferred.next = &scheduler->deferred;
+    scheduler->deferred.prev = &scheduler->deferred;
+    scheduler->deferred_with_delay.next = &scheduler->deferred_with_delay;
+    scheduler->deferred_with_delay.prev = &scheduler->deferred_with_delay;
+    scheduler->deferred_with_delay.when.tv_sec = 0;
+    scheduler->deferred_with_delay.when.tv_nsec = 0;
+    result = &scheduler->scheduler;
+    goto out;
+  }
+destroy_data_mutex:
+  pthread_mutex_destroy(&scheduler->data_mutex);
+destroy_writer_mutex:
+  pthread_mutex_destroy(&scheduler->writer_mutex);
+free_scheduler:
+  labcomm_memory_free(memory, 0, scheduler);
+out:
+  return result;
+  
+}
+
diff --git a/lib/c/2006/labcomm2006_pthread_scheduler.h b/lib/c/2006/labcomm2006_pthread_scheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8b20eca176925a9ba4468967ca6225f5d6ab806
--- /dev/null
+++ b/lib/c/2006/labcomm2006_pthread_scheduler.h
@@ -0,0 +1,31 @@
+/*
+  labcomm_pthread_scheduler.h -- labcomm pthread based task coordination
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_PTHREAD_SCHEDULER_H_
+#define _LABCOMM_PTHREAD_SCHEDULER_H_
+
+#include "labcomm.h"
+
+struct labcomm_scheduler *labcomm_pthread_scheduler_new(
+  struct labcomm_memory *memory);
+
+#endif
+
diff --git a/lib/c/2006/labcomm2006_scheduler.c b/lib/c/2006/labcomm2006_scheduler.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ef62f3b54e076f0dbf726acd4421dddec71fb42
--- /dev/null
+++ b/lib/c/2006/labcomm2006_scheduler.c
@@ -0,0 +1,85 @@
+/*
+  labcomm_scheduler.c -- labcomm task coordination
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include "labcomm_scheduler_private.h"
+
+#define SCHEDULER_scheduler(scheduler, ...) scheduler
+#define SCHEDULER(func, ...)						\
+  if (SCHEDULER_scheduler(__VA_ARGS__) &&				\
+      SCHEDULER_scheduler(__VA_ARGS__)->action->func) {			\
+    return SCHEDULER_scheduler(__VA_ARGS__)->action->func(__VA_ARGS__);	\
+  }									\
+  return -ENOSYS;
+
+int labcomm_scheduler_free(struct labcomm_scheduler *s)
+{
+  SCHEDULER(free, s);
+}
+
+int labcomm_scheduler_writer_lock(struct labcomm_scheduler *s)
+{
+  SCHEDULER(writer_lock, s);
+}
+
+int labcomm_scheduler_writer_unlock(struct labcomm_scheduler *s)
+{
+  SCHEDULER(writer_unlock, s);
+}
+
+int labcomm_scheduler_data_lock(struct labcomm_scheduler *s)
+{
+  SCHEDULER(data_lock, s);
+}
+
+int labcomm_scheduler_data_unlock(struct labcomm_scheduler *s)
+{
+  SCHEDULER(data_unlock, s);
+}
+
+struct labcomm_time *labcomm_scheduler_now(struct labcomm_scheduler *s)
+{
+  if (s && s->action->now) {
+    return s->action->now(s); 
+  } 
+  return NULL;
+}
+
+int labcomm_scheduler_sleep(struct labcomm_scheduler *s,
+			    struct labcomm_time *wakeup)
+{
+  SCHEDULER(sleep, s, wakeup);
+}
+
+int labcomm_scheduler_wakeup(struct labcomm_scheduler *s)
+{
+  SCHEDULER(wakeup, s);
+}
+
+int labcomm_scheduler_enqueue(struct labcomm_scheduler *s,
+			      uint32_t delay,
+			      void (*func)(void *context),
+			      void *context)
+{
+  SCHEDULER(enqueue, s, delay, func, context);
+}
+
+
diff --git a/lib/c/2006/labcomm2006_scheduler.h b/lib/c/2006/labcomm2006_scheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..4aef48daf6c734cafdb25780a43954d0340beb71
--- /dev/null
+++ b/lib/c/2006/labcomm2006_scheduler.h
@@ -0,0 +1,56 @@
+/*
+  labcomm_scheduler.h -- labcomm task coordination
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_SCHEDULER_H_
+#define _LABCOMM_SCHEDULER_H_
+
+#include <unistd.h>
+#include <stdint.h>
+
+struct labcomm_time;
+
+int labcomm_time_free(struct labcomm_time *t);
+int labcomm_time_add_usec(struct labcomm_time *t, uint32_t usec);
+
+struct labcomm_scheduler;
+
+int labcomm_scheduler_free(struct labcomm_scheduler *s);
+
+/* Lock and event handling */
+int labcomm_scheduler_writer_lock(struct labcomm_scheduler *s);
+int labcomm_scheduler_writer_unlock(struct labcomm_scheduler *s);
+int labcomm_scheduler_data_lock(struct labcomm_scheduler *s);
+int labcomm_scheduler_data_unlock(struct labcomm_scheduler *s);
+
+/* Time handling */
+struct labcomm_time *labcomm_scheduler_now(struct labcomm_scheduler *s);
+int labcomm_scheduler_sleep(struct labcomm_scheduler *s,
+			    struct labcomm_time *wakeup);
+int labcomm_scheduler_wakeup(struct labcomm_scheduler *s);
+
+/* Deferred action handling */
+int labcomm_scheduler_enqueue(struct labcomm_scheduler *s,
+			      uint32_t delay,
+			      void (*deferred)(void *context),
+			      void *context);
+
+#endif
+
diff --git a/lib/c/2006/labcomm2006_scheduler_private.h b/lib/c/2006/labcomm2006_scheduler_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc4d50e40c518eb7c43b928918e1f568a8301065
--- /dev/null
+++ b/lib/c/2006/labcomm2006_scheduler_private.h
@@ -0,0 +1,55 @@
+/*
+  labcomm_scheduler.h -- labcomm task coordination, semi-private part
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LABCOMM_SCHEDULER_PRIVATE_H_
+#define _LABCOMM_SCHEDULER_PRIVATE_H_
+
+#include <unistd.h>
+#include "labcomm_scheduler.h"
+
+struct labcomm_time {
+  const struct labcomm_time_action {
+    int (*free)(struct labcomm_time *t);
+    int (*add_usec)(struct labcomm_time *t, uint32_t usec);
+  } *action;
+  void *context;
+};
+
+struct labcomm_scheduler {
+  const struct labcomm_scheduler_action {
+    int (*free)(struct labcomm_scheduler *s);
+    int (*writer_lock)(struct labcomm_scheduler *s);
+    int (*writer_unlock)(struct labcomm_scheduler *s);
+    int (*data_lock)(struct labcomm_scheduler *s);
+    int (*data_unlock)(struct labcomm_scheduler *s);
+    struct labcomm_time *(*now)(struct labcomm_scheduler *s);
+    int (*sleep)(struct labcomm_scheduler *s,
+		 struct labcomm_time *wakeup);
+    int (*wakeup)(struct labcomm_scheduler *s);
+    int (*enqueue)(struct labcomm_scheduler *s,
+		   uint32_t delay,
+		   void (*deferred)(void *context),
+		   void *context);
+  } *action;
+  void *context;
+};
+
+#endif
diff --git a/lib/c/2006/labcomm2006_time.c b/lib/c/2006/labcomm2006_time.c
new file mode 100644
index 0000000000000000000000000000000000000000..a1a5235199aa31c1c315d19343f1e7d33963f2fd
--- /dev/null
+++ b/lib/c/2006/labcomm2006_time.c
@@ -0,0 +1,42 @@
+/*
+  labcomm_time.c -- labcomm time handling
+
+  Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
+
+  This file is part of LabComm.
+
+  LabComm is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LabComm is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include "labcomm_scheduler_private.h"
+
+#define TIME_time(time, ...) time
+#define TIME(func, ...)						\
+  if (TIME_time(__VA_ARGS__) &&				\
+      TIME_time(__VA_ARGS__)->action->func) {			\
+    return TIME_time(__VA_ARGS__)->action->func(__VA_ARGS__);	\
+  }									\
+  return -ENOSYS;
+
+int labcomm_time_free(struct labcomm_time *s)
+{
+  TIME(free, s);
+}
+
+int labcomm_time_add_usec(struct labcomm_time *s, uint32_t usec)
+{
+  TIME(add_usec, s, usec);
+}
+