blob: 53d58329505a15e6b502aae1f596ff0a6990de66 [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 Cercueil0b2ce712014-02-17 15:04:18 +010019#include "iio-private.h"
20
Paul Cercueil6a013602014-02-19 12:37:39 +010021#include <errno.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010022#include <stdio.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010023#include <string.h>
24
Paul Cercueil1b36a012014-06-05 14:39:31 +020025/* Include <winsock2.h> or <arpa/inet.h> for ntohl() */
26#ifdef _WIN32
27#include <winsock2.h>
28#else
29#include <arpa/inet.h>
30#endif
31
Paul Cercueilb0408c22014-06-26 09:38:43 +020032/* winsock2.h defines ERROR, we don't want that */
33#undef ERROR
34
35#include "debug.h"
36
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020037static char *get_attr_xml(const char *attr, size_t *length, bool is_debug)
Paul Cercueil42090d12014-02-24 12:32:23 +010038{
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020039 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr)
40 + (!is_debug ? 0 : sizeof("debug-") - 1);
Paul Cercueil42090d12014-02-24 12:32:23 +010041 char *str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010042 if (!str)
Paul Cercueil42090d12014-02-24 12:32:23 +010043 return NULL;
Paul Cercueil42090d12014-02-24 12:32:23 +010044
45 *length = len - 1; /* Skip the \0 */
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020046 if (is_debug)
47 snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
48 else
49 snprintf(str, len, "<attribute name=\"%s\" />", attr);
Paul Cercueil42090d12014-02-24 12:32:23 +010050 return str;
51}
52
53/* Returns a string containing the XML representation of this device */
54char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
55{
Paul Cercueil8c29e412014-04-07 09:46:45 +020056 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
57 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020058 char *ptr, *str, **attrs, **channels, **debug_attrs;
59 size_t *attrs_len, *channels_len, *debug_attrs_len;
60 unsigned int i, j, k;
Paul Cercueil5822ab62014-04-04 13:29:17 +020061
62 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
63 if (!attrs_len)
64 return NULL;
65
66 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
67 if (!attrs)
68 goto err_free_attrs_len;
69
Paul Cercueil42090d12014-02-24 12:32:23 +010070 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020071 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
Paul Cercueil42090d12014-02-24 12:32:23 +010072 if (!xml)
73 goto err_free_attrs;
74 attrs[i] = xml;
75 len += attrs_len[i];
76 }
77
Paul Cercueil8c29e412014-04-07 09:46:45 +020078 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
79 if (!channels_len)
80 goto err_free_attrs;
81
82 channels = malloc(dev->nb_channels * sizeof(*channels));
83 if (!channels)
84 goto err_free_channels_len;
85
Paul Cercueil42090d12014-02-24 12:32:23 +010086 for (j = 0; j < dev->nb_channels; j++) {
87 char *xml = iio_channel_get_xml(dev->channels[j],
88 &channels_len[j]);
89 if (!xml)
90 goto err_free_channels;
91 channels[j] = xml;
92 len += channels_len[j];
93 }
94
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020095 debug_attrs_len = malloc(dev->nb_debug_attrs *
96 sizeof(*debug_attrs_len));
97 if (!debug_attrs_len)
98 goto err_free_channels;
99
100 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
101 if (!debug_attrs)
102 goto err_free_debug_attrs_len;
103
104 for (k = 0; k < dev->nb_debug_attrs; k++) {
105 char *xml = get_attr_xml(dev->debug_attrs[k],
106 &debug_attrs_len[k], true);
107 if (!xml)
108 goto err_free_debug_attrs;
109 debug_attrs[k] = xml;
110 len += debug_attrs_len[k];
111 }
112
Paul Cercueil42090d12014-02-24 12:32:23 +0100113 str = malloc(len);
114 if (!str)
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200115 goto err_free_debug_attrs;
Paul Cercueil42090d12014-02-24 12:32:23 +0100116
Paul Cercueil8c29e412014-04-07 09:46:45 +0200117 snprintf(str, len, "<device id=\"%s\"", dev->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100118 ptr = strrchr(str, '\0');
119
120 if (dev->name) {
121 sprintf(ptr, " name=\"%s\"", dev->name);
122 ptr = strrchr(ptr, '\0');
123 }
124
125 strcpy(ptr, " >");
126 ptr += 2;
127
128 for (i = 0; i < dev->nb_channels; i++) {
129 strcpy(ptr, channels[i]);
130 ptr += channels_len[i];
131 free(channels[i]);
132 }
133
Paul Cercueil5822ab62014-04-04 13:29:17 +0200134 free(channels);
135 free(channels_len);
136
Paul Cercueil42090d12014-02-24 12:32:23 +0100137 for (i = 0; i < dev->nb_attrs; i++) {
138 strcpy(ptr, attrs[i]);
139 ptr += attrs_len[i];
140 free(attrs[i]);
141 }
142
Paul Cercueil5822ab62014-04-04 13:29:17 +0200143 free(attrs);
144 free(attrs_len);
145
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200146 for (i = 0; i < dev->nb_debug_attrs; i++) {
147 strcpy(ptr, debug_attrs[i]);
148 ptr += debug_attrs_len[i];
149 free(debug_attrs[i]);
150 }
151
152 free(debug_attrs);
153 free(debug_attrs_len);
154
Paul Cercueil42090d12014-02-24 12:32:23 +0100155 strcpy(ptr, "</device>");
156 *length = ptr - str + sizeof("</device>") - 1;
157 return str;
158
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200159err_free_debug_attrs:
160 while (k--)
161 free(debug_attrs[k]);
162 free(debug_attrs);
163err_free_debug_attrs_len:
164 free(debug_attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100165err_free_channels:
166 while (j--)
167 free(channels[j]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200168 free(channels);
169err_free_channels_len:
170 free(channels_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100171err_free_attrs:
172 while (i--)
173 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200174 free(attrs);
175err_free_attrs_len:
176 free(attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100177 return NULL;
178}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100179
180const char * iio_device_get_id(const struct iio_device *dev)
181{
182 return dev->id;
183}
184
185const char * iio_device_get_name(const struct iio_device *dev)
186{
187 return dev->name;
188}
189
190unsigned int iio_device_get_channels_count(const struct iio_device *dev)
191{
192 return dev->nb_channels;
193}
194
195struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
196 unsigned int index)
197{
198 if (index >= dev->nb_channels)
199 return NULL;
200 else
201 return dev->channels[index];
202}
203
Paul Cercueil17512b02014-03-28 11:15:24 +0100204struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100205 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100206{
207 unsigned int i;
208 for (i = 0; i < dev->nb_channels; i++) {
209 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100210 if (iio_channel_is_output(chn) != output)
211 continue;
212
Paul Cercueil17512b02014-03-28 11:15:24 +0100213 if (!strcmp(chn->id, name) ||
214 (chn->name && !strcmp(chn->name, name)))
215 return chn;
216 }
217 return NULL;
218}
219
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100220unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
221{
222 return dev->nb_attrs;
223}
224
225const char * iio_device_get_attr(const struct iio_device *dev,
226 unsigned int index)
227{
228 if (index >= dev->nb_attrs)
229 return NULL;
230 else
231 return dev->attrs[index];
232}
233
Paul Cercueil4f838d02014-03-28 11:26:15 +0100234const char * iio_device_find_attr(const struct iio_device *dev,
235 const char *name)
236{
237 unsigned int i;
238 for (i = 0; i < dev->nb_attrs; i++) {
239 const char *attr = dev->attrs[i];
240 if (!strcmp(attr, name))
241 return attr;
242 }
243 return NULL;
244}
245
Paul Cercueil001d2152014-06-03 15:24:44 +0200246const char * iio_device_find_debug_attr(const struct iio_device *dev,
247 const char *name)
248{
249 unsigned int i;
250 for (i = 0; i < dev->nb_debug_attrs; i++) {
251 const char *attr = dev->debug_attrs[i];
252 if (!strcmp(attr, name))
253 return attr;
254 }
255 return NULL;
256}
257
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100258bool iio_device_is_tx(const struct iio_device *dev)
259{
260 unsigned int i;
261
262 for (i = 0; i < dev->nb_channels; i++) {
263 struct iio_channel *ch = dev->channels[i];
264 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
265 return true;
266 }
267
268 return false;
269}
270
Paul Cercueil92f15c22015-04-20 11:36:51 +0200271int iio_device_open(const struct iio_device *dev,
272 size_t samples_count, bool cyclic)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100273{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100274 unsigned int i;
275 bool has_channels = false;
276
Paul Cercueil92f15c22015-04-20 11:36:51 +0200277 for (i = 0; !has_channels && i < dev->words; i++)
278 has_channels = !!dev->mask[i];
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100279 if (!has_channels)
280 return -EINVAL;
281
Paul Cercueilec1760d2014-02-21 11:31:20 +0100282 if (dev->ctx->ops->open)
Paul Cercueil92f15c22015-04-20 11:36:51 +0200283 return dev->ctx->ops->open(dev, samples_count, cyclic);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100284 else
285 return -ENOSYS;
286}
287
288int iio_device_close(const struct iio_device *dev)
289{
290 if (dev->ctx->ops->close)
291 return dev->ctx->ops->close(dev);
292 else
293 return -ENOSYS;
294}
295
Romain Roffé6a881702015-06-30 16:25:43 +0200296int iio_device_get_poll_fd(const struct iio_device *dev)
297{
298 if (dev->ctx->ops->get_fd)
299 return dev->ctx->ops->get_fd(dev);
300 else
301 return -ENOSYS;
302}
303
Romain Roffé0ea038d2015-06-30 13:35:38 +0200304int iio_device_set_blocking_mode(const struct iio_device *dev, bool blocking)
305{
306 if (dev->ctx->ops->set_blocking_mode)
307 return dev->ctx->ops->set_blocking_mode(dev, blocking);
308 else
309 return -ENOSYS;
310}
311
Paul Cercueilec1760d2014-02-21 11:31:20 +0100312ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100313 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100314{
315 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100316 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100317 else
318 return -ENOSYS;
319}
320
321ssize_t iio_device_write_raw(const struct iio_device *dev,
322 const void *src, size_t len)
323{
324 if (dev->ctx->ops->write)
325 return dev->ctx->ops->write(dev, src, len);
326 else
327 return -ENOSYS;
328}
329
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100330ssize_t iio_device_attr_read(const struct iio_device *dev,
331 const char *attr, char *dst, size_t len)
332{
Paul Cercueil6a013602014-02-19 12:37:39 +0100333 if (dev->ctx->ops->read_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200334 return dev->ctx->ops->read_device_attr(dev,
335 attr, dst, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100336 else
337 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100338}
339
Paul Cercueilcecda352014-05-06 18:14:29 +0200340ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
341 const char *attr, const void *src, size_t len)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100342{
Paul Cercueil6a013602014-02-19 12:37:39 +0100343 if (dev->ctx->ops->write_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200344 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200345 attr, src, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100346 else
347 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100348}
Paul Cercueil00236242014-02-18 15:09:06 +0100349
Paul Cercueilcecda352014-05-06 18:14:29 +0200350ssize_t iio_device_attr_write(const struct iio_device *dev,
351 const char *attr, const char *src)
352{
353 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
354}
355
Paul Cercueild96e61f2014-03-07 16:13:37 +0100356void iio_device_set_data(struct iio_device *dev, void *data)
357{
358 dev->userdata = data;
359}
360
361void * iio_device_get_data(const struct iio_device *dev)
362{
363 return dev->userdata;
364}
365
Paul Cercueil3156f632014-03-10 11:22:55 +0100366bool iio_device_is_trigger(const struct iio_device *dev)
367{
368 /* A trigger has a name, an id which starts by "trigger",
369 * and zero channels. */
370
371 unsigned int nb = iio_device_get_channels_count(dev);
372 const char *name = iio_device_get_name(dev),
373 *id = iio_device_get_id(dev);
374 return ((nb == 0) && !!name &&
375 !strncmp(id, "trigger", sizeof("trigger") - 1));
376}
377
Romain Roffé6c385d92015-06-30 13:36:05 +0200378int iio_device_set_kernel_buffers_count(const struct iio_device *dev,
379 unsigned int nb_buffers)
380{
381 if (nb_buffers == 0)
382 return -EINVAL;
383 else if (dev->ctx->ops->set_kernel_buffers_count)
384 return dev->ctx->ops->set_kernel_buffers_count(dev, nb_buffers);
385 else
386 return -ENOSYS;
387}
388
Paul Cercueil24ffa532014-03-10 12:39:58 +0100389int iio_device_get_trigger(const struct iio_device *dev,
390 const struct iio_device **trigger)
391{
392 if (!trigger)
393 return -EINVAL;
394 else if (dev->ctx->ops->get_trigger)
395 return dev->ctx->ops->get_trigger(dev, trigger);
396 else
397 return -ENOSYS;
398}
399
400int iio_device_set_trigger(const struct iio_device *dev,
401 const struct iio_device *trigger)
402{
403 if (trigger && !iio_device_is_trigger(trigger))
404 return -EINVAL;
405 else if (dev->ctx->ops->set_trigger)
406 return dev->ctx->ops->set_trigger(dev, trigger);
407 else
408 return -ENOSYS;
409}
410
Paul Cercueil00236242014-02-18 15:09:06 +0100411void free_device(struct iio_device *dev)
412{
413 unsigned int i;
414 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200415 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100416 if (dev->nb_attrs)
417 free(dev->attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200418 for (i = 0; i < dev->nb_debug_attrs; i++)
419 free(dev->debug_attrs[i]);
420 if (dev->nb_debug_attrs)
421 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100422 for (i = 0; i < dev->nb_channels; i++)
423 free_channel(dev->channels[i]);
424 if (dev->nb_channels)
425 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100426 if (dev->mask)
427 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100428 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200429 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100430 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200431 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100432 free(dev);
433}
Paul Cercueil1a474732014-03-17 11:38:34 +0100434
Paul Cercueil645ab972014-03-24 14:36:12 +0100435ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil92f15c22015-04-20 11:36:51 +0200436 const uint32_t *mask, size_t words)
Paul Cercueil1a474732014-03-17 11:38:34 +0100437{
438 ssize_t size = 0;
439 unsigned int i;
440
441 if (words != (dev->nb_channels + 31) / 32)
442 return -EINVAL;
443
444 for (i = 0; i < dev->nb_channels; i++) {
445 const struct iio_channel *chn = dev->channels[i];
446 unsigned int length = chn->format.length / 8;
447
448 if (chn->index < 0)
449 break;
450 if (!TEST_BIT(mask, chn->index))
451 continue;
452
453 if (size % length)
454 size += 2 * length - (size % length);
455 else
456 size += length;
457 }
458 return size;
459}
Paul Cercueil46825942014-03-18 14:28:49 +0100460
Paul Cercueil645ab972014-03-24 14:36:12 +0100461ssize_t iio_device_get_sample_size(const struct iio_device *dev)
462{
463 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
464}
465
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200466int iio_device_attr_read_longlong(const struct iio_device *dev,
467 const char *attr, long long *val)
468{
469 char *end, buf[1024];
470 long long value;
471 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
472 if (ret < 0)
473 return (int) ret;
474
475 value = strtoll(buf, &end, 0);
476 if (end == buf)
477 return -EINVAL;
478 *val = value;
479 return 0;
480}
481
482int iio_device_attr_read_bool(const struct iio_device *dev,
483 const char *attr, bool *val)
484{
485 long long value;
486 int ret = iio_device_attr_read_longlong(dev, attr, &value);
487 if (ret < 0)
488 return ret;
489
490 *val = !!value;
491 return 0;
492}
493
494int iio_device_attr_read_double(const struct iio_device *dev,
495 const char *attr, double *val)
496{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200497 char buf[1024];
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200498 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
499 if (ret < 0)
500 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200501 else
502 return read_double(buf, val);
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200503}
504
505int iio_device_attr_write_longlong(const struct iio_device *dev,
506 const char *attr, long long val)
507{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200508 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200509 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200510
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200511 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200512 ret = iio_device_attr_write(dev, attr, buf);
513
514 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200515}
516
517int iio_device_attr_write_double(const struct iio_device *dev,
518 const char *attr, double val)
519{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200520 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200521 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200522
Paul Cercueil225a3e12015-03-03 18:08:41 +0100523 ret = (ssize_t) write_double(buf, sizeof(buf), val);
524 if (!ret)
525 ret = iio_device_attr_write(dev, attr, buf);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200526 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200527}
528
529int iio_device_attr_write_bool(const struct iio_device *dev,
530 const char *attr, bool val)
531{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200532 ssize_t ret;
533
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200534 if (val)
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200535 ret = iio_device_attr_write(dev, attr, "1");
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200536 else
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200537 ret = iio_device_attr_write(dev, attr, "0");
538
539 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200540}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200541
542ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
543 const char *attr, char *dst, size_t len)
544{
545 if (dev->ctx->ops->read_device_attr)
546 return dev->ctx->ops->read_device_attr(dev,
547 attr, dst, len, true);
548 else
549 return -ENOSYS;
550}
551
Paul Cercueilcecda352014-05-06 18:14:29 +0200552ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
553 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200554{
555 if (dev->ctx->ops->write_device_attr)
556 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200557 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200558 else
559 return -ENOSYS;
560}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200561
Paul Cercueilcecda352014-05-06 18:14:29 +0200562ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
563 const char *attr, const char *src)
564{
565 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
566}
567
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200568unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
569{
570 return dev->nb_debug_attrs;
571}
572
573const char * iio_device_get_debug_attr(const struct iio_device *dev,
574 unsigned int index)
575{
576 if (index >= dev->nb_debug_attrs)
577 return NULL;
578 else
579 return dev->debug_attrs[index];
580}
Paul Cercueile3960742014-04-15 16:00:50 +0200581
582int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
583 const char *attr, long long *val)
584{
585 char *end, buf[1024];
586 long long value;
587 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
588 if (ret < 0)
589 return (int) ret;
590
591 value = strtoll(buf, &end, 0);
592 if (end == buf)
593 return -EINVAL;
594 *val = value;
595 return 0;
596}
597
598int iio_device_debug_attr_read_bool(const struct iio_device *dev,
599 const char *attr, bool *val)
600{
601 long long value;
602 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
603 if (ret < 0)
604 return ret;
605
606 *val = !!value;
607 return 0;
608}
609
610int iio_device_debug_attr_read_double(const struct iio_device *dev,
611 const char *attr, double *val)
612{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200613 char buf[1024];
Paul Cercueile3960742014-04-15 16:00:50 +0200614 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
615 if (ret < 0)
616 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200617 else
618 return read_double(buf, val);
Paul Cercueile3960742014-04-15 16:00:50 +0200619}
620
621int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
622 const char *attr, long long val)
623{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200624 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200625 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200626
Paul Cercueile3960742014-04-15 16:00:50 +0200627 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200628 ret = iio_device_debug_attr_write(dev, attr, buf);
629
630 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200631}
632
633int iio_device_debug_attr_write_double(const struct iio_device *dev,
634 const char *attr, double val)
635{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200636 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200637 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200638
Paul Cercueil225a3e12015-03-03 18:08:41 +0100639 ret = (ssize_t) write_double(buf, sizeof(buf), val);
640 if (!ret)
641 ret = iio_device_debug_attr_write(dev, attr, buf);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200642 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200643}
644
645int iio_device_debug_attr_write_bool(const struct iio_device *dev,
646 const char *attr, bool val)
647{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200648 ssize_t ret;
649
Paul Cercueile3960742014-04-15 16:00:50 +0200650 if (val)
Andrea Galbuserac547d222014-07-28 08:50:46 +0200651 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200652 else
Andrea Galbuserac547d222014-07-28 08:50:46 +0200653 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
654
655 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200656}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200657
658int iio_device_identify_filename(const struct iio_device *dev,
659 const char *filename, struct iio_channel **chn,
660 const char **attr)
661{
662 unsigned int i;
663
664 for (i = 0; i < dev->nb_channels; i++) {
665 struct iio_channel *ch = dev->channels[i];
666 unsigned int j;
667
668 for (j = 0; j < ch->nb_attrs; j++) {
669 if (!strcmp(ch->attrs[j].filename, filename)) {
670 *attr = ch->attrs[j].name;
671 *chn = ch;
672 return 0;
673 }
674 }
675 }
676
677 for (i = 0; i < dev->nb_attrs; i++) {
678 /* Devices attributes are named after their filename */
679 if (!strcmp(dev->attrs[i], filename)) {
680 *attr = dev->attrs[i];
681 *chn = NULL;
682 return 0;
683 }
684 }
685
686 for (i = 0; i < dev->nb_debug_attrs; i++) {
687 if (!strcmp(dev->debug_attrs[i], filename)) {
688 *attr = dev->debug_attrs[i];
689 *chn = NULL;
690 return 0;
691 }
692 }
693
694 return -EINVAL;
695}
Paul Cercueil14405872014-05-07 14:00:32 +0200696
697int iio_device_reg_write(struct iio_device *dev,
698 uint32_t address, uint32_t value)
699{
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200700 ssize_t ret;
701
Paul Cercueil14405872014-05-07 14:00:32 +0200702 char buf[1024];
703 snprintf(buf, sizeof(buf), "0x%x 0x%x", address, value);
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200704 ret = iio_device_debug_attr_write(dev, "direct_reg_access", buf);
705
706 return ret < 0 ? ret : 0;
Paul Cercueil14405872014-05-07 14:00:32 +0200707}
708
709int iio_device_reg_read(struct iio_device *dev,
710 uint32_t address, uint32_t *value)
711{
712 /* NOTE: There is a race condition here. But it is extremely unlikely to
713 * happen, and as this is a debug function, it shouldn't be used for
714 * something else than debug. */
715
716 long long val;
717 int ret = iio_device_debug_attr_write_longlong(dev,
718 "direct_reg_access", (long long) address);
719 if (ret < 0)
720 return ret;
721
722 ret = iio_device_debug_attr_read_longlong(dev,
723 "direct_reg_access", &val);
724 if (!ret)
725 *value = (uint32_t) val;
726 return ret;
727}
Paul Cercueil1b36a012014-06-05 14:39:31 +0200728
729static int read_each_attr(struct iio_device *dev, bool is_debug,
730 int (*cb)(struct iio_device *dev,
731 const char *attr, const char *val, size_t len, void *d),
732 void *data)
733{
734 int ret;
735 char *buf, *ptr;
736 unsigned int i, count;
737
738 /* We need a big buffer here; 1 MiB should be enough */
739 buf = malloc(0x100000);
740 if (!buf)
741 return -ENOMEM;
742
743 if (is_debug) {
744 count = iio_device_get_debug_attrs_count(dev);
745 ret = (int) iio_device_debug_attr_read(dev,
746 NULL, buf, 0x100000);
747 } else {
748 count = iio_device_get_attrs_count(dev);
749 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
750 }
751
752 if (ret < 0)
753 goto err_free_buf;
754
755 ptr = buf;
756
757 for (i = 0; i < count; i++) {
758 const char *attr;
759 int32_t len = (int32_t) ntohl(*(uint32_t *) ptr);
760
761 if (is_debug)
762 attr = iio_device_get_debug_attr(dev, i);
763 else
764 attr = iio_device_get_attr(dev, i);
765
766 ptr += 4;
767 if (len > 0) {
768 ret = cb(dev, attr, ptr, (size_t) len, data);
769 if (ret < 0)
770 goto err_free_buf;
771
772 if (len & 0x3)
773 len = ((len >> 2) + 1) << 2;
774 ptr += len;
775 }
776 }
777
778err_free_buf:
779 free(buf);
780 return ret < 0 ? ret : 0;
781}
782
783static int write_each_attr(struct iio_device *dev, bool is_debug,
784 ssize_t (*cb)(struct iio_device *dev,
785 const char *attr, void *buf, size_t len, void *d),
786 void *data)
787{
788 char *buf, *ptr;
789 unsigned int i, count;
790 size_t len = 0x100000;
791 int ret;
792
793 /* We need a big buffer here; 1 MiB should be enough */
794 buf = malloc(len);
795 if (!buf)
796 return -ENOMEM;
797
798 ptr = buf;
799
800 if (is_debug)
801 count = iio_device_get_debug_attrs_count(dev);
802 else
803 count = iio_device_get_attrs_count(dev);
804
805 for (i = 0; i < count; i++) {
806 const char *attr;
807
808 if (is_debug)
809 attr = iio_device_get_debug_attr(dev, i);
810 else
811 attr = iio_device_get_attr(dev, i);
812
813 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
814 if (ret < 0)
815 goto err_free_buf;
816
817 *(int32_t *) ptr = (int32_t) htonl((uint32_t) ret);
818 ptr += 4;
819 len -= 4;
820
821 if (ret > 0) {
822 if (ret & 0x3)
823 ret = ((ret >> 2) + 1) << 2;
824 ptr += ret;
825 len -= ret;
826 }
827 }
828
829 if (is_debug)
830 ret = (int) iio_device_debug_attr_write_raw(dev,
831 NULL, buf, ptr - buf);
832 else
833 ret = (int) iio_device_attr_write_raw(dev,
834 NULL, buf, ptr - buf);
835
836err_free_buf:
837 free(buf);
838 return ret < 0 ? ret : 0;
839}
840
841int iio_device_debug_attr_read_all(struct iio_device *dev,
842 int (*cb)(struct iio_device *dev,
843 const char *attr, const char *val, size_t len, void *d),
844 void *data)
845{
846 return read_each_attr(dev, true, cb, data);
847}
848
849int iio_device_attr_read_all(struct iio_device *dev,
850 int (*cb)(struct iio_device *dev,
851 const char *attr, const char *val, size_t len, void *d),
852 void *data)
853{
854 return read_each_attr(dev, false, cb, data);
855}
856
857int iio_device_debug_attr_write_all(struct iio_device *dev,
858 ssize_t (*cb)(struct iio_device *dev,
859 const char *attr, void *buf, size_t len, void *d),
860 void *data)
861{
862 return write_each_attr(dev, true, cb, data);
863}
864
865int iio_device_attr_write_all(struct iio_device *dev,
866 ssize_t (*cb)(struct iio_device *dev,
867 const char *attr, void *buf, size_t len, void *d),
868 void *data)
869{
870 return write_each_attr(dev, false, cb, data);
871}
Paul Cercueil03b6c812015-04-14 16:49:06 +0200872
873const struct iio_context * iio_device_get_context(const struct iio_device *dev)
874{
875 return dev->ctx;
876}