1 /*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2014 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
19 #include "debug.h"
20 #include "iio-private.h"
21
22 #include <inttypes.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <string.h>
26
get_attr_xml(const char * attr,size_t * length,enum iio_attr_type type)27 static char *get_attr_xml(const char *attr, size_t *length, enum iio_attr_type type)
28 {
29 size_t len;
30 char *str;
31
32 len = sizeof("<attribute name=\"\" />") - 1;
33 len += strnlen(attr, MAX_ATTR_NAME);
34
35 switch(type){
36 case IIO_ATTR_TYPE_DEVICE:
37 break;
38 case IIO_ATTR_TYPE_DEBUG:
39 len += (sizeof("debug-") - 1);
40 break;
41 case IIO_ATTR_TYPE_BUFFER:
42 len += (sizeof("buffer-") - 1);
43 break;
44 default:
45 return NULL;
46 }
47
48 *length = len; /* just the chars */
49 len++; /* room for terminating NULL */
50 str = malloc(len);
51 if (!str)
52 return NULL;
53
54 switch (type) {
55 case IIO_ATTR_TYPE_DEVICE:
56 iio_snprintf(str, len, "<attribute name=\"%s\" />", attr);
57 break;
58 case IIO_ATTR_TYPE_DEBUG:
59 iio_snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
60 break;
61 case IIO_ATTR_TYPE_BUFFER:
62 iio_snprintf(str, len, "<buffer-attribute name=\"%s\" />", attr);
63 break;
64 }
65
66 return str;
67 }
68
69 /* Returns a string containing the XML representation of this device */
iio_device_get_xml(const struct iio_device * dev,size_t * length)70 char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
71 {
72 ssize_t len;
73 char *ptr, *eptr, *str, **attrs, **channels, **buffer_attrs, **debug_attrs;
74 size_t *attrs_len, *channels_len, *buffer_attrs_len, *debug_attrs_len;
75 unsigned int i, j, k;
76
77 len = sizeof("<device id=\"\" ></device>") - 1;
78 len += strnlen(dev->id, MAX_DEV_ID);
79 if (dev->name) {
80 len += sizeof(" name=\"\"") - 1;
81 len += strnlen(dev->name, MAX_DEV_NAME);
82 }
83
84 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
85 if (!attrs_len)
86 return NULL;
87
88 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
89 if (!attrs)
90 goto err_free_attrs_len;
91
92 for (i = 0; i < dev->nb_attrs; i++) {
93 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], IIO_ATTR_TYPE_DEVICE);
94 if (!xml)
95 goto err_free_attrs;
96 attrs[i] = xml;
97 len += attrs_len[i];
98 }
99
100 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
101 if (!channels_len)
102 goto err_free_attrs;
103
104 channels = malloc(dev->nb_channels * sizeof(*channels));
105 if (!channels)
106 goto err_free_channels_len;
107
108 for (j = 0; j < dev->nb_channels; j++) {
109 char *xml = iio_channel_get_xml(dev->channels[j],
110 &channels_len[j]);
111 if (!xml)
112 goto err_free_channels;
113 channels[j] = xml;
114 len += channels_len[j];
115 }
116
117 buffer_attrs_len = malloc(dev->nb_buffer_attrs *
118 sizeof(*buffer_attrs_len));
119 if (!buffer_attrs_len)
120 goto err_free_channels;
121
122 buffer_attrs = malloc(dev->nb_buffer_attrs * sizeof(*buffer_attrs));
123 if (!buffer_attrs)
124 goto err_free_buffer_attrs_len;
125
126 for (k = 0; k < dev->nb_buffer_attrs; k++) {
127 char *xml = get_attr_xml(dev->buffer_attrs[k],
128 &buffer_attrs_len[k], IIO_ATTR_TYPE_BUFFER);
129 if (!xml)
130 goto err_free_buffer_attrs;
131 buffer_attrs[k] = xml;
132 len += buffer_attrs_len[k];
133 }
134
135 debug_attrs_len = malloc(dev->nb_debug_attrs *
136 sizeof(*debug_attrs_len));
137 if (!debug_attrs_len)
138 goto err_free_buffer_attrs;
139
140 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
141 if (!debug_attrs)
142 goto err_free_debug_attrs_len;
143
144 for (k = 0; k < dev->nb_debug_attrs; k++) {
145 char *xml = get_attr_xml(dev->debug_attrs[k],
146 &debug_attrs_len[k], IIO_ATTR_TYPE_DEBUG);
147 if (!xml)
148 goto err_free_debug_attrs;
149 debug_attrs[k] = xml;
150 len += debug_attrs_len[k];
151 }
152
153 len++; /* room for terminating NULL */
154 str = malloc(len);
155 if (!str)
156 goto err_free_debug_attrs;
157 eptr = str + len;
158 ptr = str;
159
160 if (len > 0) {
161 ptr += iio_snprintf(str, len, "<device id=\"%s\"", dev->id);
162 len = eptr - ptr;
163 }
164
165 if (dev->name && len > 0) {
166 ptr += iio_snprintf(ptr, len, " name=\"%s\"", dev->name);
167 len = eptr - ptr;
168 }
169
170 if (len > 0) {
171 ptr += iio_strlcpy(ptr, " >", len);
172 len -= 2;
173 }
174
175 for (i = 0; i < dev->nb_channels; i++) {
176 if (len > (ssize_t) channels_len[i]) {
177 memcpy(ptr, channels[i], channels_len[i]); /* Flawfinder: ignore */
178 ptr += channels_len[i];
179 len -= channels_len[i];
180 }
181 free(channels[i]);
182 }
183
184 free(channels);
185 free(channels_len);
186
187 for (i = 0; i < dev->nb_attrs; i++) {
188 if (len > (ssize_t) attrs_len[i]) {
189 memcpy(ptr, attrs[i], attrs_len[i]); /* Flawfinder: ignore */
190 ptr += attrs_len[i];
191 len -= attrs_len[i];
192 }
193 free(attrs[i]);
194 }
195
196 free(attrs);
197 free(attrs_len);
198
199 for (i = 0; i < dev->nb_buffer_attrs; i++) {
200 if (len > (ssize_t) buffer_attrs_len[i]) {
201 memcpy(ptr, buffer_attrs[i], buffer_attrs_len[i]); /* Flawfinder: ignore */
202 ptr += buffer_attrs_len[i];
203 len -= buffer_attrs_len[i];
204 }
205 free(buffer_attrs[i]);
206 }
207
208 free(buffer_attrs);
209 free(buffer_attrs_len);
210
211 for (i = 0; i < dev->nb_debug_attrs; i++) {
212 if (len > (ssize_t) debug_attrs_len[i]) {
213 memcpy(ptr, debug_attrs[i], debug_attrs_len[i]); /* Flawfinder: ignore */
214 ptr += debug_attrs_len[i];
215 len -= debug_attrs_len[i];
216 }
217 free(debug_attrs[i]);
218 }
219
220 free(debug_attrs);
221 free(debug_attrs_len);
222
223 if (len > 0) {
224 ptr += iio_strlcpy(ptr, "</device>", len);
225 len -= sizeof("</device>") - 1;
226 }
227
228 *length = ptr - str;
229
230 if (len != 1) {
231 IIO_ERROR("Internal libIIO error: iio_device_get_xml str length issue\n");
232 free(str);
233 return NULL;
234 }
235
236 return str;
237
238 err_free_debug_attrs:
239 while (k--)
240 free(debug_attrs[k]);
241 free(debug_attrs);
242 err_free_debug_attrs_len:
243 free(debug_attrs_len);
244 err_free_buffer_attrs:
245 while (k--)
246 free(buffer_attrs[k]);
247 free(buffer_attrs);
248 err_free_buffer_attrs_len:
249 free(buffer_attrs_len);
250 err_free_channels:
251 while (j--)
252 free(channels[j]);
253 free(channels);
254 err_free_channels_len:
255 free(channels_len);
256 err_free_attrs:
257 while (i--)
258 free(attrs[i]);
259 free(attrs);
260 err_free_attrs_len:
261 free(attrs_len);
262 return NULL;
263 }
264
iio_device_get_id(const struct iio_device * dev)265 const char * iio_device_get_id(const struct iio_device *dev)
266 {
267 return dev->id;
268 }
269
iio_device_get_name(const struct iio_device * dev)270 const char * iio_device_get_name(const struct iio_device *dev)
271 {
272 return dev->name;
273 }
274
iio_device_get_channels_count(const struct iio_device * dev)275 unsigned int iio_device_get_channels_count(const struct iio_device *dev)
276 {
277 return dev->nb_channels;
278 }
279
iio_device_get_channel(const struct iio_device * dev,unsigned int index)280 struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
281 unsigned int index)
282 {
283 if (index >= dev->nb_channels)
284 return NULL;
285 else
286 return dev->channels[index];
287 }
288
iio_device_find_channel(const struct iio_device * dev,const char * name,bool output)289 struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
290 const char *name, bool output)
291 {
292 unsigned int i;
293 for (i = 0; i < dev->nb_channels; i++) {
294 struct iio_channel *chn = dev->channels[i];
295 if (iio_channel_is_output(chn) != output)
296 continue;
297
298 if (!strcmp(chn->id, name) ||
299 (chn->name && !strcmp(chn->name, name)))
300 return chn;
301 }
302 return NULL;
303 }
304
iio_device_get_attrs_count(const struct iio_device * dev)305 unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
306 {
307 return dev->nb_attrs;
308 }
309
iio_device_get_attr(const struct iio_device * dev,unsigned int index)310 const char * iio_device_get_attr(const struct iio_device *dev,
311 unsigned int index)
312 {
313 if (index >= dev->nb_attrs)
314 return NULL;
315 else
316 return dev->attrs[index];
317 }
318
iio_device_find_attr(const struct iio_device * dev,const char * name)319 const char * iio_device_find_attr(const struct iio_device *dev,
320 const char *name)
321 {
322 unsigned int i;
323 for (i = 0; i < dev->nb_attrs; i++) {
324 const char *attr = dev->attrs[i];
325 if (!strcmp(attr, name))
326 return attr;
327 }
328 return NULL;
329 }
330
iio_device_get_buffer_attrs_count(const struct iio_device * dev)331 unsigned int iio_device_get_buffer_attrs_count(const struct iio_device *dev)
332 {
333 return dev->nb_buffer_attrs;
334 }
335
iio_device_get_buffer_attr(const struct iio_device * dev,unsigned int index)336 const char * iio_device_get_buffer_attr(const struct iio_device *dev,
337 unsigned int index)
338 {
339 if (index >= dev->nb_buffer_attrs)
340 return NULL;
341 else
342 return dev->buffer_attrs[index];
343 }
344
iio_device_find_buffer_attr(const struct iio_device * dev,const char * name)345 const char * iio_device_find_buffer_attr(const struct iio_device *dev,
346 const char *name)
347 {
348 unsigned int i;
349 for (i = 0; i < dev->nb_buffer_attrs; i++) {
350 const char *attr = dev->buffer_attrs[i];
351 if (!strcmp(attr, name))
352 return attr;
353 }
354 return NULL;
355 }
356
iio_device_find_debug_attr(const struct iio_device * dev,const char * name)357 const char * iio_device_find_debug_attr(const struct iio_device *dev,
358 const char *name)
359 {
360 unsigned int i;
361 for (i = 0; i < dev->nb_debug_attrs; i++) {
362 const char *attr = dev->debug_attrs[i];
363 if (!strcmp(attr, name))
364 return attr;
365 }
366 return NULL;
367 }
368
iio_device_is_tx(const struct iio_device * dev)369 bool iio_device_is_tx(const struct iio_device *dev)
370 {
371 unsigned int i;
372
373 for (i = 0; i < dev->nb_channels; i++) {
374 struct iio_channel *ch = dev->channels[i];
375 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
376 return true;
377 }
378
379 return false;
380 }
381
iio_device_open(const struct iio_device * dev,size_t samples_count,bool cyclic)382 int iio_device_open(const struct iio_device *dev,
383 size_t samples_count, bool cyclic)
384 {
385 unsigned int i;
386 bool has_channels = false;
387
388 for (i = 0; !has_channels && i < dev->words; i++)
389 has_channels = !!dev->mask[i];
390 if (!has_channels)
391 return -EINVAL;
392
393 if (dev->ctx->ops->open)
394 return dev->ctx->ops->open(dev, samples_count, cyclic);
395 else
396 return -ENOSYS;
397 }
398
iio_device_close(const struct iio_device * dev)399 int iio_device_close(const struct iio_device *dev)
400 {
401 if (dev->ctx->ops->close)
402 return dev->ctx->ops->close(dev);
403 else
404 return -ENOSYS;
405 }
406
iio_device_get_poll_fd(const struct iio_device * dev)407 int iio_device_get_poll_fd(const struct iio_device *dev)
408 {
409 if (dev->ctx->ops->get_fd)
410 return dev->ctx->ops->get_fd(dev);
411 else
412 return -ENOSYS;
413 }
414
iio_device_set_blocking_mode(const struct iio_device * dev,bool blocking)415 int iio_device_set_blocking_mode(const struct iio_device *dev, bool blocking)
416 {
417 if (dev->ctx->ops->set_blocking_mode)
418 return dev->ctx->ops->set_blocking_mode(dev, blocking);
419 else
420 return -ENOSYS;
421 }
422
iio_device_read_raw(const struct iio_device * dev,void * dst,size_t len,uint32_t * mask,size_t words)423 ssize_t iio_device_read_raw(const struct iio_device *dev,
424 void *dst, size_t len, uint32_t *mask, size_t words)
425 {
426 if (dev->ctx->ops->read)
427 return dev->ctx->ops->read(dev, dst, len, mask, words);
428 else
429 return -ENOSYS;
430 }
431
iio_device_write_raw(const struct iio_device * dev,const void * src,size_t len)432 ssize_t iio_device_write_raw(const struct iio_device *dev,
433 const void *src, size_t len)
434 {
435 if (dev->ctx->ops->write)
436 return dev->ctx->ops->write(dev, src, len);
437 else
438 return -ENOSYS;
439 }
440
iio_device_attr_read(const struct iio_device * dev,const char * attr,char * dst,size_t len)441 ssize_t iio_device_attr_read(const struct iio_device *dev,
442 const char *attr, char *dst, size_t len)
443 {
444 if (dev->ctx->ops->read_device_attr)
445 return dev->ctx->ops->read_device_attr(dev,
446 attr, dst, len, IIO_ATTR_TYPE_DEVICE);
447 else
448 return -ENOSYS;
449 }
450
iio_device_attr_write_raw(const struct iio_device * dev,const char * attr,const void * src,size_t len)451 ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
452 const char *attr, const void *src, size_t len)
453 {
454 if (dev->ctx->ops->write_device_attr)
455 return dev->ctx->ops->write_device_attr(dev,
456 attr, src, len, IIO_ATTR_TYPE_DEVICE);
457 else
458 return -ENOSYS;
459 }
460
iio_device_attr_write(const struct iio_device * dev,const char * attr,const char * src)461 ssize_t iio_device_attr_write(const struct iio_device *dev,
462 const char *attr, const char *src)
463 {
464 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
465 }
466
iio_device_buffer_attr_read(const struct iio_device * dev,const char * attr,char * dst,size_t len)467 ssize_t iio_device_buffer_attr_read(const struct iio_device *dev,
468 const char *attr, char *dst, size_t len)
469 {
470 if (dev->ctx->ops->read_device_attr)
471 return dev->ctx->ops->read_device_attr(dev,
472 attr, dst, len, IIO_ATTR_TYPE_BUFFER);
473 else
474 return -ENOSYS;
475 }
476
iio_device_buffer_attr_write_raw(const struct iio_device * dev,const char * attr,const void * src,size_t len)477 ssize_t iio_device_buffer_attr_write_raw(const struct iio_device *dev,
478 const char *attr, const void *src, size_t len)
479 {
480 if (dev->ctx->ops->write_device_attr)
481 return dev->ctx->ops->write_device_attr(dev,
482 attr, src, len, IIO_ATTR_TYPE_BUFFER);
483 else
484 return -ENOSYS;
485 }
486
iio_device_buffer_attr_write(const struct iio_device * dev,const char * attr,const char * src)487 ssize_t iio_device_buffer_attr_write(const struct iio_device *dev,
488 const char *attr, const char *src)
489 {
490 return iio_device_buffer_attr_write_raw(dev, attr, src, strlen(src) + 1);
491 }
492
iio_device_set_data(struct iio_device * dev,void * data)493 void iio_device_set_data(struct iio_device *dev, void *data)
494 {
495 dev->userdata = data;
496 }
497
iio_device_get_data(const struct iio_device * dev)498 void * iio_device_get_data(const struct iio_device *dev)
499 {
500 return dev->userdata;
501 }
502
iio_device_is_trigger(const struct iio_device * dev)503 bool iio_device_is_trigger(const struct iio_device *dev)
504 {
505 /* A trigger has a name, an id which starts by "trigger",
506 * and zero channels. */
507
508 unsigned int nb = iio_device_get_channels_count(dev);
509 const char *name = iio_device_get_name(dev),
510 *id = iio_device_get_id(dev);
511 return ((nb == 0) && !!name &&
512 !strncmp(id, "trigger", sizeof("trigger") - 1));
513 }
514
iio_device_set_kernel_buffers_count(const struct iio_device * dev,unsigned int nb_buffers)515 int iio_device_set_kernel_buffers_count(const struct iio_device *dev,
516 unsigned int nb_buffers)
517 {
518 if (nb_buffers == 0)
519 return -EINVAL;
520 else if (dev->ctx->ops->set_kernel_buffers_count)
521 return dev->ctx->ops->set_kernel_buffers_count(dev, nb_buffers);
522 else
523 return -ENOSYS;
524 }
525
iio_device_get_trigger(const struct iio_device * dev,const struct iio_device ** trigger)526 int iio_device_get_trigger(const struct iio_device *dev,
527 const struct iio_device **trigger)
528 {
529 if (!trigger)
530 return -EINVAL;
531 else if (dev->ctx->ops->get_trigger)
532 return dev->ctx->ops->get_trigger(dev, trigger);
533 else
534 return -ENOSYS;
535 }
536
iio_device_set_trigger(const struct iio_device * dev,const struct iio_device * trigger)537 int iio_device_set_trigger(const struct iio_device *dev,
538 const struct iio_device *trigger)
539 {
540 if (trigger && !iio_device_is_trigger(trigger))
541 return -EINVAL;
542 else if (dev->ctx->ops->set_trigger)
543 return dev->ctx->ops->set_trigger(dev, trigger);
544 else
545 return -ENOSYS;
546 }
547
free_device(struct iio_device * dev)548 void free_device(struct iio_device *dev)
549 {
550 unsigned int i;
551 for (i = 0; i < dev->nb_attrs; i++)
552 free(dev->attrs[i]);
553 if (dev->nb_attrs)
554 free(dev->attrs);
555 for (i = 0; i < dev->nb_buffer_attrs; i++)
556 free(dev->buffer_attrs[i]);
557 if (dev->nb_buffer_attrs)
558 free(dev->buffer_attrs);
559 for (i = 0; i < dev->nb_debug_attrs; i++)
560 free(dev->debug_attrs[i]);
561 if (dev->nb_debug_attrs)
562 free(dev->debug_attrs);
563 for (i = 0; i < dev->nb_channels; i++)
564 free_channel(dev->channels[i]);
565 if (dev->nb_channels)
566 free(dev->channels);
567 if (dev->mask)
568 free(dev->mask);
569 if (dev->name)
570 free(dev->name);
571 if (dev->id)
572 free(dev->id);
573 free(dev);
574 }
575
iio_device_get_sample_size_mask(const struct iio_device * dev,const uint32_t * mask,size_t words)576 ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
577 const uint32_t *mask, size_t words)
578 {
579 ssize_t size = 0;
580 unsigned int i;
581 const struct iio_channel *prev = NULL;
582
583 if (words != (dev->nb_channels + 31) / 32)
584 return -EINVAL;
585
586 for (i = 0; i < dev->nb_channels; i++) {
587 const struct iio_channel *chn = dev->channels[i];
588 unsigned int length = chn->format.length / 8 *
589 chn->format.repeat;
590
591 if (chn->index < 0)
592 break;
593 if (!TEST_BIT(mask, chn->number))
594 continue;
595
596 if (prev && chn->index == prev->index) {
597 prev = chn;
598 continue;
599 }
600
601 if (size % length)
602 size += 2 * length - (size % length);
603 else
604 size += length;
605
606 prev = chn;
607 }
608 return size;
609 }
610
iio_device_get_sample_size(const struct iio_device * dev)611 ssize_t iio_device_get_sample_size(const struct iio_device *dev)
612 {
613 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
614 }
615
iio_device_attr_read_longlong(const struct iio_device * dev,const char * attr,long long * val)616 int iio_device_attr_read_longlong(const struct iio_device *dev,
617 const char *attr, long long *val)
618 {
619 char *end, buf[1024];
620 long long value;
621 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
622 if (ret < 0)
623 return (int) ret;
624
625 errno = 0;
626 value = strtoll(buf, &end, 0);
627 if (end == buf || errno == ERANGE)
628 return -EINVAL;
629 *val = value;
630 return 0;
631 }
632
iio_device_attr_read_bool(const struct iio_device * dev,const char * attr,bool * val)633 int iio_device_attr_read_bool(const struct iio_device *dev,
634 const char *attr, bool *val)
635 {
636 long long value;
637 int ret = iio_device_attr_read_longlong(dev, attr, &value);
638 if (ret < 0)
639 return ret;
640
641 *val = !!value;
642 return 0;
643 }
644
iio_device_attr_read_double(const struct iio_device * dev,const char * attr,double * val)645 int iio_device_attr_read_double(const struct iio_device *dev,
646 const char *attr, double *val)
647 {
648 char buf[1024];
649 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
650 if (ret < 0)
651 return (int) ret;
652 else
653 return read_double(buf, val);
654 }
655
iio_device_attr_write_longlong(const struct iio_device * dev,const char * attr,long long val)656 int iio_device_attr_write_longlong(const struct iio_device *dev,
657 const char *attr, long long val)
658 {
659 ssize_t ret;
660 char buf[1024];
661
662 iio_snprintf(buf, sizeof(buf), "%lld", val);
663 ret = iio_device_attr_write(dev, attr, buf);
664
665 return (int) (ret < 0 ? ret : 0);
666 }
667
iio_device_attr_write_double(const struct iio_device * dev,const char * attr,double val)668 int iio_device_attr_write_double(const struct iio_device *dev,
669 const char *attr, double val)
670 {
671 ssize_t ret;
672 char buf[1024];
673
674 ret = (ssize_t) write_double(buf, sizeof(buf), val);
675 if (!ret)
676 ret = iio_device_attr_write(dev, attr, buf);
677 return (int) (ret < 0 ? ret : 0);
678 }
679
iio_device_attr_write_bool(const struct iio_device * dev,const char * attr,bool val)680 int iio_device_attr_write_bool(const struct iio_device *dev,
681 const char *attr, bool val)
682 {
683 ssize_t ret;
684
685 if (val)
686 ret = iio_device_attr_write(dev, attr, "1");
687 else
688 ret = iio_device_attr_write(dev, attr, "0");
689
690 return (int) (ret < 0 ? ret : 0);
691 }
692
iio_device_buffer_attr_read_longlong(const struct iio_device * dev,const char * attr,long long * val)693 int iio_device_buffer_attr_read_longlong(const struct iio_device *dev,
694 const char *attr, long long *val)
695 {
696 char *end, buf[1024];
697 long long value;
698 ssize_t ret = iio_device_buffer_attr_read(dev, attr, buf, sizeof(buf));
699 if (ret < 0)
700 return (int) ret;
701
702 errno = 0;
703 value = strtoll(buf, &end, 0);
704 if (end == buf || errno == ERANGE)
705 return -EINVAL;
706 *val = value;
707 return 0;
708 }
709
iio_device_buffer_attr_read_bool(const struct iio_device * dev,const char * attr,bool * val)710 int iio_device_buffer_attr_read_bool(const struct iio_device *dev,
711 const char *attr, bool *val)
712 {
713 long long value;
714 int ret = iio_device_buffer_attr_read_longlong(dev, attr, &value);
715 if (ret < 0)
716 return ret;
717
718 *val = !!value;
719 return 0;
720 }
721
iio_device_buffer_attr_read_double(const struct iio_device * dev,const char * attr,double * val)722 int iio_device_buffer_attr_read_double(const struct iio_device *dev,
723 const char *attr, double *val)
724 {
725 char buf[1024];
726 ssize_t ret = iio_device_buffer_attr_read(dev, attr, buf, sizeof(buf));
727 if (ret < 0)
728 return (int) ret;
729 else
730 return read_double(buf, val);
731 }
732
iio_device_buffer_attr_write_longlong(const struct iio_device * dev,const char * attr,long long val)733 int iio_device_buffer_attr_write_longlong(const struct iio_device *dev,
734 const char *attr, long long val)
735 {
736 ssize_t ret;
737 char buf[1024];
738
739 iio_snprintf(buf, sizeof(buf), "%lld", val);
740 ret = iio_device_buffer_attr_write(dev, attr, buf);
741
742 return (int) (ret < 0 ? ret : 0);
743 }
744
iio_device_buffer_attr_write_double(const struct iio_device * dev,const char * attr,double val)745 int iio_device_buffer_attr_write_double(const struct iio_device *dev,
746 const char *attr, double val)
747 {
748 ssize_t ret;
749 char buf[1024];
750
751 ret = (ssize_t) write_double(buf, sizeof(buf), val);
752 if (!ret)
753 ret = iio_device_buffer_attr_write(dev, attr, buf);
754 return (int) (ret < 0 ? ret : 0);
755 }
756
iio_device_buffer_attr_write_bool(const struct iio_device * dev,const char * attr,bool val)757 int iio_device_buffer_attr_write_bool(const struct iio_device *dev,
758 const char *attr, bool val)
759 {
760 ssize_t ret;
761
762 if (val)
763 ret = iio_device_buffer_attr_write(dev, attr, "1");
764 else
765 ret = iio_device_buffer_attr_write(dev, attr, "0");
766
767 return (int) (ret < 0 ? ret : 0);
768 }
769
iio_device_debug_attr_read(const struct iio_device * dev,const char * attr,char * dst,size_t len)770 ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
771 const char *attr, char *dst, size_t len)
772 {
773 if (dev->ctx->ops->read_device_attr)
774 return dev->ctx->ops->read_device_attr(dev,
775 attr, dst, len, IIO_ATTR_TYPE_DEBUG);
776 else
777 return -ENOSYS;
778 }
779
iio_device_debug_attr_write_raw(const struct iio_device * dev,const char * attr,const void * src,size_t len)780 ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
781 const char *attr, const void *src, size_t len)
782 {
783 if (dev->ctx->ops->write_device_attr)
784 return dev->ctx->ops->write_device_attr(dev,
785 attr, src, len, IIO_ATTR_TYPE_DEBUG);
786 else
787 return -ENOSYS;
788 }
789
iio_device_debug_attr_write(const struct iio_device * dev,const char * attr,const char * src)790 ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
791 const char *attr, const char *src)
792 {
793 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
794 }
795
iio_device_get_debug_attrs_count(const struct iio_device * dev)796 unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
797 {
798 return dev->nb_debug_attrs;
799 }
800
iio_device_get_debug_attr(const struct iio_device * dev,unsigned int index)801 const char * iio_device_get_debug_attr(const struct iio_device *dev,
802 unsigned int index)
803 {
804 if (index >= dev->nb_debug_attrs)
805 return NULL;
806 else
807 return dev->debug_attrs[index];
808 }
809
iio_device_debug_attr_read_longlong(const struct iio_device * dev,const char * attr,long long * val)810 int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
811 const char *attr, long long *val)
812 {
813 char *end, buf[1024];
814 long long value;
815 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
816 if (ret < 0)
817 return (int) ret;
818
819 errno = 0;
820 value = strtoll(buf, &end, 0);
821 if (end == buf || errno == ERANGE)
822 return -EINVAL;
823 *val = value;
824 return 0;
825 }
826
iio_device_debug_attr_read_bool(const struct iio_device * dev,const char * attr,bool * val)827 int iio_device_debug_attr_read_bool(const struct iio_device *dev,
828 const char *attr, bool *val)
829 {
830 long long value;
831 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
832 if (ret < 0)
833 return ret;
834
835 *val = !!value;
836 return 0;
837 }
838
iio_device_debug_attr_read_double(const struct iio_device * dev,const char * attr,double * val)839 int iio_device_debug_attr_read_double(const struct iio_device *dev,
840 const char *attr, double *val)
841 {
842 char buf[1024];
843 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
844 if (ret < 0)
845 return (int) ret;
846 else
847 return read_double(buf, val);
848 }
849
iio_device_debug_attr_write_longlong(const struct iio_device * dev,const char * attr,long long val)850 int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
851 const char *attr, long long val)
852 {
853 ssize_t ret;
854 char buf[1024];
855
856 iio_snprintf(buf, sizeof(buf), "%lld", val);
857 ret = iio_device_debug_attr_write(dev, attr, buf);
858
859 return (int) (ret < 0 ? ret : 0);
860 }
861
iio_device_debug_attr_write_double(const struct iio_device * dev,const char * attr,double val)862 int iio_device_debug_attr_write_double(const struct iio_device *dev,
863 const char *attr, double val)
864 {
865 ssize_t ret;
866 char buf[1024];
867
868 ret = (ssize_t) write_double(buf, sizeof(buf), val);
869 if (!ret)
870 ret = iio_device_debug_attr_write(dev, attr, buf);
871 return (int) (ret < 0 ? ret : 0);
872 }
873
iio_device_debug_attr_write_bool(const struct iio_device * dev,const char * attr,bool val)874 int iio_device_debug_attr_write_bool(const struct iio_device *dev,
875 const char *attr, bool val)
876 {
877 ssize_t ret;
878
879 if (val)
880 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
881 else
882 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
883
884 return (int) (ret < 0 ? ret : 0);
885 }
886
iio_device_identify_filename(const struct iio_device * dev,const char * filename,struct iio_channel ** chn,const char ** attr)887 int iio_device_identify_filename(const struct iio_device *dev,
888 const char *filename, struct iio_channel **chn,
889 const char **attr)
890 {
891 unsigned int i;
892
893 for (i = 0; i < dev->nb_channels; i++) {
894 struct iio_channel *ch = dev->channels[i];
895 unsigned int j;
896
897 for (j = 0; j < ch->nb_attrs; j++) {
898 if (!strcmp(ch->attrs[j].filename, filename)) {
899 *attr = ch->attrs[j].name;
900 *chn = ch;
901 return 0;
902 }
903 }
904 }
905
906 for (i = 0; i < dev->nb_attrs; i++) {
907 /* Devices attributes are named after their filename */
908 if (!strcmp(dev->attrs[i], filename)) {
909 *attr = dev->attrs[i];
910 *chn = NULL;
911 return 0;
912 }
913 }
914
915 for (i = 0; i < dev->nb_debug_attrs; i++) {
916 if (!strcmp(dev->debug_attrs[i], filename)) {
917 *attr = dev->debug_attrs[i];
918 *chn = NULL;
919 return 0;
920 }
921 }
922
923 return -EINVAL;
924 }
925
iio_device_reg_write(struct iio_device * dev,uint32_t address,uint32_t value)926 int iio_device_reg_write(struct iio_device *dev,
927 uint32_t address, uint32_t value)
928 {
929 ssize_t ret;
930 char buf[1024];
931
932 iio_snprintf(buf, sizeof(buf), "0x%" PRIx32 " 0x%" PRIx32,
933 address, value);
934 ret = iio_device_debug_attr_write(dev, "direct_reg_access", buf);
935
936 return (int) (ret < 0 ? ret : 0);
937 }
938
iio_device_reg_read(struct iio_device * dev,uint32_t address,uint32_t * value)939 int iio_device_reg_read(struct iio_device *dev,
940 uint32_t address, uint32_t *value)
941 {
942 /* NOTE: There is a race condition here. But it is extremely unlikely to
943 * happen, and as this is a debug function, it shouldn't be used for
944 * something else than debug. */
945
946 long long val;
947 int ret = iio_device_debug_attr_write_longlong(dev,
948 "direct_reg_access", (long long) address);
949 if (ret < 0)
950 return ret;
951
952 ret = iio_device_debug_attr_read_longlong(dev,
953 "direct_reg_access", &val);
954 if (!ret)
955 *value = (uint32_t) val;
956 return ret;
957 }
958
read_each_attr(struct iio_device * dev,enum iio_attr_type type,int (* cb)(struct iio_device * dev,const char * attr,const char * val,size_t len,void * d),void * data)959 static int read_each_attr(struct iio_device *dev, enum iio_attr_type type,
960 int (*cb)(struct iio_device *dev,
961 const char *attr, const char *val, size_t len, void *d),
962 void *data)
963 {
964 int ret, buf_size;
965 char *buf, *ptr;
966 unsigned int i, count;
967
968 /* We need a big buffer here; 1 MiB should be enough */
969 buf = malloc(0x100000);
970 if (!buf)
971 return -ENOMEM;
972
973 switch(type){
974 case IIO_ATTR_TYPE_DEVICE:
975 count = iio_device_get_attrs_count(dev);
976 ret = (int) iio_device_attr_read(dev,
977 NULL, buf, 0x100000);
978 break;
979 case IIO_ATTR_TYPE_DEBUG:
980 count = iio_device_get_debug_attrs_count(dev);
981 ret = (int) iio_device_debug_attr_read(dev,
982 NULL, buf, 0x100000);
983 break;
984 case IIO_ATTR_TYPE_BUFFER:
985 count = iio_device_get_buffer_attrs_count(dev);
986 ret = (int) iio_device_buffer_attr_read(dev,
987 NULL, buf, 0x100000);
988 break;
989 default:
990 ret = -EINVAL;
991 count = 0;
992 break;
993 }
994
995 if (ret < 0)
996 goto err_free_buf;
997
998 ptr = buf;
999 buf_size = ret;
1000
1001 for (i = 0; i < count; i++) {
1002 const char *attr;
1003 int32_t len;
1004
1005 if (buf_size < 4) {
1006 ret = -EPROTO;
1007 break;
1008 }
1009
1010 len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
1011 ptr += 4;
1012 buf_size -= 4;
1013
1014 if (len > 0 && buf_size < len) {
1015 ret = -EPROTO;
1016 break;
1017 }
1018
1019 switch(type){
1020 case IIO_ATTR_TYPE_DEVICE:
1021 attr = iio_device_get_attr(dev, i);
1022 break;
1023 case IIO_ATTR_TYPE_DEBUG:
1024 attr = iio_device_get_debug_attr(dev, i);
1025 break;
1026 case IIO_ATTR_TYPE_BUFFER:
1027 attr = iio_device_get_buffer_attr(dev, i);
1028 break;
1029 default:
1030 attr = NULL;
1031 break;
1032 }
1033
1034 if (len > 0) {
1035 ret = cb(dev, attr, ptr, (size_t) len, data);
1036 if (ret < 0)
1037 goto err_free_buf;
1038
1039 if (len & 0x3)
1040 len = ((len >> 2) + 1) << 2;
1041 ptr += len;
1042 if (len >= buf_size)
1043 buf_size = 0;
1044 else
1045 buf_size -= len;
1046 }
1047 }
1048
1049 err_free_buf:
1050 free(buf);
1051 return ret < 0 ? ret : 0;
1052 }
1053
write_each_attr(struct iio_device * dev,enum iio_attr_type type,ssize_t (* cb)(struct iio_device * dev,const char * attr,void * buf,size_t len,void * d),void * data)1054 static int write_each_attr(struct iio_device *dev, enum iio_attr_type type,
1055 ssize_t (*cb)(struct iio_device *dev,
1056 const char *attr, void *buf, size_t len, void *d),
1057 void *data)
1058 {
1059 char *buf, *ptr;
1060 unsigned int i, count;
1061 size_t len = 0x100000;
1062 int ret;
1063
1064 /* We need a big buffer here; 1 MiB should be enough */
1065 buf = malloc(len);
1066 if (!buf)
1067 return -ENOMEM;
1068
1069 ptr = buf;
1070
1071 switch(type){
1072 case IIO_ATTR_TYPE_DEVICE:
1073 count = iio_device_get_attrs_count(dev);
1074 break;
1075 case IIO_ATTR_TYPE_DEBUG:
1076 count = iio_device_get_debug_attrs_count(dev);
1077 break;
1078 case IIO_ATTR_TYPE_BUFFER:
1079 count = iio_device_get_buffer_attrs_count(dev);
1080 break;
1081 default:
1082 ret = -EINVAL;
1083 goto err_free_buf;
1084 }
1085
1086 for (i = 0; i < count; i++) {
1087 const char *attr;
1088
1089 switch(type){
1090 case IIO_ATTR_TYPE_DEVICE:
1091 attr = iio_device_get_attr(dev, i);
1092 break;
1093 case IIO_ATTR_TYPE_DEBUG:
1094 attr = iio_device_get_debug_attr(dev, i);
1095 break;
1096 case IIO_ATTR_TYPE_BUFFER:
1097 attr = iio_device_get_buffer_attr(dev, i);
1098 break;
1099 default:
1100 attr = NULL;
1101 break;
1102 }
1103
1104 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
1105 if (ret < 0)
1106 goto err_free_buf;
1107
1108 *(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
1109 ptr += 4;
1110 len -= 4;
1111
1112 if (ret > 0) {
1113 if (ret & 0x3)
1114 ret = ((ret >> 2) + 1) << 2;
1115 ptr += ret;
1116 len -= ret;
1117 }
1118 }
1119
1120 switch(type){
1121 case IIO_ATTR_TYPE_DEVICE:
1122 ret = (int) iio_device_attr_write_raw(dev,
1123 NULL, buf, ptr - buf);
1124 break;
1125 case IIO_ATTR_TYPE_DEBUG:
1126 ret = (int) iio_device_debug_attr_write_raw(dev,
1127 NULL, buf, ptr - buf);
1128 break;
1129 case IIO_ATTR_TYPE_BUFFER:
1130 ret = (int) iio_device_buffer_attr_write_raw(dev,
1131 NULL, buf, ptr - buf);
1132 break;
1133 default:
1134 ret = -EINVAL;
1135 break;
1136 }
1137
1138 err_free_buf:
1139 free(buf);
1140 return ret < 0 ? ret : 0;
1141 }
1142
iio_device_debug_attr_read_all(struct iio_device * dev,int (* cb)(struct iio_device * dev,const char * attr,const char * val,size_t len,void * d),void * data)1143 int iio_device_debug_attr_read_all(struct iio_device *dev,
1144 int (*cb)(struct iio_device *dev,
1145 const char *attr, const char *val, size_t len, void *d),
1146 void *data)
1147 {
1148 return read_each_attr(dev, IIO_ATTR_TYPE_DEBUG, cb, data);
1149 }
1150
iio_device_buffer_attr_read_all(struct iio_device * dev,int (* cb)(struct iio_device * dev,const char * attr,const char * val,size_t len,void * d),void * data)1151 int iio_device_buffer_attr_read_all(struct iio_device *dev,
1152 int (*cb)(struct iio_device *dev,
1153 const char *attr, const char *val, size_t len, void *d),
1154 void *data)
1155 {
1156 return read_each_attr(dev, IIO_ATTR_TYPE_BUFFER, cb, data);
1157 }
1158
iio_device_attr_read_all(struct iio_device * dev,int (* cb)(struct iio_device * dev,const char * attr,const char * val,size_t len,void * d),void * data)1159 int iio_device_attr_read_all(struct iio_device *dev,
1160 int (*cb)(struct iio_device *dev,
1161 const char *attr, const char *val, size_t len, void *d),
1162 void *data)
1163 {
1164 return read_each_attr(dev, IIO_ATTR_TYPE_DEVICE ,cb, data);
1165 }
1166
iio_device_debug_attr_write_all(struct iio_device * dev,ssize_t (* cb)(struct iio_device * dev,const char * attr,void * buf,size_t len,void * d),void * data)1167 int iio_device_debug_attr_write_all(struct iio_device *dev,
1168 ssize_t (*cb)(struct iio_device *dev,
1169 const char *attr, void *buf, size_t len, void *d),
1170 void *data)
1171 {
1172 return write_each_attr(dev, IIO_ATTR_TYPE_DEBUG, cb, data);
1173 }
1174
iio_device_buffer_attr_write_all(struct iio_device * dev,ssize_t (* cb)(struct iio_device * dev,const char * attr,void * buf,size_t len,void * d),void * data)1175 int iio_device_buffer_attr_write_all(struct iio_device *dev,
1176 ssize_t (*cb)(struct iio_device *dev,
1177 const char *attr, void *buf, size_t len, void *d),
1178 void *data)
1179 {
1180 return write_each_attr(dev, IIO_ATTR_TYPE_BUFFER, cb, data);
1181 }
1182
iio_device_attr_write_all(struct iio_device * dev,ssize_t (* cb)(struct iio_device * dev,const char * attr,void * buf,size_t len,void * d),void * data)1183 int iio_device_attr_write_all(struct iio_device *dev,
1184 ssize_t (*cb)(struct iio_device *dev,
1185 const char *attr, void *buf, size_t len, void *d),
1186 void *data)
1187 {
1188 return write_each_attr(dev, IIO_ATTR_TYPE_DEVICE, cb, data);
1189 }
1190
iio_device_get_context(const struct iio_device * dev)1191 const struct iio_context * iio_device_get_context(const struct iio_device *dev)
1192 {
1193 return dev->ctx;
1194 }
1195