blob: 0fc88bcfdd8ed7b7c3a2d063ead069b62a0e01d0 [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 Cercueil2042c902016-04-25 18:43:45 +020019#include "debug.h"
Paul Cercueil0b2ce712014-02-17 15:04:18 +010020#include "iio-private.h"
21
Paul Cercueil9e4df462016-04-27 11:34:38 +020022#include <inttypes.h>
Paul Cercueil6a013602014-02-19 12:37:39 +010023#include <errno.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010024#include <stdio.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010025#include <string.h>
26
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020027static char *get_attr_xml(const char *attr, size_t *length, bool is_debug)
Paul Cercueil42090d12014-02-24 12:32:23 +010028{
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020029 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr)
30 + (!is_debug ? 0 : sizeof("debug-") - 1);
Paul Cercueil42090d12014-02-24 12:32:23 +010031 char *str = malloc(len);
Paul Cercueildfeca0d2015-03-16 17:18:00 +010032 if (!str)
Paul Cercueil42090d12014-02-24 12:32:23 +010033 return NULL;
Paul Cercueil42090d12014-02-24 12:32:23 +010034
35 *length = len - 1; /* Skip the \0 */
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020036 if (is_debug)
Paul Cercueil9c9a5562017-01-24 10:48:31 +010037 iio_snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020038 else
Paul Cercueil9c9a5562017-01-24 10:48:31 +010039 iio_snprintf(str, len, "<attribute name=\"%s\" />", attr);
Paul Cercueil42090d12014-02-24 12:32:23 +010040 return str;
41}
42
43/* Returns a string containing the XML representation of this device */
44char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
45{
Paul Cercueil8c29e412014-04-07 09:46:45 +020046 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
47 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020048 char *ptr, *str, **attrs, **channels, **debug_attrs;
49 size_t *attrs_len, *channels_len, *debug_attrs_len;
50 unsigned int i, j, k;
Paul Cercueil5822ab62014-04-04 13:29:17 +020051
52 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
53 if (!attrs_len)
54 return NULL;
55
56 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
57 if (!attrs)
58 goto err_free_attrs_len;
59
Paul Cercueil42090d12014-02-24 12:32:23 +010060 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020061 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
Paul Cercueil42090d12014-02-24 12:32:23 +010062 if (!xml)
63 goto err_free_attrs;
64 attrs[i] = xml;
65 len += attrs_len[i];
66 }
67
Paul Cercueil8c29e412014-04-07 09:46:45 +020068 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
69 if (!channels_len)
70 goto err_free_attrs;
71
72 channels = malloc(dev->nb_channels * sizeof(*channels));
73 if (!channels)
74 goto err_free_channels_len;
75
Paul Cercueil42090d12014-02-24 12:32:23 +010076 for (j = 0; j < dev->nb_channels; j++) {
77 char *xml = iio_channel_get_xml(dev->channels[j],
78 &channels_len[j]);
79 if (!xml)
80 goto err_free_channels;
81 channels[j] = xml;
82 len += channels_len[j];
83 }
84
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020085 debug_attrs_len = malloc(dev->nb_debug_attrs *
86 sizeof(*debug_attrs_len));
87 if (!debug_attrs_len)
88 goto err_free_channels;
89
90 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
91 if (!debug_attrs)
92 goto err_free_debug_attrs_len;
93
94 for (k = 0; k < dev->nb_debug_attrs; k++) {
95 char *xml = get_attr_xml(dev->debug_attrs[k],
96 &debug_attrs_len[k], true);
97 if (!xml)
98 goto err_free_debug_attrs;
99 debug_attrs[k] = xml;
100 len += debug_attrs_len[k];
101 }
102
Paul Cercueil42090d12014-02-24 12:32:23 +0100103 str = malloc(len);
104 if (!str)
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200105 goto err_free_debug_attrs;
Paul Cercueil42090d12014-02-24 12:32:23 +0100106
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100107 iio_snprintf(str, len, "<device id=\"%s\"", dev->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100108 ptr = strrchr(str, '\0');
109
110 if (dev->name) {
111 sprintf(ptr, " name=\"%s\"", dev->name);
112 ptr = strrchr(ptr, '\0');
113 }
114
115 strcpy(ptr, " >");
116 ptr += 2;
117
118 for (i = 0; i < dev->nb_channels; i++) {
119 strcpy(ptr, channels[i]);
120 ptr += channels_len[i];
121 free(channels[i]);
122 }
123
Paul Cercueil5822ab62014-04-04 13:29:17 +0200124 free(channels);
125 free(channels_len);
126
Paul Cercueil42090d12014-02-24 12:32:23 +0100127 for (i = 0; i < dev->nb_attrs; i++) {
128 strcpy(ptr, attrs[i]);
129 ptr += attrs_len[i];
130 free(attrs[i]);
131 }
132
Paul Cercueil5822ab62014-04-04 13:29:17 +0200133 free(attrs);
134 free(attrs_len);
135
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200136 for (i = 0; i < dev->nb_debug_attrs; i++) {
137 strcpy(ptr, debug_attrs[i]);
138 ptr += debug_attrs_len[i];
139 free(debug_attrs[i]);
140 }
141
142 free(debug_attrs);
143 free(debug_attrs_len);
144
Paul Cercueil42090d12014-02-24 12:32:23 +0100145 strcpy(ptr, "</device>");
146 *length = ptr - str + sizeof("</device>") - 1;
147 return str;
148
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200149err_free_debug_attrs:
150 while (k--)
151 free(debug_attrs[k]);
152 free(debug_attrs);
153err_free_debug_attrs_len:
154 free(debug_attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100155err_free_channels:
156 while (j--)
157 free(channels[j]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200158 free(channels);
159err_free_channels_len:
160 free(channels_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100161err_free_attrs:
162 while (i--)
163 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200164 free(attrs);
165err_free_attrs_len:
166 free(attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100167 return NULL;
168}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100169
170const char * iio_device_get_id(const struct iio_device *dev)
171{
172 return dev->id;
173}
174
175const char * iio_device_get_name(const struct iio_device *dev)
176{
177 return dev->name;
178}
179
180unsigned int iio_device_get_channels_count(const struct iio_device *dev)
181{
182 return dev->nb_channels;
183}
184
185struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
186 unsigned int index)
187{
188 if (index >= dev->nb_channels)
189 return NULL;
190 else
191 return dev->channels[index];
192}
193
Paul Cercueil17512b02014-03-28 11:15:24 +0100194struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100195 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100196{
197 unsigned int i;
198 for (i = 0; i < dev->nb_channels; i++) {
199 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100200 if (iio_channel_is_output(chn) != output)
201 continue;
202
Paul Cercueil17512b02014-03-28 11:15:24 +0100203 if (!strcmp(chn->id, name) ||
204 (chn->name && !strcmp(chn->name, name)))
205 return chn;
206 }
207 return NULL;
208}
209
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100210unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
211{
212 return dev->nb_attrs;
213}
214
215const char * iio_device_get_attr(const struct iio_device *dev,
216 unsigned int index)
217{
218 if (index >= dev->nb_attrs)
219 return NULL;
220 else
221 return dev->attrs[index];
222}
223
Paul Cercueil4f838d02014-03-28 11:26:15 +0100224const char * iio_device_find_attr(const struct iio_device *dev,
225 const char *name)
226{
227 unsigned int i;
228 for (i = 0; i < dev->nb_attrs; i++) {
229 const char *attr = dev->attrs[i];
230 if (!strcmp(attr, name))
231 return attr;
232 }
233 return NULL;
234}
235
Paul Cercueil001d2152014-06-03 15:24:44 +0200236const char * iio_device_find_debug_attr(const struct iio_device *dev,
237 const char *name)
238{
239 unsigned int i;
240 for (i = 0; i < dev->nb_debug_attrs; i++) {
241 const char *attr = dev->debug_attrs[i];
242 if (!strcmp(attr, name))
243 return attr;
244 }
245 return NULL;
246}
247
Lars-Peter Clausen62bd5522015-03-27 16:06:52 +0100248bool iio_device_is_tx(const struct iio_device *dev)
249{
250 unsigned int i;
251
252 for (i = 0; i < dev->nb_channels; i++) {
253 struct iio_channel *ch = dev->channels[i];
254 if (iio_channel_is_output(ch) && iio_channel_is_enabled(ch))
255 return true;
256 }
257
258 return false;
259}
260
Paul Cercueil92f15c22015-04-20 11:36:51 +0200261int iio_device_open(const struct iio_device *dev,
262 size_t samples_count, bool cyclic)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100263{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100264 unsigned int i;
265 bool has_channels = false;
266
Paul Cercueil92f15c22015-04-20 11:36:51 +0200267 for (i = 0; !has_channels && i < dev->words; i++)
268 has_channels = !!dev->mask[i];
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100269 if (!has_channels)
270 return -EINVAL;
271
Paul Cercueilec1760d2014-02-21 11:31:20 +0100272 if (dev->ctx->ops->open)
Paul Cercueil92f15c22015-04-20 11:36:51 +0200273 return dev->ctx->ops->open(dev, samples_count, cyclic);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100274 else
275 return -ENOSYS;
276}
277
278int iio_device_close(const struct iio_device *dev)
279{
280 if (dev->ctx->ops->close)
281 return dev->ctx->ops->close(dev);
282 else
283 return -ENOSYS;
284}
285
Romain Roffé6a881702015-06-30 16:25:43 +0200286int iio_device_get_poll_fd(const struct iio_device *dev)
287{
288 if (dev->ctx->ops->get_fd)
289 return dev->ctx->ops->get_fd(dev);
290 else
291 return -ENOSYS;
292}
293
Romain Roffé0ea038d2015-06-30 13:35:38 +0200294int iio_device_set_blocking_mode(const struct iio_device *dev, bool blocking)
295{
296 if (dev->ctx->ops->set_blocking_mode)
297 return dev->ctx->ops->set_blocking_mode(dev, blocking);
298 else
299 return -ENOSYS;
300}
301
Paul Cercueilec1760d2014-02-21 11:31:20 +0100302ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100303 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100304{
305 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100306 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100307 else
308 return -ENOSYS;
309}
310
311ssize_t iio_device_write_raw(const struct iio_device *dev,
312 const void *src, size_t len)
313{
314 if (dev->ctx->ops->write)
315 return dev->ctx->ops->write(dev, src, len);
316 else
317 return -ENOSYS;
318}
319
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100320ssize_t iio_device_attr_read(const struct iio_device *dev,
321 const char *attr, char *dst, size_t len)
322{
Paul Cercueil6a013602014-02-19 12:37:39 +0100323 if (dev->ctx->ops->read_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200324 return dev->ctx->ops->read_device_attr(dev,
325 attr, dst, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100326 else
327 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100328}
329
Paul Cercueilcecda352014-05-06 18:14:29 +0200330ssize_t iio_device_attr_write_raw(const struct iio_device *dev,
331 const char *attr, const void *src, size_t len)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100332{
Paul Cercueil6a013602014-02-19 12:37:39 +0100333 if (dev->ctx->ops->write_device_attr)
Paul Cercueil50c762a2014-04-14 15:55:43 +0200334 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200335 attr, src, len, false);
Paul Cercueil6a013602014-02-19 12:37:39 +0100336 else
337 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100338}
Paul Cercueil00236242014-02-18 15:09:06 +0100339
Paul Cercueilcecda352014-05-06 18:14:29 +0200340ssize_t iio_device_attr_write(const struct iio_device *dev,
341 const char *attr, const char *src)
342{
343 return iio_device_attr_write_raw(dev, attr, src, strlen(src) + 1);
344}
345
Paul Cercueild96e61f2014-03-07 16:13:37 +0100346void iio_device_set_data(struct iio_device *dev, void *data)
347{
348 dev->userdata = data;
349}
350
351void * iio_device_get_data(const struct iio_device *dev)
352{
353 return dev->userdata;
354}
355
Paul Cercueil3156f632014-03-10 11:22:55 +0100356bool iio_device_is_trigger(const struct iio_device *dev)
357{
358 /* A trigger has a name, an id which starts by "trigger",
359 * and zero channels. */
360
361 unsigned int nb = iio_device_get_channels_count(dev);
362 const char *name = iio_device_get_name(dev),
363 *id = iio_device_get_id(dev);
364 return ((nb == 0) && !!name &&
365 !strncmp(id, "trigger", sizeof("trigger") - 1));
366}
367
Romain Roffé6c385d92015-06-30 13:36:05 +0200368int iio_device_set_kernel_buffers_count(const struct iio_device *dev,
369 unsigned int nb_buffers)
370{
371 if (nb_buffers == 0)
372 return -EINVAL;
373 else if (dev->ctx->ops->set_kernel_buffers_count)
374 return dev->ctx->ops->set_kernel_buffers_count(dev, nb_buffers);
375 else
376 return -ENOSYS;
377}
378
Paul Cercueil24ffa532014-03-10 12:39:58 +0100379int iio_device_get_trigger(const struct iio_device *dev,
380 const struct iio_device **trigger)
381{
382 if (!trigger)
383 return -EINVAL;
384 else if (dev->ctx->ops->get_trigger)
385 return dev->ctx->ops->get_trigger(dev, trigger);
386 else
387 return -ENOSYS;
388}
389
390int iio_device_set_trigger(const struct iio_device *dev,
391 const struct iio_device *trigger)
392{
393 if (trigger && !iio_device_is_trigger(trigger))
394 return -EINVAL;
395 else if (dev->ctx->ops->set_trigger)
396 return dev->ctx->ops->set_trigger(dev, trigger);
397 else
398 return -ENOSYS;
399}
400
Paul Cercueil00236242014-02-18 15:09:06 +0100401void free_device(struct iio_device *dev)
402{
403 unsigned int i;
404 for (i = 0; i < dev->nb_attrs; i++)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200405 free(dev->attrs[i]);
Paul Cercueil00236242014-02-18 15:09:06 +0100406 if (dev->nb_attrs)
407 free(dev->attrs);
Matt Fornero7f9598f2017-11-30 14:07:52 -0500408 for (i = 0; i < dev->nb_buffer_attrs; i++)
409 free(dev->buffer_attrs[i]);
410 if (dev->nb_buffer_attrs)
411 free(dev->buffer_attrs);
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200412 for (i = 0; i < dev->nb_debug_attrs; i++)
413 free(dev->debug_attrs[i]);
414 if (dev->nb_debug_attrs)
415 free(dev->debug_attrs);
Paul Cercueil00236242014-02-18 15:09:06 +0100416 for (i = 0; i < dev->nb_channels; i++)
417 free_channel(dev->channels[i]);
418 if (dev->nb_channels)
419 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100420 if (dev->mask)
421 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100422 if (dev->name)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200423 free(dev->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100424 if (dev->id)
Paul Cercueilddaa26a2014-04-14 17:32:18 +0200425 free(dev->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100426 free(dev);
427}
Paul Cercueil1a474732014-03-17 11:38:34 +0100428
Paul Cercueil645ab972014-03-24 14:36:12 +0100429ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil92f15c22015-04-20 11:36:51 +0200430 const uint32_t *mask, size_t words)
Paul Cercueil1a474732014-03-17 11:38:34 +0100431{
432 ssize_t size = 0;
433 unsigned int i;
Paul Cercueil5e3b9cd2017-04-11 17:31:46 +0200434 const struct iio_channel *prev = NULL;
Paul Cercueil1a474732014-03-17 11:38:34 +0100435
436 if (words != (dev->nb_channels + 31) / 32)
437 return -EINVAL;
438
439 for (i = 0; i < dev->nb_channels; i++) {
440 const struct iio_channel *chn = dev->channels[i];
Lucas Magasweran77fe2912016-08-29 13:47:29 -0700441 unsigned int length = chn->format.length / 8 *
442 chn->format.repeat;
Paul Cercueil1a474732014-03-17 11:38:34 +0100443
444 if (chn->index < 0)
445 break;
Paul Cercueil5e3b9cd2017-04-11 17:31:46 +0200446 if (!TEST_BIT(mask, chn->number))
Paul Cercueil1a474732014-03-17 11:38:34 +0100447 continue;
Paul Cercueil5e3b9cd2017-04-11 17:31:46 +0200448
449 if (prev && chn->index == prev->index) {
450 prev = chn;
Paul Cercueil965957d2015-12-16 14:51:05 +0100451 continue;
Paul Cercueil5e3b9cd2017-04-11 17:31:46 +0200452 }
Paul Cercueil1a474732014-03-17 11:38:34 +0100453
454 if (size % length)
455 size += 2 * length - (size % length);
456 else
457 size += length;
Paul Cercueil3d043d62017-04-24 11:37:45 +0200458
459 prev = chn;
Paul Cercueil1a474732014-03-17 11:38:34 +0100460 }
461 return size;
462}
Paul Cercueil46825942014-03-18 14:28:49 +0100463
Paul Cercueil645ab972014-03-24 14:36:12 +0100464ssize_t iio_device_get_sample_size(const struct iio_device *dev)
465{
466 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
467}
468
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200469int iio_device_attr_read_longlong(const struct iio_device *dev,
470 const char *attr, long long *val)
471{
472 char *end, buf[1024];
473 long long value;
474 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
475 if (ret < 0)
476 return (int) ret;
477
478 value = strtoll(buf, &end, 0);
479 if (end == buf)
480 return -EINVAL;
481 *val = value;
482 return 0;
483}
484
485int iio_device_attr_read_bool(const struct iio_device *dev,
486 const char *attr, bool *val)
487{
488 long long value;
489 int ret = iio_device_attr_read_longlong(dev, attr, &value);
490 if (ret < 0)
491 return ret;
492
493 *val = !!value;
494 return 0;
495}
496
497int iio_device_attr_read_double(const struct iio_device *dev,
498 const char *attr, double *val)
499{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200500 char buf[1024];
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200501 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
502 if (ret < 0)
503 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200504 else
505 return read_double(buf, val);
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200506}
507
508int iio_device_attr_write_longlong(const struct iio_device *dev,
509 const char *attr, long long val)
510{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200511 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200512 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200513
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100514 iio_snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200515 ret = iio_device_attr_write(dev, attr, buf);
516
517 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200518}
519
520int iio_device_attr_write_double(const struct iio_device *dev,
521 const char *attr, double val)
522{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200523 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200524 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200525
Paul Cercueil225a3e12015-03-03 18:08:41 +0100526 ret = (ssize_t) write_double(buf, sizeof(buf), val);
527 if (!ret)
528 ret = iio_device_attr_write(dev, attr, buf);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200529 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200530}
531
532int iio_device_attr_write_bool(const struct iio_device *dev,
533 const char *attr, bool val)
534{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200535 ssize_t ret;
536
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200537 if (val)
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200538 ret = iio_device_attr_write(dev, attr, "1");
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200539 else
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200540 ret = iio_device_attr_write(dev, attr, "0");
541
542 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200543}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200544
545ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
546 const char *attr, char *dst, size_t len)
547{
548 if (dev->ctx->ops->read_device_attr)
549 return dev->ctx->ops->read_device_attr(dev,
550 attr, dst, len, true);
551 else
552 return -ENOSYS;
553}
554
Paul Cercueilcecda352014-05-06 18:14:29 +0200555ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
556 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200557{
558 if (dev->ctx->ops->write_device_attr)
559 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200560 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200561 else
562 return -ENOSYS;
563}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200564
Paul Cercueilcecda352014-05-06 18:14:29 +0200565ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
566 const char *attr, const char *src)
567{
568 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
569}
570
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200571unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
572{
573 return dev->nb_debug_attrs;
574}
575
576const char * iio_device_get_debug_attr(const struct iio_device *dev,
577 unsigned int index)
578{
579 if (index >= dev->nb_debug_attrs)
580 return NULL;
581 else
582 return dev->debug_attrs[index];
583}
Paul Cercueile3960742014-04-15 16:00:50 +0200584
585int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
586 const char *attr, long long *val)
587{
588 char *end, buf[1024];
589 long long value;
590 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
591 if (ret < 0)
592 return (int) ret;
593
594 value = strtoll(buf, &end, 0);
595 if (end == buf)
596 return -EINVAL;
597 *val = value;
598 return 0;
599}
600
601int iio_device_debug_attr_read_bool(const struct iio_device *dev,
602 const char *attr, bool *val)
603{
604 long long value;
605 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
606 if (ret < 0)
607 return ret;
608
609 *val = !!value;
610 return 0;
611}
612
613int iio_device_debug_attr_read_double(const struct iio_device *dev,
614 const char *attr, double *val)
615{
Paul Cercueil542cbb42014-10-21 13:00:38 +0200616 char buf[1024];
Paul Cercueile3960742014-04-15 16:00:50 +0200617 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
618 if (ret < 0)
619 return (int) ret;
Paul Cercueil542cbb42014-10-21 13:00:38 +0200620 else
621 return read_double(buf, val);
Paul Cercueile3960742014-04-15 16:00:50 +0200622}
623
624int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
625 const char *attr, long long val)
626{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200627 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200628 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200629
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100630 iio_snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200631 ret = iio_device_debug_attr_write(dev, attr, buf);
632
633 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200634}
635
636int iio_device_debug_attr_write_double(const struct iio_device *dev,
637 const char *attr, double val)
638{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200639 ssize_t ret;
Paul Cercueile3960742014-04-15 16:00:50 +0200640 char buf[1024];
Paul Cercueil542cbb42014-10-21 13:00:38 +0200641
Paul Cercueil225a3e12015-03-03 18:08:41 +0100642 ret = (ssize_t) write_double(buf, sizeof(buf), val);
643 if (!ret)
644 ret = iio_device_debug_attr_write(dev, attr, buf);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200645 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200646}
647
648int iio_device_debug_attr_write_bool(const struct iio_device *dev,
649 const char *attr, bool val)
650{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200651 ssize_t ret;
652
Paul Cercueile3960742014-04-15 16:00:50 +0200653 if (val)
Andrea Galbuserac547d222014-07-28 08:50:46 +0200654 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200655 else
Andrea Galbuserac547d222014-07-28 08:50:46 +0200656 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
657
658 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200659}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200660
661int iio_device_identify_filename(const struct iio_device *dev,
662 const char *filename, struct iio_channel **chn,
663 const char **attr)
664{
665 unsigned int i;
666
667 for (i = 0; i < dev->nb_channels; i++) {
668 struct iio_channel *ch = dev->channels[i];
669 unsigned int j;
670
671 for (j = 0; j < ch->nb_attrs; j++) {
672 if (!strcmp(ch->attrs[j].filename, filename)) {
673 *attr = ch->attrs[j].name;
674 *chn = ch;
675 return 0;
676 }
677 }
678 }
679
680 for (i = 0; i < dev->nb_attrs; i++) {
681 /* Devices attributes are named after their filename */
682 if (!strcmp(dev->attrs[i], filename)) {
683 *attr = dev->attrs[i];
684 *chn = NULL;
685 return 0;
686 }
687 }
688
689 for (i = 0; i < dev->nb_debug_attrs; i++) {
690 if (!strcmp(dev->debug_attrs[i], filename)) {
691 *attr = dev->debug_attrs[i];
692 *chn = NULL;
693 return 0;
694 }
695 }
696
697 return -EINVAL;
698}
Paul Cercueil14405872014-05-07 14:00:32 +0200699
700int iio_device_reg_write(struct iio_device *dev,
701 uint32_t address, uint32_t value)
702{
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200703 ssize_t ret;
Paul Cercueil14405872014-05-07 14:00:32 +0200704 char buf[1024];
Paul Cercueil9c9a5562017-01-24 10:48:31 +0100705
706 iio_snprintf(buf, sizeof(buf), "0x%" PRIx32 " 0x%" PRIx32,
707 address, value);
Andrea Galbusera842cfa52014-07-28 08:50:46 +0200708 ret = iio_device_debug_attr_write(dev, "direct_reg_access", buf);
709
710 return ret < 0 ? ret : 0;
Paul Cercueil14405872014-05-07 14:00:32 +0200711}
712
713int iio_device_reg_read(struct iio_device *dev,
714 uint32_t address, uint32_t *value)
715{
716 /* NOTE: There is a race condition here. But it is extremely unlikely to
717 * happen, and as this is a debug function, it shouldn't be used for
718 * something else than debug. */
719
720 long long val;
721 int ret = iio_device_debug_attr_write_longlong(dev,
722 "direct_reg_access", (long long) address);
723 if (ret < 0)
724 return ret;
725
726 ret = iio_device_debug_attr_read_longlong(dev,
727 "direct_reg_access", &val);
728 if (!ret)
729 *value = (uint32_t) val;
730 return ret;
731}
Paul Cercueil1b36a012014-06-05 14:39:31 +0200732
733static int read_each_attr(struct iio_device *dev, bool is_debug,
734 int (*cb)(struct iio_device *dev,
735 const char *attr, const char *val, size_t len, void *d),
736 void *data)
737{
738 int ret;
739 char *buf, *ptr;
740 unsigned int i, count;
741
742 /* We need a big buffer here; 1 MiB should be enough */
743 buf = malloc(0x100000);
744 if (!buf)
745 return -ENOMEM;
746
747 if (is_debug) {
748 count = iio_device_get_debug_attrs_count(dev);
749 ret = (int) iio_device_debug_attr_read(dev,
750 NULL, buf, 0x100000);
751 } else {
752 count = iio_device_get_attrs_count(dev);
753 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
754 }
755
756 if (ret < 0)
757 goto err_free_buf;
758
759 ptr = buf;
760
761 for (i = 0; i < count; i++) {
762 const char *attr;
Paul Cercueil2042c902016-04-25 18:43:45 +0200763 int32_t len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
Paul Cercueil1b36a012014-06-05 14:39:31 +0200764
765 if (is_debug)
766 attr = iio_device_get_debug_attr(dev, i);
767 else
768 attr = iio_device_get_attr(dev, i);
769
770 ptr += 4;
771 if (len > 0) {
772 ret = cb(dev, attr, ptr, (size_t) len, data);
773 if (ret < 0)
774 goto err_free_buf;
775
776 if (len & 0x3)
777 len = ((len >> 2) + 1) << 2;
778 ptr += len;
779 }
780 }
781
782err_free_buf:
783 free(buf);
784 return ret < 0 ? ret : 0;
785}
786
787static int write_each_attr(struct iio_device *dev, bool is_debug,
788 ssize_t (*cb)(struct iio_device *dev,
789 const char *attr, void *buf, size_t len, void *d),
790 void *data)
791{
792 char *buf, *ptr;
793 unsigned int i, count;
794 size_t len = 0x100000;
795 int ret;
796
797 /* We need a big buffer here; 1 MiB should be enough */
798 buf = malloc(len);
799 if (!buf)
800 return -ENOMEM;
801
802 ptr = buf;
803
804 if (is_debug)
805 count = iio_device_get_debug_attrs_count(dev);
806 else
807 count = iio_device_get_attrs_count(dev);
808
809 for (i = 0; i < count; i++) {
810 const char *attr;
811
812 if (is_debug)
813 attr = iio_device_get_debug_attr(dev, i);
814 else
815 attr = iio_device_get_attr(dev, i);
816
817 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
818 if (ret < 0)
819 goto err_free_buf;
820
Paul Cercueil2042c902016-04-25 18:43:45 +0200821 *(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
Paul Cercueil1b36a012014-06-05 14:39:31 +0200822 ptr += 4;
823 len -= 4;
824
825 if (ret > 0) {
826 if (ret & 0x3)
827 ret = ((ret >> 2) + 1) << 2;
828 ptr += ret;
829 len -= ret;
830 }
831 }
832
833 if (is_debug)
834 ret = (int) iio_device_debug_attr_write_raw(dev,
835 NULL, buf, ptr - buf);
836 else
837 ret = (int) iio_device_attr_write_raw(dev,
838 NULL, buf, ptr - buf);
839
840err_free_buf:
841 free(buf);
842 return ret < 0 ? ret : 0;
843}
844
845int iio_device_debug_attr_read_all(struct iio_device *dev,
846 int (*cb)(struct iio_device *dev,
847 const char *attr, const char *val, size_t len, void *d),
848 void *data)
849{
850 return read_each_attr(dev, true, cb, data);
851}
852
853int iio_device_attr_read_all(struct iio_device *dev,
854 int (*cb)(struct iio_device *dev,
855 const char *attr, const char *val, size_t len, void *d),
856 void *data)
857{
858 return read_each_attr(dev, false, cb, data);
859}
860
861int iio_device_debug_attr_write_all(struct iio_device *dev,
862 ssize_t (*cb)(struct iio_device *dev,
863 const char *attr, void *buf, size_t len, void *d),
864 void *data)
865{
866 return write_each_attr(dev, true, cb, data);
867}
868
869int iio_device_attr_write_all(struct iio_device *dev,
870 ssize_t (*cb)(struct iio_device *dev,
871 const char *attr, void *buf, size_t len, void *d),
872 void *data)
873{
874 return write_each_attr(dev, false, cb, data);
875}
Paul Cercueil03b6c812015-04-14 16:49:06 +0200876
877const struct iio_context * iio_device_get_context(const struct iio_device *dev)
878{
879 return dev->ctx;
880}