blob: 8802a00767cae1dec1fb8cb7c02772aa32e55961 [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 Cercueil1b36a012014-06-05 14:39:31 +020026/* Include <winsock2.h> or <arpa/inet.h> for ntohl() */
27#ifdef _WIN32
28#include <winsock2.h>
29#else
30#include <arpa/inet.h>
31#endif
32
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020033static char *get_attr_xml(const char *attr, size_t *length, bool is_debug)
Paul Cercueil42090d12014-02-24 12:32:23 +010034{
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020035 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr)
36 + (!is_debug ? 0 : sizeof("debug-") - 1);
Paul Cercueil42090d12014-02-24 12:32:23 +010037 char *str = malloc(len);
38 if (!str) {
39 ERROR("Unable to allocate memory\n");
40 return NULL;
41 }
42
43 *length = len - 1; /* Skip the \0 */
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020044 if (is_debug)
45 snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
46 else
47 snprintf(str, len, "<attribute name=\"%s\" />", attr);
Paul Cercueil42090d12014-02-24 12:32:23 +010048 return str;
49}
50
51/* Returns a string containing the XML representation of this device */
52char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
53{
Paul Cercueil8c29e412014-04-07 09:46:45 +020054 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
55 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020056 char *ptr, *str, **attrs, **channels, **debug_attrs;
57 size_t *attrs_len, *channels_len, *debug_attrs_len;
58 unsigned int i, j, k;
Paul Cercueil5822ab62014-04-04 13:29:17 +020059
60 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
61 if (!attrs_len)
62 return NULL;
63
64 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
65 if (!attrs)
66 goto err_free_attrs_len;
67
Paul Cercueil42090d12014-02-24 12:32:23 +010068 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020069 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
Paul Cercueil42090d12014-02-24 12:32:23 +010070 if (!xml)
71 goto err_free_attrs;
72 attrs[i] = xml;
73 len += attrs_len[i];
74 }
75
Paul Cercueil8c29e412014-04-07 09:46:45 +020076 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
77 if (!channels_len)
78 goto err_free_attrs;
79
80 channels = malloc(dev->nb_channels * sizeof(*channels));
81 if (!channels)
82 goto err_free_channels_len;
83
Paul Cercueil42090d12014-02-24 12:32:23 +010084 for (j = 0; j < dev->nb_channels; j++) {
85 char *xml = iio_channel_get_xml(dev->channels[j],
86 &channels_len[j]);
87 if (!xml)
88 goto err_free_channels;
89 channels[j] = xml;
90 len += channels_len[j];
91 }
92
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020093 debug_attrs_len = malloc(dev->nb_debug_attrs *
94 sizeof(*debug_attrs_len));
95 if (!debug_attrs_len)
96 goto err_free_channels;
97
98 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
99 if (!debug_attrs)
100 goto err_free_debug_attrs_len;
101
102 for (k = 0; k < dev->nb_debug_attrs; k++) {
103 char *xml = get_attr_xml(dev->debug_attrs[k],
104 &debug_attrs_len[k], true);
105 if (!xml)
106 goto err_free_debug_attrs;
107 debug_attrs[k] = xml;
108 len += debug_attrs_len[k];
109 }
110
Paul Cercueil42090d12014-02-24 12:32:23 +0100111 str = malloc(len);
112 if (!str)
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200113 goto err_free_debug_attrs;
Paul Cercueil42090d12014-02-24 12:32:23 +0100114
Paul Cercueil8c29e412014-04-07 09:46:45 +0200115 snprintf(str, len, "<device id=\"%s\"", dev->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100116 ptr = strrchr(str, '\0');
117
118 if (dev->name) {
119 sprintf(ptr, " name=\"%s\"", dev->name);
120 ptr = strrchr(ptr, '\0');
121 }
122
123 strcpy(ptr, " >");
124 ptr += 2;
125
126 for (i = 0; i < dev->nb_channels; i++) {
127 strcpy(ptr, channels[i]);
128 ptr += channels_len[i];
129 free(channels[i]);
130 }
131
Paul Cercueil5822ab62014-04-04 13:29:17 +0200132 free(channels);
133 free(channels_len);
134
Paul Cercueil42090d12014-02-24 12:32:23 +0100135 for (i = 0; i < dev->nb_attrs; i++) {
136 strcpy(ptr, attrs[i]);
137 ptr += attrs_len[i];
138 free(attrs[i]);
139 }
140
Paul Cercueil5822ab62014-04-04 13:29:17 +0200141 free(attrs);
142 free(attrs_len);
143
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200144 for (i = 0; i < dev->nb_debug_attrs; i++) {
145 strcpy(ptr, debug_attrs[i]);
146 ptr += debug_attrs_len[i];
147 free(debug_attrs[i]);
148 }
149
150 free(debug_attrs);
151 free(debug_attrs_len);
152
Paul Cercueil42090d12014-02-24 12:32:23 +0100153 strcpy(ptr, "</device>");
154 *length = ptr - str + sizeof("</device>") - 1;
155 return str;
156
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200157err_free_debug_attrs:
158 while (k--)
159 free(debug_attrs[k]);
160 free(debug_attrs);
161err_free_debug_attrs_len:
162 free(debug_attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100163err_free_channels:
164 while (j--)
165 free(channels[j]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200166 free(channels);
167err_free_channels_len:
168 free(channels_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100169err_free_attrs:
170 while (i--)
171 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200172 free(attrs);
173err_free_attrs_len:
174 free(attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100175 return NULL;
176}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100177
178const char * iio_device_get_id(const struct iio_device *dev)
179{
180 return dev->id;
181}
182
183const char * iio_device_get_name(const struct iio_device *dev)
184{
185 return dev->name;
186}
187
188unsigned int iio_device_get_channels_count(const struct iio_device *dev)
189{
190 return dev->nb_channels;
191}
192
193struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
194 unsigned int index)
195{
196 if (index >= dev->nb_channels)
197 return NULL;
198 else
199 return dev->channels[index];
200}
201
Paul Cercueil17512b02014-03-28 11:15:24 +0100202struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100203 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100204{
205 unsigned int i;
206 for (i = 0; i < dev->nb_channels; i++) {
207 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100208 if (iio_channel_is_output(chn) != output)
209 continue;
210
Paul Cercueil17512b02014-03-28 11:15:24 +0100211 if (!strcmp(chn->id, name) ||
212 (chn->name && !strcmp(chn->name, name)))
213 return chn;
214 }
215 return NULL;
216}
217
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100218unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
219{
220 return dev->nb_attrs;
221}
222
223const char * iio_device_get_attr(const struct iio_device *dev,
224 unsigned int index)
225{
226 if (index >= dev->nb_attrs)
227 return NULL;
228 else
229 return dev->attrs[index];
230}
231
Paul Cercueil4f838d02014-03-28 11:26:15 +0100232const char * iio_device_find_attr(const struct iio_device *dev,
233 const char *name)
234{
235 unsigned int i;
236 for (i = 0; i < dev->nb_attrs; i++) {
237 const char *attr = dev->attrs[i];
238 if (!strcmp(attr, name))
239 return attr;
240 }
241 return NULL;
242}
243
Paul Cercueil001d2152014-06-03 15:24:44 +0200244const char * iio_device_find_debug_attr(const struct iio_device *dev,
245 const char *name)
246{
247 unsigned int i;
248 for (i = 0; i < dev->nb_debug_attrs; i++) {
249 const char *attr = dev->debug_attrs[i];
250 if (!strcmp(attr, name))
251 return attr;
252 }
253 return NULL;
254}
255
Paul Cercueil3cc3a002014-03-24 13:44:11 +0100256static int iio_device_open_mask(const struct iio_device *dev,
Paul Cercueil71694c72014-05-22 14:02:13 +0200257 size_t samples_count, uint32_t *mask, size_t words, bool cyclic)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100258{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100259 unsigned int i;
260 bool has_channels = false;
261
262 for (i = 0; !has_channels && i < words; i++)
263 has_channels = !!mask[i];
264 if (!has_channels)
265 return -EINVAL;
266
Paul Cercueilec1760d2014-02-21 11:31:20 +0100267 if (dev->ctx->ops->open)
Paul Cercueil71694c72014-05-22 14:02:13 +0200268 return dev->ctx->ops->open(dev,
269 samples_count, mask, words, cyclic);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100270 else
271 return -ENOSYS;
272}
273
Paul Cercueil71694c72014-05-22 14:02:13 +0200274int iio_device_open(const struct iio_device *dev,
275 size_t samples_count, bool cyclic)
Paul Cercueile1311222014-03-12 15:46:16 +0100276{
277 size_t nb = (dev->nb_channels + 31) / 32;
278 uint32_t *mask = NULL;
279 unsigned int i;
280 int ret;
281
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100282 if (nb == 0)
283 return -EINVAL;
284
285 mask = calloc(nb, sizeof(*mask));
286 if (!mask)
287 return -ENOMEM;
Paul Cercueile1311222014-03-12 15:46:16 +0100288
289 for (i = 0; i < dev->nb_channels; i++) {
290 struct iio_channel *chn = dev->channels[i];
291 if (iio_channel_is_enabled(chn) && chn->index >= 0)
292 SET_BIT(mask, chn->index);
293 }
294
Paul Cercueil71694c72014-05-22 14:02:13 +0200295 ret = iio_device_open_mask(dev, samples_count, mask, nb, cyclic);
Paul Cercueile1311222014-03-12 15:46:16 +0100296 free(mask);
297 return ret;
298}
299
Paul Cercueilec1760d2014-02-21 11:31:20 +0100300int iio_device_close(const struct iio_device *dev)
301{
302 if (dev->ctx->ops->close)
303 return dev->ctx->ops->close(dev);
304 else
305 return -ENOSYS;
306}
307
308ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100309 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100310{
311 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100312 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100313 else
314 return -ENOSYS;
315}
316
317ssize_t iio_device_write_raw(const struct iio_device *dev,
318 const void *src, size_t len)
319{
320 if (dev->ctx->ops->write)
321 return dev->ctx->ops->write(dev, src, len);
322 else
323 return -ENOSYS;
324}
325
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100326ssize_t iio_device_attr_read(const struct iio_device *dev,
327 const char *attr, char *dst, size_t len)
328{
Paul Cercueil6a013602014-02-19 12:37:39 +0100329 if (dev->ctx->ops->read_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200330 return dev->ctx->ops->read_device_attr(dev,
331 attr, dst, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100332 else
333 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100334}
335
Paul Cercueilcecda352014-05-06 18:14:29 +0200336ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
337 const char *attr, const void *src, size_t len)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100338{
Paul Cercueil6a013602014-02-19 12:37:39 +0100339 if (dev->ctx->ops->write_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200340 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200341 attr, src, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100342 else
343 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100344}
Paul Cercueil00236242014-02-18 15:09:06 +0100345
Paul Cercueilcecda352014-05-06 18:14:29 +0200346ssize_t iio_device_attr_write(const struct iio_device *dev,
347 const char *attr, const char *src)
348{
349 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
350}
351
Paul Cercueild96e61f2014-03-07 16:13:37 +0100352void iio_device_set_data(struct iio_device *dev, void *data)
353{
354 dev->userdata = data;
355}
356
357void * iio_device_get_data(const struct iio_device *dev)
358{
359 return dev->userdata;
360}
361
Paul Cercueil3156f632014-03-10 11:22:55 +0100362bool iio_device_is_trigger(const struct iio_device *dev)
363{
364 /* A trigger has a name, an id which starts by "trigger",
365 * and zero channels. */
366
367 unsigned int nb = iio_device_get_channels_count(dev);
368 const char *name = iio_device_get_name(dev),
369 *id = iio_device_get_id(dev);
370 return ((nb == 0) && !!name &&
371 !strncmp(id, "trigger", sizeof("trigger") - 1));
372}
373
Paul Cercueil24ffa532014-03-10 12:39:58 +0100374int iio_device_get_trigger(const struct iio_device *dev,
375 const struct iio_device **trigger)
376{
377 if (!trigger)
378 return -EINVAL;
379 else if (dev->ctx->ops->get_trigger)
380 return dev->ctx->ops->get_trigger(dev, trigger);
381 else
382 return -ENOSYS;
383}
384
385int iio_device_set_trigger(const struct iio_device *dev,
386 const struct iio_device *trigger)
387{
388 if (trigger && !iio_device_is_trigger(trigger))
389 return -EINVAL;
390 else if (dev->ctx->ops->set_trigger)
391 return dev->ctx->ops->set_trigger(dev, trigger);
392 else
393 return -ENOSYS;
394}
395
Paul Cercueil00236242014-02-18 15:09:06 +0100396void free_device(struct iio_device *dev)
397{
398 unsigned int i;
399 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200400 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100401 if (dev->nb_attrs)
402 free(dev->attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200403 for (i = 0; i < dev->nb_debug_attrs; i++)
404 free(dev->debug_attrs[i]);
405 if (dev->nb_debug_attrs)
406 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100407 for (i = 0; i < dev->nb_channels; i++)
408 free_channel(dev->channels[i]);
409 if (dev->nb_channels)
410 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100411 if (dev->mask)
412 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100413 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200414 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100415 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200416 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100417 free(dev);
418}
Paul Cercueil1a474732014-03-17 11:38:34 +0100419
Paul Cercueil645ab972014-03-24 14:36:12 +0100420ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil1a474732014-03-17 11:38:34 +0100421 uint32_t *mask, size_t words)
422{
423 ssize_t size = 0;
424 unsigned int i;
425
426 if (words != (dev->nb_channels + 31) / 32)
427 return -EINVAL;
428
429 for (i = 0; i < dev->nb_channels; i++) {
430 const struct iio_channel *chn = dev->channels[i];
431 unsigned int length = chn->format.length / 8;
432
433 if (chn->index < 0)
434 break;
435 if (!TEST_BIT(mask, chn->index))
436 continue;
437
438 if (size % length)
439 size += 2 * length - (size % length);
440 else
441 size += length;
442 }
443 return size;
444}
Paul Cercueil46825942014-03-18 14:28:49 +0100445
Paul Cercueil645ab972014-03-24 14:36:12 +0100446ssize_t iio_device_get_sample_size(const struct iio_device *dev)
447{
448 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
449}
450
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200451int iio_device_attr_read_longlong(const struct iio_device *dev,
452 const char *attr, long long *val)
453{
454 char *end, buf[1024];
455 long long value;
456 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
457 if (ret < 0)
458 return (int) ret;
459
460 value = strtoll(buf, &end, 0);
461 if (end == buf)
462 return -EINVAL;
463 *val = value;
464 return 0;
465}
466
467int iio_device_attr_read_bool(const struct iio_device *dev,
468 const char *attr, bool *val)
469{
470 long long value;
471 int ret = iio_device_attr_read_longlong(dev, attr, &value);
472 if (ret < 0)
473 return ret;
474
475 *val = !!value;
476 return 0;
477}
478
479int iio_device_attr_read_double(const struct iio_device *dev,
480 const char *attr, double *val)
481{
482 char *end, buf[1024];
483 double value;
484 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
485 if (ret < 0)
486 return (int) ret;
487
488 value = strtod(buf, &end);
489 if (end == buf)
490 return -EINVAL;
491 *val = value;
492 return 0;
493}
494
495int iio_device_attr_write_longlong(const struct iio_device *dev,
496 const char *attr, long long val)
497{
498 char buf[1024];
499 snprintf(buf, sizeof(buf), "%lld", val);
500 return iio_device_attr_write(dev, attr, buf);
501}
502
503int iio_device_attr_write_double(const struct iio_device *dev,
504 const char *attr, double val)
505{
506 char buf[1024];
507 snprintf(buf, sizeof(buf), "%lf", val);
508 return iio_device_attr_write(dev, attr, buf);
509}
510
511int iio_device_attr_write_bool(const struct iio_device *dev,
512 const char *attr, bool val)
513{
514 if (val)
515 return iio_device_attr_write(dev, attr, "1");
516 else
517 return iio_device_attr_write(dev, attr, "0");
518}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200519
520ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
521 const char *attr, char *dst, size_t len)
522{
523 if (dev->ctx->ops->read_device_attr)
524 return dev->ctx->ops->read_device_attr(dev,
525 attr, dst, len, true);
526 else
527 return -ENOSYS;
528}
529
Paul Cercueilcecda352014-05-06 18:14:29 +0200530ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
531 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200532{
533 if (dev->ctx->ops->write_device_attr)
534 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200535 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200536 else
537 return -ENOSYS;
538}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200539
Paul Cercueilcecda352014-05-06 18:14:29 +0200540ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
541 const char *attr, const char *src)
542{
543 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
544}
545
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200546unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
547{
548 return dev->nb_debug_attrs;
549}
550
551const char * iio_device_get_debug_attr(const struct iio_device *dev,
552 unsigned int index)
553{
554 if (index >= dev->nb_debug_attrs)
555 return NULL;
556 else
557 return dev->debug_attrs[index];
558}
Paul Cercueile3960742014-04-15 16:00:50 +0200559
560int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
561 const char *attr, long long *val)
562{
563 char *end, buf[1024];
564 long long value;
565 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
566 if (ret < 0)
567 return (int) ret;
568
569 value = strtoll(buf, &end, 0);
570 if (end == buf)
571 return -EINVAL;
572 *val = value;
573 return 0;
574}
575
576int iio_device_debug_attr_read_bool(const struct iio_device *dev,
577 const char *attr, bool *val)
578{
579 long long value;
580 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
581 if (ret < 0)
582 return ret;
583
584 *val = !!value;
585 return 0;
586}
587
588int iio_device_debug_attr_read_double(const struct iio_device *dev,
589 const char *attr, double *val)
590{
591 char *end, buf[1024];
592 double value;
593 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
594 if (ret < 0)
595 return (int) ret;
596
597 value = strtod(buf, &end);
598 if (end == buf)
599 return -EINVAL;
600 *val = value;
601 return 0;
602}
603
604int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
605 const char *attr, long long val)
606{
607 char buf[1024];
608 snprintf(buf, sizeof(buf), "%lld", val);
609 return iio_device_debug_attr_write(dev, attr, buf);
610}
611
612int iio_device_debug_attr_write_double(const struct iio_device *dev,
613 const char *attr, double val)
614{
615 char buf[1024];
616 snprintf(buf, sizeof(buf), "%lf", val);
617 return iio_device_debug_attr_write(dev, attr, buf);
618}
619
620int iio_device_debug_attr_write_bool(const struct iio_device *dev,
621 const char *attr, bool val)
622{
623 if (val)
Paul Cercueilcecda352014-05-06 18:14:29 +0200624 return iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200625 else
Paul Cercueilcecda352014-05-06 18:14:29 +0200626 return iio_device_debug_attr_write_raw(dev, attr, "0", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200627}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200628
629int iio_device_identify_filename(const struct iio_device *dev,
630 const char *filename, struct iio_channel **chn,
631 const char **attr)
632{
633 unsigned int i;
634
635 for (i = 0; i < dev->nb_channels; i++) {
636 struct iio_channel *ch = dev->channels[i];
637 unsigned int j;
638
639 for (j = 0; j < ch->nb_attrs; j++) {
640 if (!strcmp(ch->attrs[j].filename, filename)) {
641 *attr = ch->attrs[j].name;
642 *chn = ch;
643 return 0;
644 }
645 }
646 }
647
648 for (i = 0; i < dev->nb_attrs; i++) {
649 /* Devices attributes are named after their filename */
650 if (!strcmp(dev->attrs[i], filename)) {
651 *attr = dev->attrs[i];
652 *chn = NULL;
653 return 0;
654 }
655 }
656
657 for (i = 0; i < dev->nb_debug_attrs; i++) {
658 if (!strcmp(dev->debug_attrs[i], filename)) {
659 *attr = dev->debug_attrs[i];
660 *chn = NULL;
661 return 0;
662 }
663 }
664
665 return -EINVAL;
666}
Paul Cercueil14405872014-05-07 14:00:32 +0200667
668int iio_device_reg_write(struct iio_device *dev,
669 uint32_t address, uint32_t value)
670{
671 char buf[1024];
672 snprintf(buf, sizeof(buf), "0x%x 0x%x", address, value);
673 return iio_device_debug_attr_write(dev, "direct_reg_access", buf);
674}
675
676int iio_device_reg_read(struct iio_device *dev,
677 uint32_t address, uint32_t *value)
678{
679 /* NOTE: There is a race condition here. But it is extremely unlikely to
680 * happen, and as this is a debug function, it shouldn't be used for
681 * something else than debug. */
682
683 long long val;
684 int ret = iio_device_debug_attr_write_longlong(dev,
685 "direct_reg_access", (long long) address);
686 if (ret < 0)
687 return ret;
688
689 ret = iio_device_debug_attr_read_longlong(dev,
690 "direct_reg_access", &val);
691 if (!ret)
692 *value = (uint32_t) val;
693 return ret;
694}
Paul Cercueil1b36a012014-06-05 14:39:31 +0200695
696static int read_each_attr(struct iio_device *dev, bool is_debug,
697 int (*cb)(struct iio_device *dev,
698 const char *attr, const char *val, size_t len, void *d),
699 void *data)
700{
701 int ret;
702 char *buf, *ptr;
703 unsigned int i, count;
704
705 /* We need a big buffer here; 1 MiB should be enough */
706 buf = malloc(0x100000);
707 if (!buf)
708 return -ENOMEM;
709
710 if (is_debug) {
711 count = iio_device_get_debug_attrs_count(dev);
712 ret = (int) iio_device_debug_attr_read(dev,
713 NULL, buf, 0x100000);
714 } else {
715 count = iio_device_get_attrs_count(dev);
716 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
717 }
718
719 if (ret < 0)
720 goto err_free_buf;
721
722 ptr = buf;
723
724 for (i = 0; i < count; i++) {
725 const char *attr;
726 int32_t len = (int32_t) ntohl(*(uint32_t *) ptr);
727
728 if (is_debug)
729 attr = iio_device_get_debug_attr(dev, i);
730 else
731 attr = iio_device_get_attr(dev, i);
732
733 ptr += 4;
734 if (len > 0) {
735 ret = cb(dev, attr, ptr, (size_t) len, data);
736 if (ret < 0)
737 goto err_free_buf;
738
739 if (len & 0x3)
740 len = ((len >> 2) + 1) << 2;
741 ptr += len;
742 }
743 }
744
745err_free_buf:
746 free(buf);
747 return ret < 0 ? ret : 0;
748}
749
750static int write_each_attr(struct iio_device *dev, bool is_debug,
751 ssize_t (*cb)(struct iio_device *dev,
752 const char *attr, void *buf, size_t len, void *d),
753 void *data)
754{
755 char *buf, *ptr;
756 unsigned int i, count;
757 size_t len = 0x100000;
758 int ret;
759
760 /* We need a big buffer here; 1 MiB should be enough */
761 buf = malloc(len);
762 if (!buf)
763 return -ENOMEM;
764
765 ptr = buf;
766
767 if (is_debug)
768 count = iio_device_get_debug_attrs_count(dev);
769 else
770 count = iio_device_get_attrs_count(dev);
771
772 for (i = 0; i < count; i++) {
773 const char *attr;
774
775 if (is_debug)
776 attr = iio_device_get_debug_attr(dev, i);
777 else
778 attr = iio_device_get_attr(dev, i);
779
780 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
781 if (ret < 0)
782 goto err_free_buf;
783
784 *(int32_t *) ptr = (int32_t) htonl((uint32_t) ret);
785 ptr += 4;
786 len -= 4;
787
788 if (ret > 0) {
789 if (ret & 0x3)
790 ret = ((ret >> 2) + 1) << 2;
791 ptr += ret;
792 len -= ret;
793 }
794 }
795
796 if (is_debug)
797 ret = (int) iio_device_debug_attr_write_raw(dev,
798 NULL, buf, ptr - buf);
799 else
800 ret = (int) iio_device_attr_write_raw(dev,
801 NULL, buf, ptr - buf);
802
803err_free_buf:
804 free(buf);
805 return ret < 0 ? ret : 0;
806}
807
808int iio_device_debug_attr_read_all(struct iio_device *dev,
809 int (*cb)(struct iio_device *dev,
810 const char *attr, const char *val, size_t len, void *d),
811 void *data)
812{
813 return read_each_attr(dev, true, cb, data);
814}
815
816int iio_device_attr_read_all(struct iio_device *dev,
817 int (*cb)(struct iio_device *dev,
818 const char *attr, const char *val, size_t len, void *d),
819 void *data)
820{
821 return read_each_attr(dev, false, cb, data);
822}
823
824int iio_device_debug_attr_write_all(struct iio_device *dev,
825 ssize_t (*cb)(struct iio_device *dev,
826 const char *attr, void *buf, size_t len, void *d),
827 void *data)
828{
829 return write_each_attr(dev, true, cb, data);
830}
831
832int iio_device_attr_write_all(struct iio_device *dev,
833 ssize_t (*cb)(struct iio_device *dev,
834 const char *attr, void *buf, size_t len, void *d),
835 void *data)
836{
837 return write_each_attr(dev, false, cb, data);
838}