blob: d45c5022d631fab87d48a80757f8d55ca96cb980 [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
Paul Cercueilcecda352014-05-06 18:14:29 +0200315ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
316 const char *attr, const void *src, size_t len)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100317{
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,
Paul Cercueilcecda352014-05-06 18:14:29 +0200320 attr, src, len, 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 Cercueilcecda352014-05-06 18:14:29 +0200325ssize_t iio_device_attr_write(const struct iio_device *dev,
326 const char *attr, const char *src)
327{
328 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
329}
330
Paul Cercueild96e61f2014-03-07 16:13:37 +0100331void iio_device_set_data(struct iio_device *dev, void *data)
332{
333 dev->userdata = data;
334}
335
336void * iio_device_get_data(const struct iio_device *dev)
337{
338 return dev->userdata;
339}
340
Paul Cercueil3156f632014-03-10 11:22:55 +0100341bool iio_device_is_trigger(const struct iio_device *dev)
342{
343 /* A trigger has a name, an id which starts by "trigger",
344 * and zero channels. */
345
346 unsigned int nb = iio_device_get_channels_count(dev);
347 const char *name = iio_device_get_name(dev),
348 *id = iio_device_get_id(dev);
349 return ((nb == 0) && !!name &&
350 !strncmp(id, "trigger", sizeof("trigger") - 1));
351}
352
Paul Cercueil24ffa532014-03-10 12:39:58 +0100353int iio_device_get_trigger(const struct iio_device *dev,
354 const struct iio_device **trigger)
355{
356 if (!trigger)
357 return -EINVAL;
358 else if (dev->ctx->ops->get_trigger)
359 return dev->ctx->ops->get_trigger(dev, trigger);
360 else
361 return -ENOSYS;
362}
363
364int iio_device_set_trigger(const struct iio_device *dev,
365 const struct iio_device *trigger)
366{
367 if (trigger && !iio_device_is_trigger(trigger))
368 return -EINVAL;
369 else if (dev->ctx->ops->set_trigger)
370 return dev->ctx->ops->set_trigger(dev, trigger);
371 else
372 return -ENOSYS;
373}
374
Paul Cercueil00236242014-02-18 15:09:06 +0100375void free_device(struct iio_device *dev)
376{
377 unsigned int i;
378 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200379 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100380 if (dev->nb_attrs)
381 free(dev->attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200382 for (i = 0; i < dev->nb_debug_attrs; i++)
383 free(dev->debug_attrs[i]);
384 if (dev->nb_debug_attrs)
385 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100386 for (i = 0; i < dev->nb_channels; i++)
387 free_channel(dev->channels[i]);
388 if (dev->nb_channels)
389 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100390 if (dev->mask)
391 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100392 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200393 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100394 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200395 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100396 free(dev);
397}
Paul Cercueil1a474732014-03-17 11:38:34 +0100398
Paul Cercueil645ab972014-03-24 14:36:12 +0100399ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil1a474732014-03-17 11:38:34 +0100400 uint32_t *mask, size_t words)
401{
402 ssize_t size = 0;
403 unsigned int i;
404
405 if (words != (dev->nb_channels + 31) / 32)
406 return -EINVAL;
407
408 for (i = 0; i < dev->nb_channels; i++) {
409 const struct iio_channel *chn = dev->channels[i];
410 unsigned int length = chn->format.length / 8;
411
412 if (chn->index < 0)
413 break;
414 if (!TEST_BIT(mask, chn->index))
415 continue;
416
417 if (size % length)
418 size += 2 * length - (size % length);
419 else
420 size += length;
421 }
422 return size;
423}
Paul Cercueil46825942014-03-18 14:28:49 +0100424
Paul Cercueil645ab972014-03-24 14:36:12 +0100425ssize_t iio_device_get_sample_size(const struct iio_device *dev)
426{
427 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
428}
429
Paul Cercueil46825942014-03-18 14:28:49 +0100430ssize_t iio_device_process_samples(const struct iio_device *dev,
431 uint32_t *mask, size_t words, void *buf, size_t len,
432 ssize_t (*cb)(const struct iio_channel *, void *, void *),
433 void *data)
434{
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200435 uintptr_t ptr = (uintptr_t) buf, end = ptr + len;
Paul Cercueil46825942014-03-18 14:28:49 +0100436 unsigned int i;
437 ssize_t processed = 0,
Paul Cercueil645ab972014-03-24 14:36:12 +0100438 sample_size = iio_device_get_sample_size_mask(dev, mask, words);
Paul Cercueil46825942014-03-18 14:28:49 +0100439 if (sample_size <= 0)
440 return -EINVAL;
441
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200442 while (end - ptr >= (size_t) sample_size) {
Paul Cercueil46825942014-03-18 14:28:49 +0100443 for (i = 0; i < dev->nb_channels; i++) {
444 const struct iio_channel *chn = dev->channels[i];
445 unsigned int length = chn->format.length / 8;
446 ssize_t ret;
447
Paul Cercueilc3110452014-04-28 15:52:16 +0200448 if (chn->index < 0)
Paul Cercueil46825942014-03-18 14:28:49 +0100449 break;
Paul Cercueil46825942014-03-18 14:28:49 +0100450
451 if (!TEST_BIT(mask, chn->index))
452 continue;
453
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200454 if (ptr % length)
455 ptr += length - (ptr % length);
Paul Cercueil46825942014-03-18 14:28:49 +0100456
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200457 ret = cb(chn, (void *) ptr, data);
Paul Cercueil46825942014-03-18 14:28:49 +0100458 if (ret < 0)
459 return ret;
460 else
461 processed += ret;
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200462 ptr += length;
Paul Cercueil46825942014-03-18 14:28:49 +0100463 }
464 }
465 return processed;
466}
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200467
468int iio_device_attr_read_longlong(const struct iio_device *dev,
469 const char *attr, long long *val)
470{
471 char *end, buf[1024];
472 long long value;
473 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
474 if (ret < 0)
475 return (int) ret;
476
477 value = strtoll(buf, &end, 0);
478 if (end == buf)
479 return -EINVAL;
480 *val = value;
481 return 0;
482}
483
484int iio_device_attr_read_bool(const struct iio_device *dev,
485 const char *attr, bool *val)
486{
487 long long value;
488 int ret = iio_device_attr_read_longlong(dev, attr, &value);
489 if (ret < 0)
490 return ret;
491
492 *val = !!value;
493 return 0;
494}
495
496int iio_device_attr_read_double(const struct iio_device *dev,
497 const char *attr, double *val)
498{
499 char *end, buf[1024];
500 double value;
501 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
502 if (ret < 0)
503 return (int) ret;
504
505 value = strtod(buf, &end);
506 if (end == buf)
507 return -EINVAL;
508 *val = value;
509 return 0;
510}
511
512int iio_device_attr_write_longlong(const struct iio_device *dev,
513 const char *attr, long long val)
514{
515 char buf[1024];
516 snprintf(buf, sizeof(buf), "%lld", val);
517 return iio_device_attr_write(dev, attr, buf);
518}
519
520int iio_device_attr_write_double(const struct iio_device *dev,
521 const char *attr, double val)
522{
523 char buf[1024];
524 snprintf(buf, sizeof(buf), "%lf", val);
525 return iio_device_attr_write(dev, attr, buf);
526}
527
528int iio_device_attr_write_bool(const struct iio_device *dev,
529 const char *attr, bool val)
530{
531 if (val)
532 return iio_device_attr_write(dev, attr, "1");
533 else
534 return iio_device_attr_write(dev, attr, "0");
535}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200536
537ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
538 const char *attr, char *dst, size_t len)
539{
540 if (dev->ctx->ops->read_device_attr)
541 return dev->ctx->ops->read_device_attr(dev,
542 attr, dst, len, true);
543 else
544 return -ENOSYS;
545}
546
Paul Cercueilcecda352014-05-06 18:14:29 +0200547ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
548 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200549{
550 if (dev->ctx->ops->write_device_attr)
551 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200552 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200553 else
554 return -ENOSYS;
555}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200556
Paul Cercueilcecda352014-05-06 18:14:29 +0200557ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
558 const char *attr, const char *src)
559{
560 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
561}
562
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200563unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
564{
565 return dev->nb_debug_attrs;
566}
567
568const char * iio_device_get_debug_attr(const struct iio_device *dev,
569 unsigned int index)
570{
571 if (index >= dev->nb_debug_attrs)
572 return NULL;
573 else
574 return dev->debug_attrs[index];
575}
Paul Cercueile3960742014-04-15 16:00:50 +0200576
577int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
578 const char *attr, long long *val)
579{
580 char *end, buf[1024];
581 long long value;
582 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
583 if (ret < 0)
584 return (int) ret;
585
586 value = strtoll(buf, &end, 0);
587 if (end == buf)
588 return -EINVAL;
589 *val = value;
590 return 0;
591}
592
593int iio_device_debug_attr_read_bool(const struct iio_device *dev,
594 const char *attr, bool *val)
595{
596 long long value;
597 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
598 if (ret < 0)
599 return ret;
600
601 *val = !!value;
602 return 0;
603}
604
605int iio_device_debug_attr_read_double(const struct iio_device *dev,
606 const char *attr, double *val)
607{
608 char *end, buf[1024];
609 double value;
610 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
611 if (ret < 0)
612 return (int) ret;
613
614 value = strtod(buf, &end);
615 if (end == buf)
616 return -EINVAL;
617 *val = value;
618 return 0;
619}
620
621int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
622 const char *attr, long long val)
623{
624 char buf[1024];
625 snprintf(buf, sizeof(buf), "%lld", val);
626 return iio_device_debug_attr_write(dev, attr, buf);
627}
628
629int iio_device_debug_attr_write_double(const struct iio_device *dev,
630 const char *attr, double val)
631{
632 char buf[1024];
633 snprintf(buf, sizeof(buf), "%lf", val);
634 return iio_device_debug_attr_write(dev, attr, buf);
635}
636
637int iio_device_debug_attr_write_bool(const struct iio_device *dev,
638 const char *attr, bool val)
639{
640 if (val)
Paul Cercueilcecda352014-05-06 18:14:29 +0200641 return iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200642 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200643 return iio_device_debug_attr_write_raw(dev, attr, "0", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200644}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200645
646int iio_device_identify_filename(const struct iio_device *dev,
647 const char *filename, struct iio_channel **chn,
648 const char **attr)
649{
650 unsigned int i;
651
652 for (i = 0; i < dev->nb_channels; i++) {
653 struct iio_channel *ch = dev->channels[i];
654 unsigned int j;
655
656 for (j = 0; j < ch->nb_attrs; j++) {
657 if (!strcmp(ch->attrs[j].filename, filename)) {
658 *attr = ch->attrs[j].name;
659 *chn = ch;
660 return 0;
661 }
662 }
663 }
664
665 for (i = 0; i < dev->nb_attrs; i++) {
666 /* Devices attributes are named after their filename */
667 if (!strcmp(dev->attrs[i], filename)) {
668 *attr = dev->attrs[i];
669 *chn = NULL;
670 return 0;
671 }
672 }
673
674 for (i = 0; i < dev->nb_debug_attrs; i++) {
675 if (!strcmp(dev->debug_attrs[i], filename)) {
676 *attr = dev->debug_attrs[i];
677 *chn = NULL;
678 return 0;
679 }
680 }
681
682 return -EINVAL;
683}