12 #include "libautomation.h"
14 int atm_file_integer(const char *filename
, int *v
) {
18 fd
= open(filename
, O_RDONLY
);
22 ret
= read(fd
, buf
, 256);
25 atm_log("read_device(%s): %s", filename
, strerror(errno
));
27 *v
= atm_read_int_or_fail(buf
, filename
);
35 int atm_file_float(const char *filename
, float *v
) {
39 fd
= open(filename
, O_RDONLY
);
43 ret
= read(fd
, buf
, 256);
46 atm_log("read_device(%s): %s", filename
, strerror(errno
));
48 *v
= atm_read_float_or_fail(buf
, filename
);
56 int atm_ds_trf_filter(struct ATM_DSTRF_FILTER
*transf
, int *v
) {
59 ret
= transf
->src
.cb(transf
->src
.private_data
, &value
);
61 *v
= transf
->func(transf
->data
, value
);
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
);
74 ds
->dest
->ts
= atm_time
;
79 int atm_ds_policy_ignore(struct ATM_DSGRP
*grp
) {
82 while (grp
->cur
< grp
->n
) {
83 ret
= atm_ds_policyhelper(&grp
->memb
[grp
->cur
]);
94 int atm_ds_policy_detect(struct ATM_DSGRP
*grp
) {
97 while (grp
->cur
< grp
->n
) {
98 ret
= atm_ds_policyhelper(&grp
->memb
[grp
->cur
]);
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
) {
115 ret
= atm_ds_policyhelper(&grp
->memb
[grp
->cur
]);
129 int atm_ds_policy_reset(struct ATM_DSGRP
*grp
) {
130 struct ATM_DSGRP_PD_RESET
*d
= grp
->policy_data
;
133 if (d
->status
== -1) {
135 d
->enable(d
->enable_data
);
140 while (grp
->cur
< grp
->n
) {
141 ret
= atm_ds_policyhelper(&grp
->memb
[grp
->cur
]);
153 d
->disable(d
->disable_data
);
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
;
163 char buffer
[NAME_MAX
], *p
, *filename
;
164 int fd
, i
, size
, offset
= 0;
168 glob(dev
, GLOB_MARK
, NULL
, &globbuf
);
169 if (globbuf
.gl_pathc
= 0)
172 size
= strlen(*globbuf
.gl_pathv
);
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
));
181 if (!strncmp(buffer
, dev
, size
)) /* TODO: linebreak */
184 if (i
== globbuf
.gl_pathc
)
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
);
197 glob(buffer
, 0, NULL
, &globbuf
);
198 if (globbuf
.gl_pathc
== 1) {
199 filename
= strdup(buffer
);
203 glob(buffer
, 0, NULL
, &globbuf
);
204 if (globbuf
.gl_pathc
== 0)
207 filename
= strdup(buffer
);
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
);
229 atm_ds_set_char(&ds
->src
, filename
, atm_file_integer
);
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
;
243 void *private_data
, *cb
;
247 if (strncmp(url
, "file:", 5) == 0) {
248 private_data
= atm_globdup(&url
[5]);
250 atm_log("Can't find %s", url
);
254 cb
= atm_file_integer
;
262 if (strncmp(url
, "iiosysfs:", 9) == 0) {
264 p
= strchr(url
, ':');
269 new_entry
= _atm_iiosysfs_setup(url
, p
);
273 return new_entry
->dest
= atm_value(key
);
279 if (strncmp(url
, "local:", 6) == 0) {
281 if (!atm_shm_stdmem
) {
282 atm_log("no data for %s", url
);
286 v
= atm_shm_find(atm_shm_stdmem
, &url
[6]);
287 /* Create if we reference ourself: */
288 if (!v
&& !strcmp(key
, &url
[6]))
297 if (strncmp(url
, "shm:", 4) == 0)
298 return atm_shm_get_by_url(&url
[4]);
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));
315 atm_log("Unkown pseudo-url schema in: %s", url
);
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
) {
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
);
354 void atm_dsgrp_init(struct ATM_DSGRP
*grp
) {
355 grp
->cur
= grp
->n
= 0;
357 grp
->memb
= malloc(grp
->size
* sizeof(*grp
->memb
));
358 grp
->policy_data
= NULL
,
359 grp
->policy
= atm_ds_policy_ignore
;