diff options
author | px4dev <px4@purgatory.org> | 2012-08-19 01:30:55 -0700 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2012-08-19 01:31:27 -0700 |
commit | d903311dce6a94f09e56bc557025d2d4d73120b8 (patch) | |
tree | 3711e1e506b5f47e00189210f35a1d6eb47f51e0 /apps/systemlib/param/param.c | |
parent | a9dc84231e0e02abbbfd2f13e3500d193ebdb03b (diff) | |
download | px4-firmware-d903311dce6a94f09e56bc557025d2d4d73120b8.tar.gz px4-firmware-d903311dce6a94f09e56bc557025d2d4d73120b8.tar.bz2 px4-firmware-d903311dce6a94f09e56bc557025d2d4d73120b8.zip |
Add support for setting and exporting parameters.
Diffstat (limited to 'apps/systemlib/param/param.c')
-rw-r--r-- | apps/systemlib/param/param.c | 261 |
1 files changed, 246 insertions, 15 deletions
diff --git a/apps/systemlib/param/param.c b/apps/systemlib/param/param.c index bb82941a0..315ba187b 100644 --- a/apps/systemlib/param/param.c +++ b/apps/systemlib/param/param.c @@ -6,10 +6,13 @@ #include <string.h> #include <stdbool.h> - +#include <fcntl.h> #include <unistd.h> +#include <err.h> -#include "param.h" +#include "systemlib/param/param.h" +#include "systemlib/uthash/utarray.h" +#include "systemlib/bson/bson.h" /** * Array of static parameter info. @@ -19,12 +22,78 @@ static const struct param_info_s *param_info_base = (struct param_info_s *)&__pa static const struct param_info_s *param_info_limit = (struct param_info_s *)&__param_end; #define param_info_count ((unsigned)(param_info_limit - param_info_base)) +/** + * Storage for modified parameters. + */ +struct param_wbuf_s +{ + param_t param; + union param_value_u val; + bool unsaved; +}; + +UT_icd param_icd = {sizeof(struct param_wbuf_s), NULL, NULL, NULL}; +UT_array *param_values; + +static void +param_lock(void) +{ + /* XXX */ +} + +static void +param_unlock(void) +{ + /* XXX */ +} + +static void +param_assert_locked(void) +{ + /* XXX */ +} + static bool handle_in_range(param_t handle) { return (handle < param_info_count); } +static int +param_compare_values(const void *a, const void *b) +{ + struct param_wbuf_s *pa = (struct param_wbuf_s *)a; + struct param_wbuf_s *pb = (struct param_wbuf_s *)b; + + if (pa->param < pb->param) + return -1; + if (pa->param > pb->param) + return 1; + return 0; +} + +static struct param_wbuf_s * +param_find_changed(param_t param) +{ + struct param_wbuf_s *s = NULL; + + param_assert_locked(); + + if (param_values != NULL) { +#if 0 /* utarray_find requires bsearch, not available */ + struct param_wbuf_s key; + key.param = param; + s = utarray_find(param_values, &key, param_compare_values); +#else + while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) { + if (s->param == param) + break; + } +#endif + } + return s; +} + param_t param_find(const char *name) { @@ -39,8 +108,17 @@ param_find(const char *name) return PARAM_INVALID; } -enum -param_type_e param_type(param_t param) +const char * +param_name(param_t param) +{ + if (handle_in_range(param)) + return param_info_base[param].name; + + return NULL; +} + +enum param_type_e +param_type(param_t param) { if (handle_in_range(param)) return param_info_base[param].type; @@ -51,7 +129,6 @@ param_type_e param_type(param_t param) size_t param_size(param_t param) { - if (handle_in_range(param)) { switch (param_info_base[param].type) { case PARAM_TYPE_INT32: @@ -72,39 +149,193 @@ param_size(param_t param) int param_get(param_t param, void *val) { + int result = -1; + + param_lock(); + if (handle_in_range(param)) { + struct param_wbuf_s *s = param_find_changed(param); + const union param_value_u *v; + + /* work out whether we're fetching the default or a written value */ + if (s != NULL) { + v = &s->val; + } else { + v = ¶m_info_base[param].val; + } + /* XXX look for updated value stored elsewhere */ switch (param_info_base[param].type) { case PARAM_TYPE_INT32: - *(int32_t *)val = param_info_base[param].i; - return 0; + *(int32_t *)val = v->i; + result = 0; + break; case PARAM_TYPE_FLOAT: - *(float *)val = param_info_base[param].f; - return 0; + *(float *)val = v->f; + result = 0; + break; case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: - memcpy(val, param_info_base[param].p, param_size(param)); - return 0; + *(void **)val = v->p; + result = 0; + break; default: - return -1; + break; } + } - return -1; + + param_unlock(); + + return result; } int param_set(param_t param, void *val) { + int result = -1; + + param_lock(); + + if (param_values == NULL) + utarray_new(param_values, ¶m_icd); + if (param_values == NULL) + goto out; + if (handle_in_range(param)) { - /* XXX maintain list of changed values */ + struct param_wbuf_s *s = param_find_changed(param); + + if (s == NULL) { + /* construct a new parameter */ + struct param_wbuf_s buf = { .param = param }; + + /* add it to the array and sort */ + utarray_push_back(param_values, &buf); + utarray_sort(param_values, param_compare_values); + + /* find it after sorting */ + s = param_find_changed(param); + } + + /* update the changed value */ + switch (param_info_base[param].type) { + case PARAM_TYPE_INT32: + s->val.i = *(int32_t *)val; + break; + + case PARAM_TYPE_FLOAT: + s->val.f = *(float *)val; + break; + + case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: + s->val.p = *(void **)val; + break; + + default: + goto out; + } + s->unsaved = true; + + result = 0; } - return -1; +out: + param_unlock(); + return result; +} + +int +param_export(const char *filename, bool only_unsaved) +{ + struct param_wbuf_s *s; + bson b[1]; + int result = -1; + + param_lock(); + + bson_init(b); + + while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) { + const struct param_info_s *is = ¶m_info_base[s->param]; + + /* + * if we are only saving values changed since last save, and this + * one hasn't, then skip it + */ + if (only_unsaved & !s->unsaved) + continue; + s->unsaved = false; + + switch (is->type) { + case PARAM_TYPE_INT32: + if (bson_append_int(b, is->name, s->val.i) != BSON_OK) + goto out; + break; + case PARAM_TYPE_FLOAT: + if (bson_append_double(b, is->name, s->val.f) != BSON_OK) + goto out; + break; + + case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: + if (bson_append_binary(b, + is->name, + is->type, + is->val.p, + is->type - PARAM_TYPE_STRUCT) != BSON_OK) + goto out; + break; + default: + goto out; + } + } + result = 0; + +out: + param_unlock(); + + if (result == 0) { + bson_finish(b); + bson_print(b); + + warnx("object is %d bytes", bson_buffer_size(b)); + + if (filename != NULL) { + int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666); + int siz = bson_buffer_size(b); + int len = write(fd, bson_data(b), siz); + close(fd); + if (len != siz) + result = -1; + } + } + bson_destroy(b); + + return result; +} + +int +param_import(const char *filename) +{ + return -1; } +void +param_foreach(void (*func)(void *arg, param_t param), void *arg, bool only_changed) +{ + param_t param; + + for (param = 0; handle_in_range(param); param++) { + + /* if requested, skip unchanged values */ + if (only_changed && (param_find_changed(param) == NULL)) + continue; + + func(arg, param); + } +}
\ No newline at end of file |