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; }