blob: 9b818c319a18c655b7c37bb1ea0a0cc82d62c2bf [file] [log] [blame]
Paul Cercueilbb4401d2014-02-28 16:10:49 +01001/*
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
Paul Cercueil42090d12014-02-24 12:32:23 +010019#include "debug.h"
Paul Cercueil0b2ce712014-02-17 15:04:18 +010020#include "iio-private.h"
21
Paul Cercueil6a013602014-02-19 12:37:39 +010022#include <errno.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010023#include <stdio.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010024#include <string.h>
25
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020026static char *get_attr_xml(const char *attr, size_t *length, bool is_debug)
Paul Cercueil42090d12014-02-24 12:32:23 +010027{
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020028 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr)
29 + (!is_debug ? 0 : sizeof("debug-") - 1);
Paul Cercueil42090d12014-02-24 12:32:23 +010030 char *str = malloc(len);
31 if (!str) {
32 ERROR("Unable to allocate memory\n");
33 return NULL;
34 }
35
36 *length = len - 1; /* Skip the \0 */
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020037 if (is_debug)
38 snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
39 else
40 snprintf(str, len, "<attribute name=\"%s\" />", attr);
Paul Cercueil42090d12014-02-24 12:32:23 +010041 return str;
42}
43
44/* Returns a string containing the XML representation of this device */
45char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
46{
Paul Cercueil8c29e412014-04-07 09:46:45 +020047 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
48 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020049 char *ptr, *str, **attrs, **channels, **debug_attrs;
50 size_t *attrs_len, *channels_len, *debug_attrs_len;
51 unsigned int i, j, k;
Paul Cercueil5822ab62014-04-04 13:29:17 +020052
53 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
54 if (!attrs_len)
55 return NULL;
56
57 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
58 if (!attrs)
59 goto err_free_attrs_len;
60
Paul Cercueil42090d12014-02-24 12:32:23 +010061 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020062 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
Paul Cercueil42090d12014-02-24 12:32:23 +010063 if (!xml)
64 goto err_free_attrs;
65 attrs[i] = xml;
66 len += attrs_len[i];
67 }
68
Paul Cercueil8c29e412014-04-07 09:46:45 +020069 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
70 if (!channels_len)
71 goto err_free_attrs;
72
73 channels = malloc(dev->nb_channels * sizeof(*channels));
74 if (!channels)
75 goto err_free_channels_len;
76
Paul Cercueil42090d12014-02-24 12:32:23 +010077 for (j = 0; j < dev->nb_channels; j++) {
78 char *xml = iio_channel_get_xml(dev->channels[j],
79 &channels_len[j]);
80 if (!xml)
81 goto err_free_channels;
82 channels[j] = xml;
83 len += channels_len[j];
84 }
85
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020086 debug_attrs_len = malloc(dev->nb_debug_attrs *
87 sizeof(*debug_attrs_len));
88 if (!debug_attrs_len)
89 goto err_free_channels;
90
91 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
92 if (!debug_attrs)
93 goto err_free_debug_attrs_len;
94
95 for (k = 0; k < dev->nb_debug_attrs; k++) {
96 char *xml = get_attr_xml(dev->debug_attrs[k],
97 &debug_attrs_len[k], true);
98 if (!xml)
99 goto err_free_debug_attrs;
100 debug_attrs[k] = xml;
101 len += debug_attrs_len[k];
102 }
103
Paul Cercueil42090d12014-02-24 12:32:23 +0100104 str = malloc(len);
105 if (!str)
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200106 goto err_free_debug_attrs;
Paul Cercueil42090d12014-02-24 12:32:23 +0100107
Paul Cercueil8c29e412014-04-07 09:46:45 +0200108 snprintf(str, len, "<device id=\"%s\"", dev->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100109 ptr = strrchr(str, '\0');
110
111 if (dev->name) {
112 sprintf(ptr, " name=\"%s\"", dev->name);
113 ptr = strrchr(ptr, '\0');
114 }
115
116 strcpy(ptr, " >");
117 ptr += 2;
118
119 for (i = 0; i < dev->nb_channels; i++) {
120 strcpy(ptr, channels[i]);
121 ptr += channels_len[i];
122 free(channels[i]);
123 }
124
Paul Cercueil5822ab62014-04-04 13:29:17 +0200125 free(channels);
126 free(channels_len);
127
Paul Cercueil42090d12014-02-24 12:32:23 +0100128 for (i = 0; i < dev->nb_attrs; i++) {
129 strcpy(ptr, attrs[i]);
130 ptr += attrs_len[i];
131 free(attrs[i]);
132 }
133
Paul Cercueil5822ab62014-04-04 13:29:17 +0200134 free(attrs);
135 free(attrs_len);
136
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200137 for (i = 0; i < dev->nb_debug_attrs; i++) {
138 strcpy(ptr, debug_attrs[i]);
139 ptr += debug_attrs_len[i];
140 free(debug_attrs[i]);
141 }
142
143 free(debug_attrs);
144 free(debug_attrs_len);
145
Paul Cercueil42090d12014-02-24 12:32:23 +0100146 strcpy(ptr, "</device>");
147 *length = ptr - str + sizeof("</device>") - 1;
148 return str;
149
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200150err_free_debug_attrs:
151 while (k--)
152 free(debug_attrs[k]);
153 free(debug_attrs);
154err_free_debug_attrs_len:
155 free(debug_attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100156err_free_channels:
157 while (j--)
158 free(channels[j]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200159 free(channels);
160err_free_channels_len:
161 free(channels_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100162err_free_attrs:
163 while (i--)
164 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200165 free(attrs);
166err_free_attrs_len:
167 free(attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100168 return NULL;
169}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100170
171const char * iio_device_get_id(const struct iio_device *dev)
172{
173 return dev->id;
174}
175
176const char * iio_device_get_name(const struct iio_device *dev)
177{
178 return dev->name;
179}
180
181unsigned int iio_device_get_channels_count(const struct iio_device *dev)
182{
183 return dev->nb_channels;
184}
185
186struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
187 unsigned int index)
188{
189 if (index >= dev->nb_channels)
190 return NULL;
191 else
192 return dev->channels[index];
193}
194
Paul Cercueil17512b02014-03-28 11:15:24 +0100195struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100196 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100197{
198 unsigned int i;
199 for (i = 0; i < dev->nb_channels; i++) {
200 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100201 if (iio_channel_is_output(chn) != output)
202 continue;
203
Paul Cercueil17512b02014-03-28 11:15:24 +0100204 if (!strcmp(chn->id, name) ||
205 (chn->name && !strcmp(chn->name, name)))
206 return chn;
207 }
208 return NULL;
209}
210
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100211unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
212{
213 return dev->nb_attrs;
214}
215
216const char * iio_device_get_attr(const struct iio_device *dev,
217 unsigned int index)
218{
219 if (index >= dev->nb_attrs)
220 return NULL;
221 else
222 return dev->attrs[index];
223}
224
Paul Cercueil4f838d02014-03-28 11:26:15 +0100225const char * iio_device_find_attr(const struct iio_device *dev,
226 const char *name)
227{
228 unsigned int i;
229 for (i = 0; i < dev->nb_attrs; i++) {
230 const char *attr = dev->attrs[i];
231 if (!strcmp(attr, name))
232 return attr;
233 }
234 return NULL;
235}
236
Paul Cercueil3cc3a002014-03-24 13:44:11 +0100237static int iio_device_open_mask(const struct iio_device *dev,
Paul Cercueil93f17052014-04-02 13:56:27 +0200238 size_t samples_count, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100239{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100240 unsigned int i;
241 bool has_channels = false;
242
243 for (i = 0; !has_channels && i < words; i++)
244 has_channels = !!mask[i];
245 if (!has_channels)
246 return -EINVAL;
247
Paul Cercueilec1760d2014-02-21 11:31:20 +0100248 if (dev->ctx->ops->open)
Paul Cercueil93f17052014-04-02 13:56:27 +0200249 return dev->ctx->ops->open(dev, samples_count, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100250 else
251 return -ENOSYS;
252}
253
Paul Cercueil93f17052014-04-02 13:56:27 +0200254int iio_device_open(const struct iio_device *dev, size_t samples_count)
Paul Cercueile1311222014-03-12 15:46:16 +0100255{
256 size_t nb = (dev->nb_channels + 31) / 32;
257 uint32_t *mask = NULL;
258 unsigned int i;
259 int ret;
260
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100261 if (nb == 0)
262 return -EINVAL;
263
264 mask = calloc(nb, sizeof(*mask));
265 if (!mask)
266 return -ENOMEM;
Paul Cercueile1311222014-03-12 15:46:16 +0100267
268 for (i = 0; i < dev->nb_channels; i++) {
269 struct iio_channel *chn = dev->channels[i];
270 if (iio_channel_is_enabled(chn) && chn->index >= 0)
271 SET_BIT(mask, chn->index);
272 }
273
Paul Cercueil93f17052014-04-02 13:56:27 +0200274 ret = iio_device_open_mask(dev, samples_count, mask, nb);
Paul Cercueile1311222014-03-12 15:46:16 +0100275 free(mask);
276 return ret;
277}
278
Paul Cercueilec1760d2014-02-21 11:31:20 +0100279int iio_device_close(const struct iio_device *dev)
280{
281 if (dev->ctx->ops->close)
282 return dev->ctx->ops->close(dev);
283 else
284 return -ENOSYS;
285}
286
287ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100288 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100289{
290 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100291 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100292 else
293 return -ENOSYS;
294}
295
296ssize_t iio_device_write_raw(const struct iio_device *dev,
297 const void *src, size_t len)
298{
299 if (dev->ctx->ops->write)
300 return dev->ctx->ops->write(dev, src, len);
301 else
302 return -ENOSYS;
303}
304
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100305ssize_t iio_device_attr_read(const struct iio_device *dev,
306 const char *attr, char *dst, size_t len)
307{
Paul Cercueil6a013602014-02-19 12:37:39 +0100308 if (dev->ctx->ops->read_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200309 return dev->ctx->ops->read_device_attr(dev,
310 attr, dst, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100311 else
312 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100313}
314
315ssize_t iio_device_attr_write(const struct iio_device *dev,
316 const char *attr, const char *src)
317{
Paul Cercueil6a013602014-02-19 12:37:39 +0100318 if (dev->ctx->ops->write_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200319 return dev->ctx->ops->write_device_attr(dev,
320 attr, src, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100321 else
322 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100323}
Paul Cercueil00236242014-02-18 15:09:06 +0100324
Paul Cercueild96e61f2014-03-07 16:13:37 +0100325void iio_device_set_data(struct iio_device *dev, void *data)
326{
327 dev->userdata = data;
328}
329
330void * iio_device_get_data(const struct iio_device *dev)
331{
332 return dev->userdata;
333}
334
Paul Cercueil3156f632014-03-10 11:22:55 +0100335bool iio_device_is_trigger(const struct iio_device *dev)
336{
337 /* A trigger has a name, an id which starts by "trigger",
338 * and zero channels. */
339
340 unsigned int nb = iio_device_get_channels_count(dev);
341 const char *name = iio_device_get_name(dev),
342 *id = iio_device_get_id(dev);
343 return ((nb == 0) && !!name &&
344 !strncmp(id, "trigger", sizeof("trigger") - 1));
345}
346
Paul Cercueil24ffa532014-03-10 12:39:58 +0100347int iio_device_get_trigger(const struct iio_device *dev,
348 const struct iio_device **trigger)
349{
350 if (!trigger)
351 return -EINVAL;
352 else if (dev->ctx->ops->get_trigger)
353 return dev->ctx->ops->get_trigger(dev, trigger);
354 else
355 return -ENOSYS;
356}
357
358int iio_device_set_trigger(const struct iio_device *dev,
359 const struct iio_device *trigger)
360{
361 if (trigger && !iio_device_is_trigger(trigger))
362 return -EINVAL;
363 else if (dev->ctx->ops->set_trigger)
364 return dev->ctx->ops->set_trigger(dev, trigger);
365 else
366 return -ENOSYS;
367}
368
Paul Cercueil00236242014-02-18 15:09:06 +0100369void free_device(struct iio_device *dev)
370{
371 unsigned int i;
372 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200373 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100374 if (dev->nb_attrs)
375 free(dev->attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200376 for (i = 0; i < dev->nb_debug_attrs; i++)
377 free(dev->debug_attrs[i]);
378 if (dev->nb_debug_attrs)
379 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100380 for (i = 0; i < dev->nb_channels; i++)
381 free_channel(dev->channels[i]);
382 if (dev->nb_channels)
383 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100384 if (dev->mask)
385 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100386 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200387 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100388 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200389 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100390 free(dev);
391}
Paul Cercueil1a474732014-03-17 11:38:34 +0100392
Paul Cercueil645ab972014-03-24 14:36:12 +0100393ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil1a474732014-03-17 11:38:34 +0100394 uint32_t *mask, size_t words)
395{
396 ssize_t size = 0;
397 unsigned int i;
398
399 if (words != (dev->nb_channels + 31) / 32)
400 return -EINVAL;
401
402 for (i = 0; i < dev->nb_channels; i++) {
403 const struct iio_channel *chn = dev->channels[i];
404 unsigned int length = chn->format.length / 8;
405
406 if (chn->index < 0)
407 break;
408 if (!TEST_BIT(mask, chn->index))
409 continue;
410
411 if (size % length)
412 size += 2 * length - (size % length);
413 else
414 size += length;
415 }
416 return size;
417}
Paul Cercueil46825942014-03-18 14:28:49 +0100418
Paul Cercueil645ab972014-03-24 14:36:12 +0100419ssize_t iio_device_get_sample_size(const struct iio_device *dev)
420{
421 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
422}
423
Paul Cercueil46825942014-03-18 14:28:49 +0100424ssize_t iio_device_process_samples(const struct iio_device *dev,
425 uint32_t *mask, size_t words, void *buf, size_t len,
426 ssize_t (*cb)(const struct iio_channel *, void *, void *),
427 void *data)
428{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200429 uintptr_t ptr = (uintptr_t) buf, end = ptr + len;
Paul Cercueil46825942014-03-18 14:28:49 +0100430 unsigned int i;
431 ssize_t processed = 0,
Paul Cercueil645ab972014-03-24 14:36:12 +0100432 sample_size = iio_device_get_sample_size_mask(dev, mask, words);
Paul Cercueil46825942014-03-18 14:28:49 +0100433 if (sample_size <= 0)
434 return -EINVAL;
435
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200436 while (end - ptr >= (size_t) sample_size) {
Paul Cercueil46825942014-03-18 14:28:49 +0100437 for (i = 0; i < dev->nb_channels; i++) {
438 const struct iio_channel *chn = dev->channels[i];
439 unsigned int length = chn->format.length / 8;
440 ssize_t ret;
441
442 if (chn->index < 0) {
443 ERROR("Channel %s has negative index\n",
444 chn->id);
445 break;
446 }
447
448 if (!TEST_BIT(mask, chn->index))
449 continue;
450
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200451 if (ptr % length)
452 ptr += length - (ptr % length);
Paul Cercueil46825942014-03-18 14:28:49 +0100453
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200454 ret = cb(chn, (void *) ptr, data);
Paul Cercueil46825942014-03-18 14:28:49 +0100455 if (ret < 0)
456 return ret;
457 else
458 processed += ret;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200459 ptr += length;
Paul Cercueil46825942014-03-18 14:28:49 +0100460 }
461 }
462 return processed;
463}
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200464
465int iio_device_attr_read_longlong(const struct iio_device *dev,
466 const char *attr, long long *val)
467{
468 char *end, buf[1024];
469 long long value;
470 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
471 if (ret < 0)
472 return (int) ret;
473
474 value = strtoll(buf, &end, 0);
475 if (end == buf)
476 return -EINVAL;
477 *val = value;
478 return 0;
479}
480
481int iio_device_attr_read_bool(const struct iio_device *dev,
482 const char *attr, bool *val)
483{
484 long long value;
485 int ret = iio_device_attr_read_longlong(dev, attr, &value);
486 if (ret < 0)
487 return ret;
488
489 *val = !!value;
490 return 0;
491}
492
493int iio_device_attr_read_double(const struct iio_device *dev,
494 const char *attr, double *val)
495{
496 char *end, buf[1024];
497 double value;
498 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
499 if (ret < 0)
500 return (int) ret;
501
502 value = strtod(buf, &end);
503 if (end == buf)
504 return -EINVAL;
505 *val = value;
506 return 0;
507}
508
509int iio_device_attr_write_longlong(const struct iio_device *dev,
510 const char *attr, long long val)
511{
512 char buf[1024];
513 snprintf(buf, sizeof(buf), "%lld", val);
514 return iio_device_attr_write(dev, attr, buf);
515}
516
517int iio_device_attr_write_double(const struct iio_device *dev,
518 const char *attr, double val)
519{
520 char buf[1024];
521 snprintf(buf, sizeof(buf), "%lf", val);
522 return iio_device_attr_write(dev, attr, buf);
523}
524
525int iio_device_attr_write_bool(const struct iio_device *dev,
526 const char *attr, bool val)
527{
528 if (val)
529 return iio_device_attr_write(dev, attr, "1");
530 else
531 return iio_device_attr_write(dev, attr, "0");
532}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200533
534ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
535 const char *attr, char *dst, size_t len)
536{
537 if (dev->ctx->ops->read_device_attr)
538 return dev->ctx->ops->read_device_attr(dev,
539 attr, dst, len, true);
540 else
541 return -ENOSYS;
542}
543
544ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
545 const char *attr, const char *src)
546{
547 if (dev->ctx->ops->write_device_attr)
548 return dev->ctx->ops->write_device_attr(dev,
549 attr, src, true);
550 else
551 return -ENOSYS;
552}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200553
554unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
555{
556 return dev->nb_debug_attrs;
557}
558
559const char * iio_device_get_debug_attr(const struct iio_device *dev,
560 unsigned int index)
561{
562 if (index >= dev->nb_debug_attrs)
563 return NULL;
564 else
565 return dev->debug_attrs[index];
566}
Paul Cercueile3960742014-04-15 16:00:50 +0200567
568int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
569 const char *attr, long long *val)
570{
571 char *end, buf[1024];
572 long long value;
573 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
574 if (ret < 0)
575 return (int) ret;
576
577 value = strtoll(buf, &end, 0);
578 if (end == buf)
579 return -EINVAL;
580 *val = value;
581 return 0;
582}
583
584int iio_device_debug_attr_read_bool(const struct iio_device *dev,
585 const char *attr, bool *val)
586{
587 long long value;
588 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
589 if (ret < 0)
590 return ret;
591
592 *val = !!value;
593 return 0;
594}
595
596int iio_device_debug_attr_read_double(const struct iio_device *dev,
597 const char *attr, double *val)
598{
599 char *end, buf[1024];
600 double value;
601 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
602 if (ret < 0)
603 return (int) ret;
604
605 value = strtod(buf, &end);
606 if (end == buf)
607 return -EINVAL;
608 *val = value;
609 return 0;
610}
611
612int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
613 const char *attr, long long val)
614{
615 char buf[1024];
616 snprintf(buf, sizeof(buf), "%lld", val);
617 return iio_device_debug_attr_write(dev, attr, buf);
618}
619
620int iio_device_debug_attr_write_double(const struct iio_device *dev,
621 const char *attr, double val)
622{
623 char buf[1024];
624 snprintf(buf, sizeof(buf), "%lf", val);
625 return iio_device_debug_attr_write(dev, attr, buf);
626}
627
628int iio_device_debug_attr_write_bool(const struct iio_device *dev,
629 const char *attr, bool val)
630{
631 if (val)
632 return iio_device_debug_attr_write(dev, attr, "1");
633 else
634 return iio_device_debug_attr_write(dev, attr, "0");
635}