Commit 25d5b846 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Use-counts in place

parent b7839ae1
......@@ -3,7 +3,8 @@ CCFLAGS+=-Wall -Werror -I$(shell pwd) -g
LDFLAGS+=-L$(shell pwd)/build/ -lmoberg
MODULES:=$(wildcard modules/*)
export CCFLAGS LDFLAGS
LDFLAGS_parse_config=-ldl -export-dynamic
LDFLAGS_parse_config=-ldl
#-export-dynamic
all: $(LIBRARIES:%=build/%) $(MODULES)
echo $(MODULES)
......
......@@ -14,19 +14,66 @@
#include <moberg_config.h>
#include <moberg_parser.h>
struct moberg_digital_in_t {
int index;
char *driver;
};
static struct deferred_action {
struct deferred_action *next;
int (*action)(void *param);
void *param;
} *deferred_action = NULL;
struct moberg {
struct moberg_config *config;
struct {
int count;
struct moberg_digital_in_t *value;
} digital_in;
struct channel_list {
int capacity;
struct moberg_channel **value;
} analog_in, analog_out, digital_in, digital_out, encoder_in;
};
static int channel_list_set(struct channel_list *list,
int index,
struct moberg_channel *value)
{
if (list->capacity <= index) {
int capacity;
for (capacity = 2 ; capacity <= index ; capacity *= 2);
void *new = realloc(list->value, capacity * sizeof(**list->value));
if (!new) {
goto err;
}
void *p = new + list->capacity * sizeof(*list->value);
memset(p, 0, (capacity - list->capacity) * sizeof(**list->value));
list->value = new;
list->capacity = capacity;
}
if (0 <= index && index < list->capacity) {
list->value[index] = value;
return 1;
}
err:
return 0;
}
static int channel_list_get(struct channel_list *list,
int index,
struct moberg_channel **value)
{
if (0 <= index && index < list->capacity) {
*value = list->value[index];
return 1;
}
return 0;
}
static void channel_list_free(struct channel_list *list)
{
for (int i = 0 ; i < list->capacity ; i++) {
if (list->value[i]) {
list->value[i]->down(list->value[i]);
}
}
free(list->value);
}
static void parse_config_at(
struct moberg *moberg,
int dirfd,
......@@ -88,12 +135,77 @@ static void parse_config_dir_at(
}
static int install_channel(struct moberg *moberg,
int index,
struct moberg_device* device,
struct moberg_channel *channel)
{
fprintf(stderr, "CHAN %p %d %d\n", channel, channel->kind, index);
if (channel) {
struct moberg_channel *old = NULL;
switch (channel->kind) {
case chan_ANALOGIN:
channel_list_get(&moberg->analog_in, index, &old);
break;
case chan_ANALOGOUT:
channel_list_get(&moberg->analog_out, index, &old);
break;
case chan_DIGITALIN:
channel_list_get(&moberg->digital_in, index, &old);
break;
case chan_DIGITALOUT:
channel_list_get(&moberg->digital_out, index, &old);
break;
case chan_ENCODERIN:
channel_list_get(&moberg->encoder_in, index, &old);
break;
}
if (old) {
old->down(old);
}
channel->up(channel);
/* TODO: Clean up old channel */
switch (channel->kind) {
case chan_ANALOGIN:
if (! channel_list_set(&moberg->analog_in, index, channel)) {
goto err;
}
break;
case chan_ANALOGOUT:
if (! channel_list_set(&moberg->analog_out, index, channel)) {
goto err;
}
break;
case chan_DIGITALIN:
if (! channel_list_set(&moberg->digital_in, index, channel)) {
goto err;
}
break;
case chan_DIGITALOUT:
if (! channel_list_set(&moberg->digital_out, index, channel)) {
goto err;
}
break;
case chan_ENCODERIN:
if (! channel_list_set(&moberg->encoder_in, index, channel)) {
goto err;
}
break;
}
}
return 1;
err:
return 0;
}
static int install_config(struct moberg *moberg)
{
struct moberg_install_channels install = {
.context=moberg
struct moberg_channel_install install = {
.context=moberg,
.channel=install_channel
};
return moberg_config_install_channels(moberg->config, &install);
/* TODO cleanup unused devices...*/
}
struct moberg *moberg_new(
......@@ -104,6 +216,16 @@ struct moberg *moberg_new(
fprintf(stderr, "Failed to allocate moberg struct\n");
goto err;
}
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;
if (config) {
result->config = config;
} else {
......@@ -118,7 +240,6 @@ struct moberg *moberg_new(
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);
}
......@@ -141,8 +262,20 @@ void moberg_free(struct moberg *moberg)
{
if (moberg) {
moberg_config_free(moberg->config);
channel_list_free(&moberg->analog_in);
channel_list_free(&moberg->analog_out);
channel_list_free(&moberg->digital_in);
channel_list_free(&moberg->digital_out);
channel_list_free(&moberg->encoder_in);
free(moberg);
}
while (deferred_action) {
fprintf(stderr, "RUNNING deferred\n");
struct deferred_action *deferred = deferred_action;
deferred_action = deferred_action->next;
deferred->action(deferred->param);
free(deferred);
}
}
enum moberg_status moberg_start(
......@@ -160,3 +293,16 @@ enum moberg_status moberg_stop(
return moberg_OK;
}
void moberg_deferred_action(
int (*action)(void *param),
void *param)
{
struct deferred_action *deferred = malloc(sizeof(*deferred));
if (deferred) {
fprintf(stderr, "DEFERRED %p %p\n", action, param);
deferred->next = deferred_action;
deferred->action = action;
deferred->param = param;
deferred_action = deferred;
}
}
......@@ -2,71 +2,12 @@
#include <string.h>
#include <moberg_config.h>
#define LIST_COND_GROW(LIST, INDEX, ONERR) \
({ \
if (LIST.capacity <= INDEX) { \
int new_cap; \
for (new_cap = 2 ; new_cap <= INDEX ; new_cap *= 2); \
void *new = realloc(LIST.value, new_cap * sizeof(*LIST.value)); \
if (! new) { ONERR; } \
void *p = new + LIST.capacity * sizeof(*LIST.value); \
memset(p, 0, (new_cap - LIST.capacity) * sizeof(*LIST.value)); \
LIST.value = new; \
LIST.capacity= new_cap; \
} \
})
#define LIST_SET(LIST, INDEX, VALUE, ONERR) \
( LIST_COND_GROW(LIST, INDEX, ONERR), \
LIST.value[INDEX] = VALUE )
#define LIST_GET(LIST, INDEX, VALUE, ONERR) \
( LIST_COND_GROW(LIST, INDEX, ONERR), \
LIST.value[INDEX] )
struct moberg_config
{
struct device_entry {
struct device_entry *next;
struct moberg_device *device;
} *device;
#if 0
struct {
int capacity;
struct analog_in_entry {
struct moberg_device* device;
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;
#endif
} *device_head, **device_tail;
};
struct moberg_config *moberg_config_new()
......@@ -74,19 +15,8 @@ struct moberg_config *moberg_config_new()
struct moberg_config *result = malloc(sizeof *result);
if (result) {
result->device = NULL;
#if 0
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;
#endif
result->device_head = NULL;
result->device_tail = &result->device_head;
}
return result;
......@@ -94,31 +24,30 @@ struct moberg_config *moberg_config_new()
void moberg_config_free(struct moberg_config *config)
{
struct device_entry *entry = config->device;
struct device_entry *entry = config->device_head;
while (entry) {
struct device_entry *tmp = entry;
entry = entry->next;
moberg_device_free(tmp->device);
free(tmp);
}
#if 0
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);
#endif
free(config);
}
int moberg_config_join(struct moberg_config *dest,
struct moberg_config *src)
{
if (src && dest) {
struct device_entry **tail;
for (tail = &dest->device ; *tail ; tail = &(*tail)->next) { }
*tail = src->device;
src->device = NULL;
if (src && dest) {
while (src->device_head) {
struct device_entry *d = src->device_head;
src->device_head = d->next;
if (! src->device_head) {
src->device_tail = &src->device_head;
}
*dest->device_tail = d;
dest->device_tail = &d->next;
}
return 1;
}
return 0;
......@@ -129,79 +58,25 @@ int moberg_config_add_device(struct moberg_config *config,
{
struct device_entry *entry = malloc(sizeof(*entry));
entry->next = config->device;
if (! entry) { goto err; }
entry->next = NULL;
entry->device = device;
config->device = entry;
*config->device_tail = entry;
config->device_tail = &entry->next;
return 1;
err:
return 0;
}
int moberg_config_install_channels(struct moberg_config *config,
struct moberg_install_channels *install)
struct moberg_channel_install *install)
{
return moberg_device_install_channels(config->device->device, install);
int result = 1;
for (struct device_entry *d = config->device_head ; d ; d = d->next) {
result &= moberg_device_install_channels(d->device, install);
}
return result;
}
#if 0
int moberg_config_add_analog_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_analog_in *channel)
{
struct analog_in_entry e = { device, channel };
LIST_SET(config->analog_in, index, e, goto err);
return 1;
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;
}
#endif
......@@ -15,33 +15,6 @@ int moberg_config_add_device(struct moberg_config *config,
struct moberg_device *device);
int moberg_config_install_channels(struct moberg_config *config,
struct moberg_install_channels *install);
#if 0
int moberg_config_add_analog_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_analog_in *channel);
int moberg_config_add_analog_out(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_analog_out *channel);
int moberg_config_add_digital_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_digital_in *channel);
int moberg_config_add_digital_out(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_digital_out *channel);
int moberg_config_add_encoder_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_encoder_in *channel);
# endif
struct moberg_channel_install *install);
#endif
......@@ -4,25 +4,26 @@
#include <dlfcn.h>
#include <moberg_config.h>
#include <moberg_device.h>
#include <moberg_channel.h>
struct moberg_device {
void *driver_handle;
struct moberg_device_driver driver;
struct moberg_device_config *device_config;
struct moberg_device_context *device_context;
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;
struct moberg_channel_analog_in *analog_in;
struct moberg_channel_analog_out *analog_out;
struct moberg_channel_digital_in *digital_in;
struct moberg_channel_digital_out *digital_out;
struct moberg_channel_encoder_in *encoder_in;
struct moberg_channel *channel;
} u;
} *channel_head, **channel_tail;
struct map_range {
struct moberg_config *config;
struct moberg_device *device;
enum moberg_channel_kind kind;
int min;
int max;
......@@ -52,15 +53,21 @@ struct moberg_device *moberg_device_new(const char *driver)
fprintf(stderr, "Could not allocate result for %s\n", name);
goto dlclose_driver;
}
result->driver_handle = handle;
result->driver = *device_driver;
result->device_config = NULL;
result->device_context = result->driver.new(dlclose, handle);
if (result->device_context) {
result->driver.up(result->device_context);
} else {
fprintf(stderr, "Could not allocate context for %s\n", name);
goto free_result;
}
result->channel_head = NULL;
result->channel_tail = &result->channel_head;
result->range = NULL;
goto free_name;
free_result:
free(result);
dlclose_driver:
dlclose(handle);
free_name:
......@@ -78,48 +85,15 @@ void moberg_device_free(struct moberg_device *device)
free(channel);
channel = next;
}
device->driver.config_free(device->device_config);
free(device->device_config);
dlclose(device->driver_handle);
int use = device->driver.down(device->device_context);
fprintf(stderr, "USE: %d\n", use);
free(device);
}
int moberg_device_parse_config(struct moberg_device *device,
struct moberg_parser_context *context)
{
return device->driver.parse_config(device, context);
}
int moberg_device_set_config(struct moberg_device *device,
struct moberg_device_config *config)
struct moberg_parser_context *parser)
{
if (device->device_config) {
device->driver.config_free(device->device_config);
free(device->device_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,
enum moberg_channel_kind kind,
int min,
int max)
{
int result;
struct map_range r = {
.config=config,
.kind=kind,
.min=min,
.max=max
};
device->range = &r;
result = device->driver.parse_map(device, context, kind);
device->range = NULL;
printf("RRR %d %d\n", r.min, r.max);
return result;
return device->driver.parse_config(device->device_context, parser);
}
static int add_channel(struct moberg_device* device,
......@@ -141,7 +115,7 @@ err:
}
int moberg_device_add_analog_in(struct moberg_device* device,
struct moberg_device_analog_in *channel)
struct moberg_channel_analog_in *channel)
{
int result = 0;
......@@ -156,7 +130,7 @@ int moberg_device_add_analog_in(struct moberg_device* device,
}
int moberg_device_add_analog_out(struct moberg_device* device,
struct moberg_device_analog_out *channel)
struct moberg_channel_analog_out *channel)
{
int result = 0;
......@@ -171,7 +145,7 @@ int moberg_device_add_analog_out(struct moberg_device* device,
}
int moberg_device_add_digital_in(struct moberg_device* device,
struct moberg_device_digital_in *channel)
struct moberg_channel_digital_in *channel)
{
int result = 0;
......@@ -186,7 +160,7 @@ int moberg_device_add_digital_in(struct moberg_device* device,
}
int moberg_device_add_digital_out(struct moberg_device* device,
struct moberg_device_digital_out *channel)
struct moberg_channel_digital_out *channel)
{
int result = 0;