Cleanup - 0.0.2
[libautomation.git] / lib / datasource.c
blob5e53232038bfae01b731d34a72277acd7dc7f882
1 #include <limits.h>
2 #include <string.h>
3 #include <ev.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <glob.h>
12 #include "libautomation.h"
14 int atm_file_integer(const char *filename, int *v) {
15 int fd, ret;
16 char buf[256];
18 fd = open(filename, O_RDONLY);
19 if(fd < 0)
20 atm_fail(filename);
22 ret = read(fd, buf, 256);
23 close(fd);
24 if(ret < 0)
25 atm_log("read_device(%s): %s", filename, strerror(errno));
26 else {
27 *v = atm_read_int_or_fail(buf, filename);
29 return 0;
32 return -1;
35 int atm_file_float(const char *filename, float *v) {
36 int fd, ret;
37 char buf[256];
39 fd = open(filename, O_RDONLY);
40 if(fd < 0)
41 atm_fail(filename);
43 ret = read(fd, buf, 256);
44 close(fd);
45 if(ret < 0)
46 atm_log("read_device(%s): %s", filename, strerror(errno));
47 else {
48 *v = atm_read_float_or_fail(buf, filename);
50 return 0;
53 return -1;
56 int atm_ds_trf_filter(struct ATM_DSTRF_FILTER *transf, int *v) {
57 int value, ret;
59 ret = transf->src.cb(transf->src.private_data, &value);
60 if (ret == 0)
61 *v = transf->func(transf->data, value);
63 return ret;
66 static int atm_dsgrp_dsgrp_cb (struct ATM_DSGRP *dsgrp) {
67 return dsgrp->policy(dsgrp);
70 int atm_ds_policyhelper(struct ATM_DS *ds) {
71 int ret = ds->src.cb(ds->src.private_data, &ds->dest->v);
73 if (ret == 0)
74 ds->dest->ts = atm_time;
76 return ret;
79 int atm_ds_policy_ignore(struct ATM_DSGRP *grp) {
80 int ret;
82 while (grp->cur < grp->n) {
83 ret = atm_ds_policyhelper(&grp->memb[grp->cur]);
84 if (ret > 0)
85 return ret;
86 ++grp->cur;
89 grp->cur = 0;
91 return 0;
94 int atm_ds_policy_detect(struct ATM_DSGRP *grp) {
95 int ret;
97 while (grp->cur < grp->n) {
98 ret = atm_ds_policyhelper(&grp->memb[grp->cur]);
99 ++grp->cur;
100 if (ret != 0)
101 return ret;
104 grp->cur = 0;
106 return 0;
109 int atm_ds_policy_retry(struct ATM_DSGRP *grp) {
110 int max_retries = (int) grp->policy_data, retries = 0, ret;
112 while (grp->cur < grp->n && retries < max_retries) {
113 ++retries;
115 ret = atm_ds_policyhelper(&grp->memb[grp->cur]);
116 if (ret > 0)
117 return ret;
118 if (ret == 0) {
119 ++grp->cur;
120 retries = 0;
124 grp->cur = 0;
126 return ret;
129 int atm_ds_policy_reset(struct ATM_DSGRP *grp) {
130 struct ATM_DSGRP_PD_RESET *d = grp->policy_data;
131 int ret;
133 if (d->status == -1) {
134 d->status = 0;
135 d->enable(d->enable_data);
137 return d->delay;
140 while (grp->cur < grp->n) {
141 ret = atm_ds_policyhelper(&grp->memb[grp->cur]);
142 if (ret > 0)
143 return ret;
144 if (ret < 0)
145 ++d->status;
147 grp->cur = 0;
149 if (d->status == 0)
150 return 0;
152 d->status = -1;
153 d->disable(d->disable_data);
155 return d->delay;
158 struct ATM_DS *_atm_iiosysfs_setup(const char *dev, const char *channel) {
159 struct ATM_DS *ds = NULL;
160 struct ATM_DSTRF_FILTER *transf;
161 struct ATM_FILTER_SCALE_OFFSET *filter;
162 glob_t globbuf;
163 char buffer[NAME_MAX], *p, *filename;
164 int fd, i, size, offset = 0;
165 float scale = 1.0;
167 if (dev[0] == '/') {
168 glob(dev, GLOB_MARK, NULL, &globbuf);
169 if (globbuf.gl_pathc = 0)
170 goto err_glob;
172 size = strlen(*globbuf.gl_pathv);
173 i = 0;
175 else {
176 glob("/sys/bus/iio/iio:device*/name", 0, NULL, &globbuf);
177 for (i = 0; i < globbuf.gl_pathc; ++i) {
178 fd = open(globbuf.gl_pathv[i], O_RDONLY);
179 size = read(fd, buffer, sizeof(buffer));
180 close(fd);
181 if (!strncmp(buffer, dev, size)) /* TODO: linebreak */
182 break;
184 if (i == globbuf.gl_pathc)
185 goto err_glob;
187 size = strlen(globbuf.gl_pathv[i]) - 4;
188 globbuf.gl_pathv[i][size] = 0;
190 size = sizeof(buffer);
191 p = atm_stradd(buffer, globbuf.gl_pathv[i], &size);
192 p = atm_stradd(p, channel, &size);
193 if (size < 8)
194 goto err_glob;
196 strcpy(p, "_input");
197 glob(buffer, 0, NULL, &globbuf);
198 if (globbuf.gl_pathc == 1) {
199 filename = strdup(buffer);
201 else {
202 strcpy(p, "_raw");
203 glob(buffer, 0, NULL, &globbuf);
204 if (globbuf.gl_pathc == 0)
205 goto err_glob;
207 filename = strdup(buffer);
208 strcpy(p, "_scale");
209 atm_file_float(buffer, &scale);
210 strcpy(p, "_offset");
211 atm_file_integer(buffer, &offset);
214 ds = malloc(sizeof(*ds));
216 if (offset != 0 || scale != 1.0) {
217 filter = malloc(sizeof(*filter));
218 filter->scale = scale;
219 filter->offset = offset;
221 transf = malloc(sizeof(*transf));
222 transf->func = atm_filter_scale_offset;
223 transf->data = filter;
224 atm_ds_set_char(&transf->src, filename, atm_file_integer);
226 atm_ds_set_trf_filter(&ds->src, transf);
228 else {
229 atm_ds_set_char(&ds->src, filename, atm_file_integer);
232 err_glob:
233 globfree(&globbuf);
235 return ds;
238 struct ATM_VALUE *
239 atm_ds_register(struct ATM_DSGRP *grp, const char *url, const char *key) {
240 struct ATM_DS *new_entry;
241 char buffer[NAME_MAX], *p;
242 int i;
243 void *private_data, *cb;
245 switch (*url) {
246 case 'f':
247 if (strncmp(url, "file:", 5) == 0) {
248 private_data = atm_globdup(&url[5]);
249 if (!private_data) {
250 atm_log("Can't find %s", url);
251 return NULL;
254 cb = atm_file_integer;
256 break;
259 goto default_case;
261 case 'i':
262 if (strncmp(url, "iiosysfs:", 9) == 0) {
263 url += 9;
264 p = strchr(url, ':');
265 if (!p)
266 return NULL;
267 *p++ = 0;
269 new_entry = _atm_iiosysfs_setup(url, p);
270 if (!new_entry)
271 return NULL;
273 return new_entry->dest = atm_value(key);
276 goto default_case;
278 case 'l':
279 if (strncmp(url, "local:", 6) == 0) {
280 struct ATM_VALUE *v;
281 if (!atm_shm_stdmem) {
282 atm_log("no data for %s", url);
283 return NULL;
286 v = atm_shm_find(atm_shm_stdmem, &url[6]);
287 /* Create if we reference ourself: */
288 if (!v && !strcmp(key, &url[6]))
289 v = atm_value(key);
291 return v;
294 goto default_case;
296 case 's':
297 if (strncmp(url, "shm:", 4) == 0)
298 return atm_shm_get_by_url(&url[4]);
300 goto default_case;
302 case 'v':
303 if (strncmp(url, "value:", 6) == 0) {
304 struct ATM_VALUE *v = atm_value(key);
306 atm_shm_update(v, strtol(&url[6], NULL, 10));
308 return v;
311 goto default_case;
313 default:
314 default_case:
315 atm_log("Unkown pseudo-url schema in: %s", url);
317 return NULL;
320 /* We actually need to setup a value in shared memory */
322 return atm_dsgrp_insert(grp, cb, private_data, atm_value(key))->dest;
325 struct ATM_DS *atm_dsgrp_insert(struct ATM_DSGRP *grp, void *cb, void *pdata,
326 struct ATM_VALUE *dest) {
328 if (grp->n >= grp->size) {
329 grp->size <<= 1;
330 grp->memb = realloc(grp->memb, grp->size * sizeof(*grp->memb));
333 grp->memb[grp->n].src.cb = cb;
334 grp->memb[grp->n].src.private_data = pdata;
335 grp->memb[grp->n].dest = dest;
337 return &grp->memb[grp->n++];
340 struct ATM_VALUE *atm_ds(const char *url, const char *key) {
341 return atm_ds_register(&atm_main_task.dsgrp, url, key);
344 struct ATM_DSGRP *atm_dsgrp_dsgrp(struct ATM_DSGRP *grp) {
345 static struct ATM_VALUE dummy_dest; /* for garbage but writeable ts? */
346 struct ATM_DSGRP *newgrp = malloc(sizeof(*newgrp));
348 atm_dsgrp_init(newgrp);
349 atm_dsgrp_insert(grp, atm_dsgrp_dsgrp_cb, newgrp, &dummy_dest);
351 return newgrp;
354 void atm_dsgrp_init(struct ATM_DSGRP *grp) {
355 grp->cur = grp->n = 0;
356 grp->size = 4;
357 grp->memb = malloc(grp->size * sizeof(*grp->memb));
358 grp->policy_data = NULL,
359 grp->policy = atm_ds_policy_ignore;