diff --git a/Makefile b/Makefile
index 0c509fa409e91cb77992e6fb5c1501accfa54c83..acf30dc1c502706a173b38430864690dd7b1d2a6 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,4 @@ clean:
 build/libmoberg.so: build/lib/moberg_config.o
 build/libmoberg.so: build/lib/moberg_device.o
 build/libmoberg.so: build/lib/moberg_parser.o
-build/lib/moberg_device.o: moberg_device.h
-build/parse_config.o: moberg_parser.h
-parse_config: build/moberg_driver.o
-parse_config: build/parse_config.o
+build/lib/%.o: %.h
diff --git a/moberg.c b/moberg.c
index fc44eee38b7f6d14fb404421566e90f095150fea..0f4972e80ef1c4ab452d0f2c45a734cdaab5b7dd 100644
--- a/moberg.c
+++ b/moberg.c
@@ -43,7 +43,7 @@ static void parse_config_at(
             buf[statbuf.st_size] = 0;
           }
           printf("Parsing... %s %d %d\n", pathname, dirfd, fd);
-          struct moberg_config *config = moberg_config_parse(buf);
+          struct moberg_config *config = moberg_parse(buf);
           printf("-> %p\n", config);
           if (config) {
             if (! moberg->config) {
@@ -88,39 +88,49 @@ static void parse_config_dir_at(
   
 }
 
+static int install_config(struct moberg *moberg)
+{
+  return 1;
+}
+
 struct moberg *moberg_new(
   struct moberg_config *config)
 {
   struct moberg *result = malloc(sizeof(*result));
   if (! result) {
     fprintf(stderr, "Failed to allocate moberg struct\n");
+    goto err;
+  }
+  if (config) {
+    result->config = config;
   } else {
     result->config = NULL;
-    if (! config) {
-      /* Parse default configuration(s) */
-      const char * const *config_paths = xdgSearchableConfigDirectories(NULL);
-      const char * const *path;
-      for (path = config_paths ; *path ; path++) {
-        int dirfd1 = open(*path, O_DIRECTORY);
-        if (dirfd >= 0) {
-          parse_config_at(result, dirfd1, "moberg.conf");
-          int dirfd2 = openat(dirfd1, "moberg.d", O_DIRECTORY);
-          if (dirfd2 >= 0) { 
-            parse_config_dir_at(result, dirfd2);
-            parse_config_dir_at(result, dirfd2);
-            close(dirfd2);
-          }
-          close(dirfd1);
+    
+    /* Parse default configuration(s) */
+    const char * const *config_paths = xdgSearchableConfigDirectories(NULL);
+    const char * const *path;
+    for (path = config_paths ; *path ; path++) {
+      int dirfd1 = open(*path, O_DIRECTORY);
+      if (dirfd >= 0) {
+        parse_config_at(result, dirfd1, "moberg.conf");
+        int dirfd2 = openat(dirfd1, "moberg.d", O_DIRECTORY);
+        if (dirfd2 >= 0) { 
+          parse_config_dir_at(result, dirfd2);
+          parse_config_dir_at(result, dirfd2);
+          close(dirfd2);
         }
-        free((char*)*path);
+        close(dirfd1);
       }
-      free((const char **)config_paths);
-
-      /* Read environment default */
-      /* Parse environment overrides */
+      free((char*)*path);
     }
+    free((const char **)config_paths);
+    
+    /* Read environment default */
+    /* Parse environment overrides */
   }
+  install_config(result);
   
+err:
   return result;
 }
 
diff --git a/moberg_config.c b/moberg_config.c
index b9f4e1ce51a7c951e2686231eb07eecaf590431d..9a98854d8e91c16291365b7f1e31cd04078ff856 100644
--- a/moberg_config.c
+++ b/moberg_config.c
@@ -37,13 +37,53 @@ struct moberg_config
       struct moberg_device_analog_in *channel;
     } *value;
   } analog_in;
+  struct  {
+    int capacity;
+    struct analog_out_entry {
+      struct moberg_device* device;
+      struct moberg_device_analog_out *channel;
+    } *value;
+  } analog_out;
+  struct  {
+    int capacity;
+    struct digital_in_entry {
+      struct moberg_device* device;
+      struct moberg_device_digital_in *channel;
+    } *value;
+  } digital_in;
+  struct  {
+    int capacity;
+    struct digital_out_entry {
+      struct moberg_device* device;
+      struct moberg_device_digital_out *channel;
+    } *value;
+  } digital_out;
+  struct  {
+    int capacity;
+    struct encoder_in_entry {
+      struct moberg_device* device;
+      struct moberg_device_encoder_in *channel;
+    } *value;
+  } encoder_in;
 };
 
 struct moberg_config *moberg_config_new()
 {
   struct moberg_config *result = malloc(sizeof *result);
 
-  result->device = NULL;
+  if (result) {
+    result->device = NULL;
+    result->analog_in.capacity = 0;
+    result->analog_in.value = NULL;
+    result->analog_out.capacity = 0;
+    result->analog_out.value = NULL;
+    result->digital_in.capacity = 0;
+    result->digital_in.value = NULL;
+    result->digital_out.capacity = 0;
+    result->digital_out.value = NULL;
+    result->encoder_in.capacity = 0;
+    result->encoder_in.value = NULL;
+  }
   
   return result;
 }
@@ -57,6 +97,11 @@ void moberg_config_free(struct moberg_config *config)
     moberg_device_free(tmp->device);
     free(tmp);
   }
+  free(config->analog_in.value);
+  free(config->analog_out.value);
+  free(config->digital_in.value);
+  free(config->digital_out.value);
+  free(config->encoder_in.value);
   free(config);
 }
 
@@ -97,3 +142,51 @@ err:
   return 0;
 }
                             
+int moberg_config_add_analog_out(struct moberg_config *config,
+                                 int index,
+                                 struct moberg_device* device,
+                                 struct moberg_device_analog_out *channel)
+{
+  struct analog_out_entry e = { device, channel };
+  LIST_SET(config->analog_out, index, e, goto err);
+  return 1;
+err:
+  return 0;
+}
+                            
+int moberg_config_add_digital_in(struct moberg_config *config,
+                                int index,
+                                struct moberg_device* device,
+                                struct moberg_device_digital_in *channel)
+{
+  struct digital_in_entry e = { device, channel };
+  LIST_SET(config->digital_in, index, e, goto err);
+  return 1;
+err:
+  return 0;
+}
+                            
+int moberg_config_add_digital_out(struct moberg_config *config,
+                                 int index,
+                                 struct moberg_device* device,
+                                 struct moberg_device_digital_out *channel)
+{
+  struct digital_out_entry e = { device, channel };
+  LIST_SET(config->digital_out, index, e, goto err);
+  return 1;
+err:
+  return 0;
+}
+                            
+int moberg_config_add_encoder_in(struct moberg_config *config,
+                                int index,
+                                struct moberg_device* device,
+                                struct moberg_device_encoder_in *channel)
+{
+  struct encoder_in_entry e = { device, channel };
+  LIST_SET(config->encoder_in, index, e, goto err);
+  return 1;
+err:
+  return 0;
+}
+                            
diff --git a/moberg_device.c b/moberg_device.c
index aff00c58e9d40c039df0bade9bb3e1e716a5b26b..1ead53911e1399be0cca6b5ac2b890e2ddc9a6e1 100644
--- a/moberg_device.c
+++ b/moberg_device.c
@@ -8,8 +8,25 @@
 struct moberg_device {
   void *driver_handle;
   struct moberg_device_driver driver;
-  struct moberg_device_config *config;
-  struct moberg_device_map_range *range;
+  struct moberg_device_config *device_config;
+  struct channel_list {
+    struct channel_list *next;
+    enum moberg_channel_kind kind;
+    int index;
+    union channel {
+      struct moberg_device_analog_in *analog_in;
+      struct moberg_device_analog_out *analog_out;
+      struct moberg_device_digital_in *digital_in;
+      struct moberg_device_digital_out *digital_out;
+      struct moberg_device_encoder_in *encoder_in;
+    } u;
+  } *channel_head, **channel_tail;
+  struct map_range {
+    struct moberg_config *config;
+    enum moberg_channel_kind kind;
+    int min;
+    int max;
+  } *range;
 };
 
 struct moberg_device *moberg_device_new(const char *driver)
@@ -37,7 +54,11 @@ struct moberg_device *moberg_device_new(const char *driver)
   }
   result->driver_handle = handle;
   result->driver = *device_driver;
-  result->config = NULL;
+  result->device_config = NULL;
+  result->channel_head = NULL;
+  result->channel_tail = &result->channel_head;
+  result->range = NULL;
+  
   goto free_name;
   
 dlclose_driver:
@@ -50,8 +71,16 @@ out:
 
 void moberg_device_free(struct moberg_device *device)
 {
-  device->driver.config_free(device->config);
-  free(device->config);
+  struct channel_list *channel = device->channel_head;
+  while (channel) {
+    struct channel_list *next;
+    next = channel->next;
+    free(channel);
+    channel = next;
+  }
+  device->driver.config_free(device->device_config);
+  free(device->device_config);
+  dlclose(device->driver_handle);
   free(device);
 }
 
@@ -64,90 +93,125 @@ int moberg_device_parse_config(struct moberg_device *device,
 int moberg_device_set_config(struct moberg_device *device,
                              struct moberg_device_config *config)
 {
-  if (device->config) {
-    device->driver.config_free(device->config);
-    free(device->config);
+  if (device->device_config) {
+    device->driver.config_free(device->device_config);
+    free(device->device_config);
   }
-  device->config = config;
+  device->device_config = config;
   return 1;
 }
 
 int moberg_device_parse_map(struct moberg_device* device,
+                            struct moberg_config *config,
                             struct moberg_parser_context *context,
-                            struct moberg_device_map_range range)
+                            enum moberg_channel_kind kind,
+                            int min,
+                            int max)
 {
   int result;
-  struct moberg_device_map_range r = range;
+  struct map_range r = {
+    .config=config,
+    .kind=kind,
+    .min=min,
+    .max=max
+  };
   device->range = &r;
-  result = device->driver.parse_map(device, context, range.kind);
+  result = device->driver.parse_map(device, context, kind);
   device->range = NULL;
   printf("RRR %d %d\n", r.min, r.max);
   return result;
 }
 
+static int add_channel(struct moberg_device* device,
+                       enum moberg_channel_kind kind,
+                       int index,
+                       union channel channel)
+{
+  struct channel_list *element = malloc(sizeof(*element));
+  if (! element) { goto err; }
+  element->next = NULL;
+  element->kind = kind;
+  element->index = index;
+  element->u = channel;
+  *device->channel_tail = element;
+  device->channel_tail = &element->next;
+  return 1;
+err:
+  return 0;
+}
+
 int moberg_device_add_analog_in(struct moberg_device* device,
                                 struct moberg_device_analog_in *channel)
 {
-  if (device->range->kind == map_analog_in &&
+  int result = 0;
+  
+  if (device->range->kind == chan_ANALOGIN &&
       device->range->min <= device->range->max) {
     printf("Mapping %d\n", device->range->min);
-    // moberg_config_add_analog_in()
+    result = add_channel(device, device->range->kind, device->range->min,
+                         (union channel) { .analog_in=channel });
     device->range->min++;
-    return 1;
-  } else {
-    return 0;
   }
+  return result;
 }
                             
 int moberg_device_add_analog_out(struct moberg_device* device,
                                  struct moberg_device_analog_out *channel)
 {
-  if (device->range->kind == map_analog_out &&
+  int result = 0;
+  
+  if (device->range->kind == chan_ANALOGOUT &&
       device->range->min <= device->range->max) {
     printf("Mapping %d\n", device->range->min);
+    result = add_channel(device, device->range->kind, device->range->min,
+                         (union channel) { .analog_out=channel });
     device->range->min++;
-    return 1;
-  } else {
-    return 0;
   }
+  return result;
 }
                             
 int moberg_device_add_digital_in(struct moberg_device* device,
-                                 struct moberg_device_digital_in *channel)
+                                struct moberg_device_digital_in *channel)
 {
-  if (device->range->kind == map_digital_in &&
+  int result = 0;
+  
+  if (device->range->kind == chan_DIGITALIN &&
       device->range->min <= device->range->max) {
     printf("Mapping %d\n", device->range->min);
+    result = add_channel(device, device->range->kind, device->range->min,
+                         (union channel) { .digital_in=channel });
     device->range->min++;
-    return 1;
-  } else {
-    return 0;
   }
+  return result;
 }
                             
 int moberg_device_add_digital_out(struct moberg_device* device,
-                                  struct moberg_device_digital_out *channel)
+                                 struct moberg_device_digital_out *channel)
 {
-  if (device->range->kind == map_digital_out &&
+  int result = 0;
+  
+  if (device->range->kind == chan_DIGITALOUT &&
       device->range->min <= device->range->max) {
     printf("Mapping %d\n", device->range->min);
+    result = add_channel(device, device->range->kind, device->range->min,
+                         (union channel) { .digital_out=channel });
     device->range->min++;
-    return 1;
-  } else {
-    return 0;
   }
+  return result;
 }
                             
 int moberg_device_add_encoder_in(struct moberg_device* device,
-                                 struct moberg_device_encoder_in *channel)
+                                struct moberg_device_encoder_in *channel)
 {
-  if (device->range->kind == map_encoder_in &&
+  int result = 0;
+  
+  if (device->range->kind == chan_ENCODERIN &&
       device->range->min <= device->range->max) {
     printf("Mapping %d\n", device->range->min);
+    result = add_channel(device, device->range->kind, device->range->min,
+                         (union channel) { .encoder_in=channel });
     device->range->min++;
-    return 1;
-  } else {
-    return 0;
   }
+  return result;
 }
-
+                            
diff --git a/moberg_device.h b/moberg_device.h
index 1aeb7fa646372f0bf2e90b23aa5d0a1508cee224..5fd0710da24b845a2c66ff9d6dbbbd266aab3fcc 100644
--- a/moberg_device.h
+++ b/moberg_device.h
@@ -4,16 +4,12 @@
 #include <moberg_config.h>
 #include <moberg_parser.h>
 
-struct moberg_device_map_range {
-  enum moberg_device_map_kind {
-    map_analog_in,
-    map_analog_out,
-    map_digital_in,
-    map_digital_out,
-    map_encoder_in
-  } kind;
-  int min;
-  int max;
+enum moberg_channel_kind {
+    chan_ANALOGIN,
+    chan_ANALOGOUT,
+    chan_DIGITALIN,
+    chan_DIGITALOUT,
+    chan_ENCODERIN
 };
 
 struct moberg_device_analog_in {
@@ -62,7 +58,7 @@ struct moberg_device_driver {
   int (*parse_map)(
     struct moberg_device* device,
     struct moberg_parser_context *context,
-    enum moberg_device_map_kind kind);
+    enum moberg_channel_kind kind);
   int (*config_free)(
     struct moberg_device_config *config);
 };
@@ -80,8 +76,11 @@ int moberg_device_set_config(struct moberg_device* device,
                              struct moberg_device_config *config);
 
 int moberg_device_parse_map(struct moberg_device* device,
+                            struct moberg_config *config,
                             struct moberg_parser_context *context,
-                            struct moberg_device_map_range range);
+                            enum moberg_channel_kind kind,
+                            int min,
+                            int max);
 
 int moberg_device_add_analog_in(struct moberg_device* device,
                                 struct moberg_device_analog_in *channel);
diff --git a/moberg_parser.c b/moberg_parser.c
index 7a46d9dbd2628d8992151702cd8f39dab042bcca..da0c64600ef7d81e9029d25d19e1ee441a267f6a 100644
--- a/moberg_parser.c
+++ b/moberg_parser.c
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <moberg_config.h>
 #include <moberg_parser.h>
 #include <moberg_module.h>
 #include <moberg_device.h>
@@ -288,23 +289,24 @@ void moberg_parser_failed(
 
 
 static int parse_map_range(context_t *c,
-                           struct moberg_device_map_range *range)
+                           int *min,
+                           int *max)
 {
-  token_t min, max;
+  token_t tok_min, tok_max;
   if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; }
-  if (! acceptsym(c, tok_INTEGER, &min)) { goto syntax_err; }
+  if (! acceptsym(c, tok_INTEGER, &tok_min)) { goto syntax_err; }
   if (acceptsym(c, tok_COLON, NULL)) {
-    if (! acceptsym(c, tok_INTEGER, &max)) { goto syntax_err; }
+    if (! acceptsym(c, tok_INTEGER, &tok_max)) { goto syntax_err; }
   } else {
-    max = min;
+    tok_max = tok_min;
   }
   if (! acceptsym(c, tok_RBRACKET, NULL)) { goto syntax_err; }
-  if (! range) {
-    fprintf(stderr, "Range is NULL\n");
+  if (! min && max) {
+    fprintf(stderr, "Min or max is NULL\n");
     goto err;
   }
-  range->min = min.u.integer.value;
-  range->max = max.u.integer.value;
+  *min = tok_min.u.integer.value;
+  *max = tok_max.u.integer.value;
   return 1;
 syntax_err:
   moberg_parser_failed(c, stderr);
@@ -315,17 +317,20 @@ err:
 static int parse_map(context_t *c,
                      struct moberg_device *device)
 {
-  struct moberg_device_map_range range;
+  enum moberg_channel_kind kind;
+  int min, max;
   
-  if (acceptkeyword(c, "analog_in")) { range.kind = map_analog_in; }
-  else if (acceptkeyword(c, "analog_out")) { range.kind = map_analog_out; }
-  else if (acceptkeyword(c, "digital_in")) { range.kind = map_digital_in; }
-  else if (acceptkeyword(c, "digital_out")) { range.kind = map_digital_out; }
-  else if (acceptkeyword(c, "encoder_in")) { range.kind = map_encoder_in; }
+  if (acceptkeyword(c, "analog_in")) { kind = chan_ANALOGIN; }
+  else if (acceptkeyword(c, "analog_out")) { kind = chan_ANALOGOUT; }
+  else if (acceptkeyword(c, "digital_in")) { kind = chan_DIGITALIN; }
+  else if (acceptkeyword(c, "digital_out")) { kind = chan_DIGITALOUT; }
+  else if (acceptkeyword(c, "encoder_in")) { kind = chan_ENCODERIN; }
   else { goto syntax_err; }
-  if (! parse_map_range(c, &range)) { goto syntax_err; }
+  if (! parse_map_range(c, &min, &max)) { goto syntax_err; }
   if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
-  if (! moberg_device_parse_map(device, c, range)) { goto err; }
+  if (! moberg_device_parse_map(device, c->config, c, kind, min, max)) {
+    goto err;
+  }
   if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
   return 1;
 syntax_err:
@@ -341,11 +346,6 @@ static int parse_device(context_t *c,
   for (;;) {
     if (acceptkeyword(c, "config")) {
      moberg_device_parse_config(device, c);
-/*      
-      void *config = driver->module.parse_config(c);
-      result->add_config(config);
-      free(config);
-*/
     } else if (acceptkeyword(c, "map")) {
       if (! parse_map(c, device)) { goto err; }
     } else if (acceptsym(c, tok_RBRACE, NULL)) {
@@ -403,7 +403,7 @@ err:
   return 0;
 }
 
-struct moberg_config *moberg_config_parse(const char *buf)
+struct moberg_config *moberg_parse(const char *buf)
 {
   context_t context;
 
diff --git a/moberg_parser.h b/moberg_parser.h
index 1d8148c8dce42ca3c3ca76a9f1de910b07a51cf4..6bfcebe5a7ea53494d055e8440f85757b5158eca 100644
--- a/moberg_parser.h
+++ b/moberg_parser.h
@@ -5,6 +5,6 @@
 
 struct moberg_parser_context;
 
-struct moberg_config *moberg_config_parse(const char *buf);
+struct moberg_config *moberg_parse(const char *buf);
 
 #endif
diff --git a/modules/comedi/comedi.c b/modules/comedi/comedi.c
index ccf738c89415c16c56df50401a358acab45d88aa..4c078e6bda4a794c3999f4383cdfa2ce5d9314d0 100644
--- a/modules/comedi/comedi.c
+++ b/modules/comedi/comedi.c
@@ -90,7 +90,7 @@ err:
 static int parse_map(
   struct moberg_device *device,
   struct moberg_parser_context *c,
-  enum moberg_device_map_kind kind)
+  enum moberg_channel_kind kind)
 {
   token_t min, max;
 
@@ -114,19 +114,19 @@ static int parse_map(
     }
     for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) {
       switch (kind) {
-        case map_analog_in:
+        case chan_ANALOGIN:
           moberg_device_add_analog_in(device, NULL);
           break;
-        case map_analog_out:
+        case chan_ANALOGOUT:
           moberg_device_add_analog_out(device, NULL);
           break;
-        case map_digital_in:
+        case chan_DIGITALIN:
           moberg_device_add_digital_in(device, NULL);
           break;
-        case map_digital_out:
+        case chan_DIGITALOUT:
           moberg_device_add_digital_out(device, NULL);
           break;
-        case map_encoder_in:
+        case chan_ENCODERIN:
           moberg_device_add_encoder_in(device, NULL);
           break;
       }
diff --git a/modules/serial2002/serial2002.c b/modules/serial2002/serial2002.c
index f89a5b8120117ace2c5ced879c2cefa7fe64e450..0c3448d94dd1aa52601b8a0521e72549146c90e7 100644
--- a/modules/serial2002/serial2002.c
+++ b/modules/serial2002/serial2002.c
@@ -69,16 +69,16 @@ err:
 static int parse_map(
   struct moberg_device *device,
   struct moberg_parser_context *c,
-  enum moberg_device_map_kind ignore)
+  enum moberg_channel_kind ignore)
 {
-  enum moberg_device_map_kind kind;
+  enum moberg_channel_kind kind;
   token_t min, max;
  
-  if (acceptkeyword(c, "analog_in")) { kind = map_analog_in; }
-  else if (acceptkeyword(c, "analog_out")) { kind = map_analog_out; }
-  else if (acceptkeyword(c, "digital_in")) { kind = map_digital_in; }
-  else if (acceptkeyword(c, "digital_out")) { kind = map_digital_out; }
-  else if (acceptkeyword(c, "encoder_in")) { kind = map_encoder_in; }
+  if (acceptkeyword(c, "analog_in")) { kind = chan_ANALOGIN; }
+  else if (acceptkeyword(c, "analog_out")) { kind = chan_ANALOGOUT; }
+  else if (acceptkeyword(c, "digital_in")) { kind = chan_DIGITALIN; }
+  else if (acceptkeyword(c, "digital_out")) { kind = chan_DIGITALOUT; }
+  else if (acceptkeyword(c, "encoder_in")) { kind = chan_ENCODERIN; }
   else { goto syntax_err; }
   if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; }
   if (! acceptsym(c, tok_INTEGER, &min)) { goto syntax_err; }
@@ -90,19 +90,19 @@ static int parse_map(
   if (! acceptsym(c, tok_RBRACKET, NULL)) { goto syntax_err; }
   for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) {
     switch (kind) {
-      case map_analog_in:
+      case chan_ANALOGIN:
         moberg_device_add_analog_in(device, NULL);
         break;
-      case map_analog_out:
+      case chan_ANALOGOUT:
         moberg_device_add_analog_out(device, NULL);
         break;
-      case map_digital_in:
+      case chan_DIGITALIN:
         moberg_device_add_digital_in(device, NULL);
         break;
-      case map_digital_out:
+      case chan_DIGITALOUT:
         moberg_device_add_digital_out(device, NULL);
         break;
-      case map_encoder_in:
+      case chan_ENCODERIN:
         moberg_device_add_encoder_in(device, NULL);
         break;
     }