blob: 904978e497ea4bf28306a8e6000d86e6ff1591f3 [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);
42 if (!str) {
43 ERROR("Unable to allocate memory\n");
44 return NULL;
45 }
46
47 *length = len - 1; /* Skip the \0 */
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020048 if (is_debug)
49 snprintf(str, len, "<debug-attribute name=\"%s\" />", attr);
50 else
51 snprintf(str, len, "<attribute name=\"%s\" />", attr);
Paul Cercueil42090d12014-02-24 12:32:23 +010052 return str;
53}
54
55/* Returns a string containing the XML representation of this device */
56char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
57{
Paul Cercueil8c29e412014-04-07 09:46:45 +020058 size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
59 + strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020060 char *ptr, *str, **attrs, **channels, **debug_attrs;
61 size_t *attrs_len, *channels_len, *debug_attrs_len;
62 unsigned int i, j, k;
Paul Cercueil5822ab62014-04-04 13:29:17 +020063
64 attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
65 if (!attrs_len)
66 return NULL;
67
68 attrs = malloc(dev->nb_attrs * sizeof(*attrs));
69 if (!attrs)
70 goto err_free_attrs_len;
71
Paul Cercueil42090d12014-02-24 12:32:23 +010072 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020073 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i], false);
Paul Cercueil42090d12014-02-24 12:32:23 +010074 if (!xml)
75 goto err_free_attrs;
76 attrs[i] = xml;
77 len += attrs_len[i];
78 }
79
Paul Cercueil8c29e412014-04-07 09:46:45 +020080 channels_len = malloc(dev->nb_channels * sizeof(*channels_len));
81 if (!channels_len)
82 goto err_free_attrs;
83
84 channels = malloc(dev->nb_channels * sizeof(*channels));
85 if (!channels)
86 goto err_free_channels_len;
87
Paul Cercueil42090d12014-02-24 12:32:23 +010088 for (j = 0; j < dev->nb_channels; j++) {
89 char *xml = iio_channel_get_xml(dev->channels[j],
90 &channels_len[j]);
91 if (!xml)
92 goto err_free_channels;
93 channels[j] = xml;
94 len += channels_len[j];
95 }
96
Paul Cercueild9d9f9f2014-04-15 10:08:17 +020097 debug_attrs_len = malloc(dev->nb_debug_attrs *
98 sizeof(*debug_attrs_len));
99 if (!debug_attrs_len)
100 goto err_free_channels;
101
102 debug_attrs = malloc(dev->nb_debug_attrs * sizeof(*debug_attrs));
103 if (!debug_attrs)
104 goto err_free_debug_attrs_len;
105
106 for (k = 0; k < dev->nb_debug_attrs; k++) {
107 char *xml = get_attr_xml(dev->debug_attrs[k],
108 &debug_attrs_len[k], true);
109 if (!xml)
110 goto err_free_debug_attrs;
111 debug_attrs[k] = xml;
112 len += debug_attrs_len[k];
113 }
114
Paul Cercueil42090d12014-02-24 12:32:23 +0100115 str = malloc(len);
116 if (!str)
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200117 goto err_free_debug_attrs;
Paul Cercueil42090d12014-02-24 12:32:23 +0100118
Paul Cercueil8c29e412014-04-07 09:46:45 +0200119 snprintf(str, len, "<device id=\"%s\"", dev->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100120 ptr = strrchr(str, '\0');
121
122 if (dev->name) {
123 sprintf(ptr, " name=\"%s\"", dev->name);
124 ptr = strrchr(ptr, '\0');
125 }
126
127 strcpy(ptr, " >");
128 ptr += 2;
129
130 for (i = 0; i < dev->nb_channels; i++) {
131 strcpy(ptr, channels[i]);
132 ptr += channels_len[i];
133 free(channels[i]);
134 }
135
Paul Cercueil5822ab62014-04-04 13:29:17 +0200136 free(channels);
137 free(channels_len);
138
Paul Cercueil42090d12014-02-24 12:32:23 +0100139 for (i = 0; i < dev->nb_attrs; i++) {
140 strcpy(ptr, attrs[i]);
141 ptr += attrs_len[i];
142 free(attrs[i]);
143 }
144
Paul Cercueil5822ab62014-04-04 13:29:17 +0200145 free(attrs);
146 free(attrs_len);
147
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200148 for (i = 0; i < dev->nb_debug_attrs; i++) {
149 strcpy(ptr, debug_attrs[i]);
150 ptr += debug_attrs_len[i];
151 free(debug_attrs[i]);
152 }
153
154 free(debug_attrs);
155 free(debug_attrs_len);
156
Paul Cercueil42090d12014-02-24 12:32:23 +0100157 strcpy(ptr, "</device>");
158 *length = ptr - str + sizeof("</device>") - 1;
159 return str;
160
Paul Cercueild9d9f9f2014-04-15 10:08:17 +0200161err_free_debug_attrs:
162 while (k--)
163 free(debug_attrs[k]);
164 free(debug_attrs);
165err_free_debug_attrs_len:
166 free(debug_attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100167err_free_channels:
168 while (j--)
169 free(channels[j]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200170 free(channels);
171err_free_channels_len:
172 free(channels_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100173err_free_attrs:
174 while (i--)
175 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200176 free(attrs);
177err_free_attrs_len:
178 free(attrs_len);
Paul Cercueil42090d12014-02-24 12:32:23 +0100179 return NULL;
180}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100181
182const char * iio_device_get_id(const struct iio_device *dev)
183{
184 return dev->id;
185}
186
187const char * iio_device_get_name(const struct iio_device *dev)
188{
189 return dev->name;
190}
191
192unsigned int iio_device_get_channels_count(const struct iio_device *dev)
193{
194 return dev->nb_channels;
195}
196
197struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
198 unsigned int index)
199{
200 if (index >= dev->nb_channels)
201 return NULL;
202 else
203 return dev->channels[index];
204}
205
Paul Cercueil17512b02014-03-28 11:15:24 +0100206struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100207 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100208{
209 unsigned int i;
210 for (i = 0; i < dev->nb_channels; i++) {
211 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100212 if (iio_channel_is_output(chn) != output)
213 continue;
214
Paul Cercueil17512b02014-03-28 11:15:24 +0100215 if (!strcmp(chn->id, name) ||
216 (chn->name && !strcmp(chn->name, name)))
217 return chn;
218 }
219 return NULL;
220}
221
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100222unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
223{
224 return dev->nb_attrs;
225}
226
227const char * iio_device_get_attr(const struct iio_device *dev,
228 unsigned int index)
229{
230 if (index >= dev->nb_attrs)
231 return NULL;
232 else
233 return dev->attrs[index];
234}
235
Paul Cercueil4f838d02014-03-28 11:26:15 +0100236const char * iio_device_find_attr(const struct iio_device *dev,
237 const char *name)
238{
239 unsigned int i;
240 for (i = 0; i < dev->nb_attrs; i++) {
241 const char *attr = dev->attrs[i];
242 if (!strcmp(attr, name))
243 return attr;
244 }
245 return NULL;
246}
247
Paul Cercueil001d2152014-06-03 15:24:44 +0200248const char * iio_device_find_debug_attr(const struct iio_device *dev,
249 const char *name)
250{
251 unsigned int i;
252 for (i = 0; i < dev->nb_debug_attrs; i++) {
253 const char *attr = dev->debug_attrs[i];
254 if (!strcmp(attr, name))
255 return attr;
256 }
257 return NULL;
258}
259
Paul Cercueil3cc3a002014-03-24 13:44:11 +0100260static int iio_device_open_mask(const struct iio_device *dev,
Paul Cercueil71694c72014-05-22 14:02:13 +0200261 size_t samples_count, uint32_t *mask, size_t words, bool cyclic)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100262{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100263 unsigned int i;
264 bool has_channels = false;
265
266 for (i = 0; !has_channels && i < words; i++)
267 has_channels = !!mask[i];
268 if (!has_channels)
269 return -EINVAL;
270
Paul Cercueilec1760d2014-02-21 11:31:20 +0100271 if (dev->ctx->ops->open)
Paul Cercueil71694c72014-05-22 14:02:13 +0200272 return dev->ctx->ops->open(dev,
273 samples_count, mask, words, cyclic);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100274 else
275 return -ENOSYS;
276}
277
Paul Cercueil71694c72014-05-22 14:02:13 +0200278int iio_device_open(const struct iio_device *dev,
279 size_t samples_count, bool cyclic)
Paul Cercueile1311222014-03-12 15:46:16 +0100280{
281 size_t nb = (dev->nb_channels + 31) / 32;
282 uint32_t *mask = NULL;
283 unsigned int i;
284 int ret;
285
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100286 if (nb == 0)
287 return -EINVAL;
288
289 mask = calloc(nb, sizeof(*mask));
290 if (!mask)
291 return -ENOMEM;
Paul Cercueile1311222014-03-12 15:46:16 +0100292
293 for (i = 0; i < dev->nb_channels; i++) {
294 struct iio_channel *chn = dev->channels[i];
295 if (iio_channel_is_enabled(chn) && chn->index >= 0)
296 SET_BIT(mask, chn->index);
297 }
298
Paul Cercueil71694c72014-05-22 14:02:13 +0200299 ret = iio_device_open_mask(dev, samples_count, mask, nb, cyclic);
Paul Cercueile1311222014-03-12 15:46:16 +0100300 free(mask);
301 return ret;
302}
303
Paul Cercueilec1760d2014-02-21 11:31:20 +0100304int iio_device_close(const struct iio_device *dev)
305{
306 if (dev->ctx->ops->close)
307 return dev->ctx->ops->close(dev);
308 else
309 return -ENOSYS;
310}
311
312ssize_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 Cercueil1a474732014-03-17 11:38:34 +0100425 uint32_t *mask, size_t words)
426{
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{
486 char *end, buf[1024];
487 double value;
488 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
489 if (ret < 0)
490 return (int) ret;
491
492 value = strtod(buf, &end);
493 if (end == buf)
494 return -EINVAL;
495 *val = value;
496 return 0;
497}
498
499int iio_device_attr_write_longlong(const struct iio_device *dev,
500 const char *attr, long long val)
501{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200502 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200503 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200504
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200505 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200506 ret = iio_device_attr_write(dev, attr, buf);
507
508 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200509}
510
511int iio_device_attr_write_double(const struct iio_device *dev,
512 const char *attr, double val)
513{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200514 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200515 char buf[1024];
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200516
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200517 snprintf(buf, sizeof(buf), "%lf", val);
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200518 ret = iio_device_attr_write(dev, attr, buf);
519
520 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200521}
522
523int iio_device_attr_write_bool(const struct iio_device *dev,
524 const char *attr, bool val)
525{
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200526 ssize_t ret;
527
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200528 if (val)
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200529 ret = iio_device_attr_write(dev, attr, "1");
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200530 else
Andrea Galbusera49ef4182014-07-28 08:50:46 +0200531 ret = iio_device_attr_write(dev, attr, "0");
532
533 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200534}
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200535
536ssize_t iio_device_debug_attr_read(const struct iio_device *dev,
537 const char *attr, char *dst, size_t len)
538{
539 if (dev->ctx->ops->read_device_attr)
540 return dev->ctx->ops->read_device_attr(dev,
541 attr, dst, len, true);
542 else
543 return -ENOSYS;
544}
545
Paul Cercueilcecda352014-05-06 18:14:29 +0200546ssize_t iio_device_debug_attr_write_raw(const struct iio_device *dev,
547 const char *attr, const void *src, size_t len)
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200548{
549 if (dev->ctx->ops->write_device_attr)
550 return dev->ctx->ops->write_device_attr(dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200551 attr, src, len, true);
Paul Cercueil99b07cc2014-04-14 16:07:32 +0200552 else
553 return -ENOSYS;
554}
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200555
Paul Cercueilcecda352014-05-06 18:14:29 +0200556ssize_t iio_device_debug_attr_write(const struct iio_device *dev,
557 const char *attr, const char *src)
558{
559 return iio_device_debug_attr_write_raw(dev, attr, src, strlen(src) + 1);
560}
561
Paul Cercueil1ce35ef2014-04-15 12:28:40 +0200562unsigned int iio_device_get_debug_attrs_count(const struct iio_device *dev)
563{
564 return dev->nb_debug_attrs;
565}
566
567const char * iio_device_get_debug_attr(const struct iio_device *dev,
568 unsigned int index)
569{
570 if (index >= dev->nb_debug_attrs)
571 return NULL;
572 else
573 return dev->debug_attrs[index];
574}
Paul Cercueile3960742014-04-15 16:00:50 +0200575
576int iio_device_debug_attr_read_longlong(const struct iio_device *dev,
577 const char *attr, long long *val)
578{
579 char *end, buf[1024];
580 long long value;
581 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
582 if (ret < 0)
583 return (int) ret;
584
585 value = strtoll(buf, &end, 0);
586 if (end == buf)
587 return -EINVAL;
588 *val = value;
589 return 0;
590}
591
592int iio_device_debug_attr_read_bool(const struct iio_device *dev,
593 const char *attr, bool *val)
594{
595 long long value;
596 int ret = iio_device_debug_attr_read_longlong(dev, attr, &value);
597 if (ret < 0)
598 return ret;
599
600 *val = !!value;
601 return 0;
602}
603
604int iio_device_debug_attr_read_double(const struct iio_device *dev,
605 const char *attr, double *val)
606{
607 char *end, buf[1024];
608 double value;
609 ssize_t ret = iio_device_debug_attr_read(dev, attr, buf, sizeof(buf));
610 if (ret < 0)
611 return (int) ret;
612
613 value = strtod(buf, &end);
614 if (end == buf)
615 return -EINVAL;
616 *val = value;
617 return 0;
618}
619
620int iio_device_debug_attr_write_longlong(const struct iio_device *dev,
621 const char *attr, long long val)
622{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200623 ssize_t ret;
624
Paul Cercueile3960742014-04-15 16:00:50 +0200625 char buf[1024];
626 snprintf(buf, sizeof(buf), "%lld", val);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200627 ret = iio_device_debug_attr_write(dev, attr, buf);
628
629 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200630}
631
632int iio_device_debug_attr_write_double(const struct iio_device *dev,
633 const char *attr, double val)
634{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200635 ssize_t ret;
636
Paul Cercueile3960742014-04-15 16:00:50 +0200637 char buf[1024];
638 snprintf(buf, sizeof(buf), "%lf", val);
Andrea Galbuserac547d222014-07-28 08:50:46 +0200639 ret = iio_device_debug_attr_write(dev, attr, buf);
640
641 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200642}
643
644int iio_device_debug_attr_write_bool(const struct iio_device *dev,
645 const char *attr, bool val)
646{
Andrea Galbuserac547d222014-07-28 08:50:46 +0200647 ssize_t ret;
648
Paul Cercueile3960742014-04-15 16:00:50 +0200649 if (val)
Andrea Galbuserac547d222014-07-28 08:50:46 +0200650 ret = iio_device_debug_attr_write_raw(dev, attr, "1", 2);
Paul Cercueile3960742014-04-15 16:00:50 +0200651 else
Andrea Galbuserac547d222014-07-28 08:50:46 +0200652 ret = iio_device_debug_attr_write_raw(dev, attr, "0", 2);
653
654 return ret < 0 ? ret : 0;
Paul Cercueile3960742014-04-15 16:00:50 +0200655}
Paul Cercueil108e0aa2014-05-06 14:45:14 +0200656
657int iio_device_identify_filename(const struct iio_device *dev,
658 const char *filename, struct iio_channel **chn,
659 const char **attr)
660{
661 unsigned int i;
662
663 for (i = 0; i < dev->nb_channels; i++) {
664 struct iio_channel *ch = dev->channels[i];
665 unsigned int j;
666
667 for (j = 0; j < ch->nb_attrs; j++) {
668 if (!strcmp(ch->attrs[j].filename, filename)) {
669 *attr = ch->attrs[j].name;
670 *chn = ch;
671 return 0;
672 }
673 }
674 }
675
676 for (i = 0; i < dev->nb_attrs; i++) {
677 /* Devices attributes are named after their filename */
678 if (!strcmp(dev->attrs[i], filename)) {
679 *attr = dev->attrs[i];
680 *chn = NULL;
681 return 0;
682 }
683 }
684
685 for (i = 0; i < dev->nb_debug_attrs; i++) {
686 if (!strcmp(dev->debug_attrs[i], filename)) {
687 *attr = dev->debug_attrs[i];
688 *chn = NULL;
689 return 0;
690 }
691 }
692
693 return -EINVAL;
694}
Paul Cercueil14405872014-05-07 14:00:32 +0200695
696int iio_device_reg_write(struct iio_device *dev,
697 uint32_t address, uint32_t value)
698{
699 char buf[1024];
700 snprintf(buf, sizeof(buf), "0x%x 0x%x", address, value);
701 return iio_device_debug_attr_write(dev, "direct_reg_access", buf);
702}
703
704int iio_device_reg_read(struct iio_device *dev,
705 uint32_t address, uint32_t *value)
706{
707 /* NOTE: There is a race condition here. But it is extremely unlikely to
708 * happen, and as this is a debug function, it shouldn't be used for
709 * something else than debug. */
710
711 long long val;
712 int ret = iio_device_debug_attr_write_longlong(dev,
713 "direct_reg_access", (long long) address);
714 if (ret < 0)
715 return ret;
716
717 ret = iio_device_debug_attr_read_longlong(dev,
718 "direct_reg_access", &val);
719 if (!ret)
720 *value = (uint32_t) val;
721 return ret;
722}
Paul Cercueil1b36a012014-06-05 14:39:31 +0200723
724static int read_each_attr(struct iio_device *dev, bool is_debug,
725 int (*cb)(struct iio_device *dev,
726 const char *attr, const char *val, size_t len, void *d),
727 void *data)
728{
729 int ret;
730 char *buf, *ptr;
731 unsigned int i, count;
732
733 /* We need a big buffer here; 1 MiB should be enough */
734 buf = malloc(0x100000);
735 if (!buf)
736 return -ENOMEM;
737
738 if (is_debug) {
739 count = iio_device_get_debug_attrs_count(dev);
740 ret = (int) iio_device_debug_attr_read(dev,
741 NULL, buf, 0x100000);
742 } else {
743 count = iio_device_get_attrs_count(dev);
744 ret = (int) iio_device_attr_read(dev, NULL, buf, 0x100000);
745 }
746
747 if (ret < 0)
748 goto err_free_buf;
749
750 ptr = buf;
751
752 for (i = 0; i < count; i++) {
753 const char *attr;
754 int32_t len = (int32_t) ntohl(*(uint32_t *) ptr);
755
756 if (is_debug)
757 attr = iio_device_get_debug_attr(dev, i);
758 else
759 attr = iio_device_get_attr(dev, i);
760
761 ptr += 4;
762 if (len > 0) {
763 ret = cb(dev, attr, ptr, (size_t) len, data);
764 if (ret < 0)
765 goto err_free_buf;
766
767 if (len & 0x3)
768 len = ((len >> 2) + 1) << 2;
769 ptr += len;
770 }
771 }
772
773err_free_buf:
774 free(buf);
775 return ret < 0 ? ret : 0;
776}
777
778static int write_each_attr(struct iio_device *dev, bool is_debug,
779 ssize_t (*cb)(struct iio_device *dev,
780 const char *attr, void *buf, size_t len, void *d),
781 void *data)
782{
783 char *buf, *ptr;
784 unsigned int i, count;
785 size_t len = 0x100000;
786 int ret;
787
788 /* We need a big buffer here; 1 MiB should be enough */
789 buf = malloc(len);
790 if (!buf)
791 return -ENOMEM;
792
793 ptr = buf;
794
795 if (is_debug)
796 count = iio_device_get_debug_attrs_count(dev);
797 else
798 count = iio_device_get_attrs_count(dev);
799
800 for (i = 0; i < count; i++) {
801 const char *attr;
802
803 if (is_debug)
804 attr = iio_device_get_debug_attr(dev, i);
805 else
806 attr = iio_device_get_attr(dev, i);
807
808 ret = (int) cb(dev, attr, ptr + 4, len - 4, data);
809 if (ret < 0)
810 goto err_free_buf;
811
812 *(int32_t *) ptr = (int32_t) htonl((uint32_t) ret);
813 ptr += 4;
814 len -= 4;
815
816 if (ret > 0) {
817 if (ret & 0x3)
818 ret = ((ret >> 2) + 1) << 2;
819 ptr += ret;
820 len -= ret;
821 }
822 }
823
824 if (is_debug)
825 ret = (int) iio_device_debug_attr_write_raw(dev,
826 NULL, buf, ptr - buf);
827 else
828 ret = (int) iio_device_attr_write_raw(dev,
829 NULL, buf, ptr - buf);
830
831err_free_buf:
832 free(buf);
833 return ret < 0 ? ret : 0;
834}
835
836int iio_device_debug_attr_read_all(struct iio_device *dev,
837 int (*cb)(struct iio_device *dev,
838 const char *attr, const char *val, size_t len, void *d),
839 void *data)
840{
841 return read_each_attr(dev, true, cb, data);
842}
843
844int iio_device_attr_read_all(struct iio_device *dev,
845 int (*cb)(struct iio_device *dev,
846 const char *attr, const char *val, size_t len, void *d),
847 void *data)
848{
849 return read_each_attr(dev, false, cb, data);
850}
851
852int iio_device_debug_attr_write_all(struct iio_device *dev,
853 ssize_t (*cb)(struct iio_device *dev,
854 const char *attr, void *buf, size_t len, void *d),
855 void *data)
856{
857 return write_each_attr(dev, true, cb, data);
858}
859
860int iio_device_attr_write_all(struct iio_device *dev,
861 ssize_t (*cb)(struct iio_device *dev,
862 const char *attr, void *buf, size_t len, void *d),
863 void *data)
864{
865 return write_each_attr(dev, false, cb, data);
866}