blob: c95a59754f53875d924632cad1457597352c7803 [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
Paul Cercueil24ffa532014-03-10 12:39:58 +0100378int iio_device_get_trigger(const struct iio_device *dev,
379 const struct iio_device **trigger)
380{
381 if (!trigger)
382 return -EINVAL;
383 else if (dev->ctx->ops->get_trigger)
384 return dev->ctx->ops->get_trigger(dev, trigger);
385 else
386 return -ENOSYS;
387}
388
389int iio_device_set_trigger(const struct iio_device *dev,
390 const struct iio_device *trigger)
391{
392 if (trigger && !iio_device_is_trigger(trigger))
393 return -EINVAL;
394 else if (dev->ctx->ops->set_trigger)
395 return dev->ctx->ops->set_trigger(dev, trigger);
396 else
397 return -ENOSYS;
398}
399
Paul Cercueil00236242014-02-18 15:09:06 +0100400void free_device(struct iio_device *dev)
401{
402 unsigned int i;
403 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200404 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100405 if (dev->nb_attrs)
406 free(dev->attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200407 for (i = 0; i < dev->nb_debug_attrs; i++)
408 free(dev->debug_attrs[i]);
409 if (dev->nb_debug_attrs)
410 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100411 for (i = 0; i < dev->nb_channels; i++)
412 free_channel(dev->channels[i]);
413 if (dev->nb_channels)
414 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100415 if (dev->mask)
416 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100417 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200418 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100419 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200420 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100421 free(dev);
422}
Paul Cercueil1a474732014-03-17 11:38:34 +0100423
Paul Cercueil645ab972014-03-24 14:36:12 +0100424ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil92f15c22015-04-20 11:36:51 +0200425 const uint32_t *mask, size_t words)
Paul Cercueil1a474732014-03-17 11:38:34 +0100426{
427 ssize_t size = 0;
428 unsigned int i;
429
430 if (words != (dev->nb_channels + 31) / 32)
431 return -EINVAL;
432
433 for (i = 0; i < dev->nb_channels; i++) {
434 const struct iio_channel *chn = dev->channels[i];
435 unsigned int length = chn->format.length / 8;
436
437 if (chn->index < 0)
438 break;
439 if (!TEST_BIT(mask, chn->index))
440 continue;
441
442 if (size % length)
443 size += 2 * length - (size % length);
444 else
445 size += length;
446 }
447 return size;
448}
Paul Cercueil46825942014-03-18 14:28:49 +0100449
Paul Cercueil645ab972014-03-24 14:36:12 +0100450ssize_t iio_device_get_sample_size(const struct iio_device *dev)
451{
452 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
453}
454
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200455int iio_device_attr_read_longlong(const struct iio_device *dev,
456 const char *attr, long long *val)
457{
458 char *end, buf[1024];
459 long long value;
460 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
461 if (ret < 0)
462 return (int) ret;
463
464 value = strtoll(buf, &end, 0);
465 if (end == buf)
466 return -EINVAL;
467 *val = value;
468 return 0;
469}
470
471int iio_device_attr_read_bool(const struct iio_device *dev,
472 const char *attr, bool *val)
473{
474 long long value;
475 int ret = iio_device_attr_read_longlong(dev, attr, &value);
476 if (ret < 0)
477 return ret;
478
479 *val = !!value;
480 return 0;
481}
482
483int iio_device_attr_read_double(const struct iio_device *dev,
484 const char *attr, double *val)
485{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200486 char buf[1024];
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200487 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
488 if (ret < 0)
489 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200490 else
491 return read_double(buf, val);
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200492}
493
494int iio_device_attr_write_longlong(const struct iio_device *dev,
495 const char *attr, long long val)
496{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200497 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200498 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200499
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200500 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200501 ret = iio_device_attr_write(dev, attr, buf);
502
503 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200504}
505
506int iio_device_attr_write_double(const struct iio_device *dev,
507 const char *attr, double val)
508{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200509 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200510 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200511
Paul Cercueil225a3e12015-03-03 18:08:41 +0100512 ret = (ssize_t) write_double(buf, sizeof(buf), val);
513 if (!ret)
514 ret = iio_device_attr_write(dev, attr, buf);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200515 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200516}
517
518int iio_device_attr_write_bool(const struct iio_device *dev,
519 const char *attr, bool val)
520{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200521 ssize_t ret;
522
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200523 if (val)
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200524 ret = iio_device_attr_write(dev, attr, "1");
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200525 else
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200526 ret = iio_device_attr_write(dev, attr, "0");
527
528 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200529}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200530
531ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
532 const char *attr, char *dst, size_t len)
533{
534 if (dev->ctx->ops->read_device_attr)
535 return dev->ctx->ops->read_device_attr(dev,
536 attr, dst, len, true);
537 else
538 return -ENOSYS;
539}
540
Paul Cercueilcecda352014-05-06 18:14:29 +0200541ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
542 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200543{
544 if (dev->ctx->ops->write_device_attr)
545 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200546 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200547 else
548 return -ENOSYS;
549}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200550
Paul Cercueilcecda352014-05-06 18:14:29 +0200551ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
552 const char *attr, const char *src)
553{
554 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
555}
556
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200557unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
558{
559 return dev->nb_debug_attrs;
560}
561
562const char * iio_device_get_debug_attr(const struct iio_device *dev,
563 unsigned int index)
564{
565 if (index >= dev->nb_debug_attrs)
566 return NULL;
567 else
568 return dev->debug_attrs[index];
569}
Paul Cercueile3960742014-04-15 16:00:50 +0200570
571int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
572 const char *attr, long long *val)
573{
574 char *end, buf[1024];
575 long long value;
576 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
577 if (ret < 0)
578 return (int) ret;
579
580 value = strtoll(buf, &end, 0);
581 if (end == buf)
582 return -EINVAL;
583 *val = value;
584 return 0;
585}
586
587int iio_device_debug_attr_read_bool(const struct iio_device *dev,
588 const char *attr, bool *val)
589{
590 long long value;
591 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
592 if (ret < 0)
593 return ret;
594
595 *val = !!value;
596 return 0;
597}
598
599int iio_device_debug_attr_read_double(const struct iio_device *dev,
600 const char *attr, double *val)
601{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200602 char buf[1024];
Paul Cercueile3960742014-04-15 16:00:50 +0200603 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
604 if (ret < 0)
605 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200606 else
607 return read_double(buf, val);
Paul Cercueile3960742014-04-15 16:00:50 +0200608}
609
610int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
611 const char *attr, long long val)
612{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200613 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200614 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200615
Paul Cercueile3960742014-04-15 16:00:50 +0200616 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200617 ret = iio_device_debug_attr_write(dev, attr, buf);
618
619 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200620}
621
622int iio_device_debug_attr_write_double(const struct iio_device *dev,
623 const char *attr, double val)
624{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200625 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200626 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200627
Paul Cercueil225a3e12015-03-03 18:08:41 +0100628 ret = (ssize_t) write_double(buf, sizeof(buf), val);
629 if (!ret)
630 ret = iio_device_debug_attr_write(dev, attr, buf);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200631 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200632}
633
634int iio_device_debug_attr_write_bool(const struct iio_device *dev,
635 const char *attr, bool val)
636{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200637 ssize_t ret;
638
Paul Cercueile3960742014-04-15 16:00:50 +0200639 if (val)
Andrea Galbuserac547d222014-07-28 08:50:46 +0200640 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200641 else
Andrea Galbuserac547d222014-07-28 08:50:46 +0200642 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
643
644 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200645}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200646
647int iio_device_identify_filename(const struct iio_device *dev,
648 const char *filename, struct iio_channel **chn,
649 const char **attr)
650{
651 unsigned int i;
652
653 for (i = 0; i < dev->nb_channels; i++) {
654 struct iio_channel *ch = dev->channels[i];
655 unsigned int j;
656
657 for (j = 0; j < ch->nb_attrs; j++) {
658 if (!strcmp(ch->attrs[j].filename, filename)) {
659 *attr = ch->attrs[j].name;
660 *chn = ch;
661 return 0;
662 }
663 }
664 }
665
666 for (i = 0; i < dev->nb_attrs; i++) {
667 /* Devices attributes are named after their filename */
668 if (!strcmp(dev->attrs[i], filename)) {
669 *attr = dev->attrs[i];
670 *chn = NULL;
671 return 0;
672 }
673 }
674
675 for (i = 0; i < dev->nb_debug_attrs; i++) {
676 if (!strcmp(dev->debug_attrs[i], filename)) {
677 *attr = dev->debug_attrs[i];
678 *chn = NULL;
679 return 0;
680 }
681 }
682
683 return -EINVAL;
684}
Paul Cercueil14405872014-05-07 14:00:32 +0200685
686int iio_device_reg_write(struct iio_device *dev,
687 uint32_t address, uint32_t value)
688{
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200689 ssize_t ret;
690
Paul Cercueil14405872014-05-07 14:00:32 +0200691 char buf[1024];
692 snprintf(buf, sizeof(buf), "0x%x 0x%x", address, value);
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200693 ret = iio_device_debug_attr_write(dev, "direct_reg_access", buf);
694
695 return ret < 0 ? ret : 0;
Paul Cercueil14405872014-05-07 14:00:32 +0200696}
697
698int iio_device_reg_read(struct iio_device *dev,
699 uint32_t address, uint32_t *value)
700{
701 /* NOTE: There is a race condition here. But it is extremely unlikely to
702 * happen, and as this is a debug function, it shouldn't be used for
703 * something else than debug. */
704
705 long long val;
706 int ret = iio_device_debug_attr_write_longlong(dev,
707 "direct_reg_access", (long long) address);
708 if (ret < 0)
709 return ret;
710
711 ret = iio_device_debug_attr_read_longlong(dev,
712 "direct_reg_access", &val);
713 if (!ret)
714 *value = (uint32_t) val;
715 return ret;
716}
Paul Cercueil1b36a012014-06-05 14:39:31 +0200717
718static int read_each_attr(struct iio_device *dev, bool is_debug,
719 int (*cb)(struct iio_device *dev,
720 const char *attr, const char *val, size_t len, void *d),
721 void *data)
722{
723 int ret;
724 char *buf, *ptr;
725 unsigned int i, count;
726
727 /* We need a big buffer here; 1 MiB should be enough */
728 buf = malloc(0x100000);
729 if (!buf)
730 return -ENOMEM;
731
732 if (is_debug) {
733 count = iio_device_get_debug_attrs_count(dev);
734 ret = (int) iio_device_debug_attr_read(dev,
735 NULL, buf, 0x100000);
736 } else {
737 count = iio_device_get_attrs_count(dev);
738 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
739 }
740
741 if (ret < 0)
742 goto err_free_buf;
743
744 ptr = buf;
745
746 for (i = 0; i < count; i++) {
747 const char *attr;
748 int32_t len = (int32_t) ntohl(*(uint32_t *) ptr);
749
750 if (is_debug)
751 attr = iio_device_get_debug_attr(dev, i);
752 else
753 attr = iio_device_get_attr(dev, i);
754
755 ptr += 4;
756 if (len > 0) {
757 ret = cb(dev, attr, ptr, (size_t) len, data);
758 if (ret < 0)
759 goto err_free_buf;
760
761 if (len & 0x3)
762 len = ((len >> 2) + 1) << 2;
763 ptr += len;
764 }
765 }
766
767err_free_buf:
768 free(buf);
769 return ret < 0 ? ret : 0;
770}
771
772static int write_each_attr(struct iio_device *dev, bool is_debug,
773 ssize_t (*cb)(struct iio_device *dev,
774 const char *attr, void *buf, size_t len, void *d),
775 void *data)
776{
777 char *buf, *ptr;
778 unsigned int i, count;
779 size_t len = 0x100000;
780 int ret;
781
782 /* We need a big buffer here; 1 MiB should be enough */
783 buf = malloc(len);
784 if (!buf)
785 return -ENOMEM;
786
787 ptr = buf;
788
789 if (is_debug)
790 count = iio_device_get_debug_attrs_count(dev);
791 else
792 count = iio_device_get_attrs_count(dev);
793
794 for (i = 0; i < count; i++) {
795 const char *attr;
796
797 if (is_debug)
798 attr = iio_device_get_debug_attr(dev, i);
799 else
800 attr = iio_device_get_attr(dev, i);
801
802 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
803 if (ret < 0)
804 goto err_free_buf;
805
806 *(int32_t *) ptr = (int32_t) htonl((uint32_t) ret);
807 ptr += 4;
808 len -= 4;
809
810 if (ret > 0) {
811 if (ret & 0x3)
812 ret = ((ret >> 2) + 1) << 2;
813 ptr += ret;
814 len -= ret;
815 }
816 }
817
818 if (is_debug)
819 ret = (int) iio_device_debug_attr_write_raw(dev,
820 NULL, buf, ptr - buf);
821 else
822 ret = (int) iio_device_attr_write_raw(dev,
823 NULL, buf, ptr - buf);
824
825err_free_buf:
826 free(buf);
827 return ret < 0 ? ret : 0;
828}
829
830int iio_device_debug_attr_read_all(struct iio_device *dev,
831 int (*cb)(struct iio_device *dev,
832 const char *attr, const char *val, size_t len, void *d),
833 void *data)
834{
835 return read_each_attr(dev, true, cb, data);
836}
837
838int iio_device_attr_read_all(struct iio_device *dev,
839 int (*cb)(struct iio_device *dev,
840 const char *attr, const char *val, size_t len, void *d),
841 void *data)
842{
843 return read_each_attr(dev, false, cb, data);
844}
845
846int iio_device_debug_attr_write_all(struct iio_device *dev,
847 ssize_t (*cb)(struct iio_device *dev,
848 const char *attr, void *buf, size_t len, void *d),
849 void *data)
850{
851 return write_each_attr(dev, true, cb, data);
852}
853
854int iio_device_attr_write_all(struct iio_device *dev,
855 ssize_t (*cb)(struct iio_device *dev,
856 const char *attr, void *buf, size_t len, void *d),
857 void *data)
858{
859 return write_each_attr(dev, false, cb, data);
860}
Paul Cercueil03b6c812015-04-14 16:49:06 +0200861
862const struct iio_context * iio_device_get_context(const struct iio_device *dev)
863{
864 return dev->ctx;
865}