blob: 9cd4ffd48bf101efbb49c4338499552230d06cdd [file] [log] [blame]
Paul Cercueilbb4401d2014-02-28 16:10:49 +01001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2014 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
Paul Cercueil42090d12014-02-24 12:32:23 +010019#include "debug.h"
Paul Cercueil0b2ce712014-02-17 15:04:18 +010020#include "iio-private.h"
21
Paul Cercueil6a013602014-02-19 12:37:39 +010022#include <errno.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010023#include <stdio.h>
Paul Cercueil42090d12014-02-24 12:32:23 +010024#include <string.h>
25
26static char *get_attr_xml(const char *attr, size_t *length)
27{
28 size_t len = sizeof("<attribute name=\"\" />") + strlen(attr);
29 char *str = malloc(len);
30 if (!str) {
31 ERROR("Unable to allocate memory\n");
32 return NULL;
33 }
34
35 *length = len - 1; /* Skip the \0 */
36 sprintf(str, "<attribute name=\"%s\" />", attr);
37 return str;
38}
39
40/* Returns a string containing the XML representation of this device */
41char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
42{
43 size_t len = sizeof("<device id=\"\" name=\"\" ></device>");
44 char *ptr, *str, *attrs[dev->nb_attrs], *channels[dev->nb_channels];
45 size_t attrs_len[dev->nb_attrs], channels_len[dev->nb_channels];
46 unsigned int i, j;
47
48 for (i = 0; i < dev->nb_attrs; i++) {
49 char *xml = get_attr_xml(dev->attrs[i], &attrs_len[i]);
50 if (!xml)
51 goto err_free_attrs;
52 attrs[i] = xml;
53 len += attrs_len[i];
54 }
55
56 for (j = 0; j < dev->nb_channels; j++) {
57 char *xml = iio_channel_get_xml(dev->channels[j],
58 &channels_len[j]);
59 if (!xml)
60 goto err_free_channels;
61 channels[j] = xml;
62 len += channels_len[j];
63 }
64
65 len += strlen(dev->id);
66 if (dev->name)
67 len += strlen(dev->name);
68
69 str = malloc(len);
70 if (!str)
71 goto err_free_channels;
72
73 sprintf(str, "<device id=\"%s\"", dev->id);
74 ptr = strrchr(str, '\0');
75
76 if (dev->name) {
77 sprintf(ptr, " name=\"%s\"", dev->name);
78 ptr = strrchr(ptr, '\0');
79 }
80
81 strcpy(ptr, " >");
82 ptr += 2;
83
84 for (i = 0; i < dev->nb_channels; i++) {
85 strcpy(ptr, channels[i]);
86 ptr += channels_len[i];
87 free(channels[i]);
88 }
89
90 for (i = 0; i < dev->nb_attrs; i++) {
91 strcpy(ptr, attrs[i]);
92 ptr += attrs_len[i];
93 free(attrs[i]);
94 }
95
96 strcpy(ptr, "</device>");
97 *length = ptr - str + sizeof("</device>") - 1;
98 return str;
99
100err_free_channels:
101 while (j--)
102 free(channels[j]);
103err_free_attrs:
104 while (i--)
105 free(attrs[i]);
106 return NULL;
107}
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100108
109const char * iio_device_get_id(const struct iio_device *dev)
110{
111 return dev->id;
112}
113
114const char * iio_device_get_name(const struct iio_device *dev)
115{
116 return dev->name;
117}
118
119unsigned int iio_device_get_channels_count(const struct iio_device *dev)
120{
121 return dev->nb_channels;
122}
123
124struct iio_channel * iio_device_get_channel(const struct iio_device *dev,
125 unsigned int index)
126{
127 if (index >= dev->nb_channels)
128 return NULL;
129 else
130 return dev->channels[index];
131}
132
Paul Cercueil17512b02014-03-28 11:15:24 +0100133struct iio_channel * iio_device_find_channel(const struct iio_device *dev,
Paul Cercueil830a7f32014-03-28 13:09:31 +0100134 const char *name, bool output)
Paul Cercueil17512b02014-03-28 11:15:24 +0100135{
136 unsigned int i;
137 for (i = 0; i < dev->nb_channels; i++) {
138 struct iio_channel *chn = dev->channels[i];
Paul Cercueil830a7f32014-03-28 13:09:31 +0100139 if (iio_channel_is_output(chn) != output)
140 continue;
141
Paul Cercueil17512b02014-03-28 11:15:24 +0100142 if (!strcmp(chn->id, name) ||
143 (chn->name && !strcmp(chn->name, name)))
144 return chn;
145 }
146 return NULL;
147}
148
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100149unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
150{
151 return dev->nb_attrs;
152}
153
154const char * iio_device_get_attr(const struct iio_device *dev,
155 unsigned int index)
156{
157 if (index >= dev->nb_attrs)
158 return NULL;
159 else
160 return dev->attrs[index];
161}
162
Paul Cercueil4f838d02014-03-28 11:26:15 +0100163const char * iio_device_find_attr(const struct iio_device *dev,
164 const char *name)
165{
166 unsigned int i;
167 for (i = 0; i < dev->nb_attrs; i++) {
168 const char *attr = dev->attrs[i];
169 if (!strcmp(attr, name))
170 return attr;
171 }
172 return NULL;
173}
174
Paul Cercueil3cc3a002014-03-24 13:44:11 +0100175static int iio_device_open_mask(const struct iio_device *dev,
Paul Cercueil93f17052014-04-02 13:56:27 +0200176 size_t samples_count, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100177{
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100178 unsigned int i;
179 bool has_channels = false;
180
181 for (i = 0; !has_channels && i < words; i++)
182 has_channels = !!mask[i];
183 if (!has_channels)
184 return -EINVAL;
185
Paul Cercueilec1760d2014-02-21 11:31:20 +0100186 if (dev->ctx->ops->open)
Paul Cercueil93f17052014-04-02 13:56:27 +0200187 return dev->ctx->ops->open(dev, samples_count, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100188 else
189 return -ENOSYS;
190}
191
Paul Cercueil93f17052014-04-02 13:56:27 +0200192int iio_device_open(const struct iio_device *dev, size_t samples_count)
Paul Cercueile1311222014-03-12 15:46:16 +0100193{
194 size_t nb = (dev->nb_channels + 31) / 32;
195 uint32_t *mask = NULL;
196 unsigned int i;
197 int ret;
198
Paul Cercueilaaa8ee02014-03-28 16:43:02 +0100199 if (nb == 0)
200 return -EINVAL;
201
202 mask = calloc(nb, sizeof(*mask));
203 if (!mask)
204 return -ENOMEM;
Paul Cercueile1311222014-03-12 15:46:16 +0100205
206 for (i = 0; i < dev->nb_channels; i++) {
207 struct iio_channel *chn = dev->channels[i];
208 if (iio_channel_is_enabled(chn) && chn->index >= 0)
209 SET_BIT(mask, chn->index);
210 }
211
Paul Cercueil93f17052014-04-02 13:56:27 +0200212 ret = iio_device_open_mask(dev, samples_count, mask, nb);
Paul Cercueile1311222014-03-12 15:46:16 +0100213 free(mask);
214 return ret;
215}
216
Paul Cercueilec1760d2014-02-21 11:31:20 +0100217int iio_device_close(const struct iio_device *dev)
218{
219 if (dev->ctx->ops->close)
220 return dev->ctx->ops->close(dev);
221 else
222 return -ENOSYS;
223}
224
225ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100226 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100227{
228 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100229 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100230 else
231 return -ENOSYS;
232}
233
234ssize_t iio_device_write_raw(const struct iio_device *dev,
235 const void *src, size_t len)
236{
237 if (dev->ctx->ops->write)
238 return dev->ctx->ops->write(dev, src, len);
239 else
240 return -ENOSYS;
241}
242
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100243ssize_t iio_device_attr_read(const struct iio_device *dev,
244 const char *attr, char *dst, size_t len)
245{
Paul Cercueil6a013602014-02-19 12:37:39 +0100246 if (dev->ctx->ops->read_device_attr)
247 return dev->ctx->ops->read_device_attr(dev, attr, dst, len);
248 else
249 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100250}
251
252ssize_t iio_device_attr_write(const struct iio_device *dev,
253 const char *attr, const char *src)
254{
Paul Cercueil6a013602014-02-19 12:37:39 +0100255 if (dev->ctx->ops->write_device_attr)
256 return dev->ctx->ops->write_device_attr(dev, attr, src);
257 else
258 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100259}
Paul Cercueil00236242014-02-18 15:09:06 +0100260
Paul Cercueild96e61f2014-03-07 16:13:37 +0100261void iio_device_set_data(struct iio_device *dev, void *data)
262{
263 dev->userdata = data;
264}
265
266void * iio_device_get_data(const struct iio_device *dev)
267{
268 return dev->userdata;
269}
270
Paul Cercueil3156f632014-03-10 11:22:55 +0100271bool iio_device_is_trigger(const struct iio_device *dev)
272{
273 /* A trigger has a name, an id which starts by "trigger",
274 * and zero channels. */
275
276 unsigned int nb = iio_device_get_channels_count(dev);
277 const char *name = iio_device_get_name(dev),
278 *id = iio_device_get_id(dev);
279 return ((nb == 0) && !!name &&
280 !strncmp(id, "trigger", sizeof("trigger") - 1));
281}
282
Paul Cercueil24ffa532014-03-10 12:39:58 +0100283int iio_device_get_trigger(const struct iio_device *dev,
284 const struct iio_device **trigger)
285{
286 if (!trigger)
287 return -EINVAL;
288 else if (dev->ctx->ops->get_trigger)
289 return dev->ctx->ops->get_trigger(dev, trigger);
290 else
291 return -ENOSYS;
292}
293
294int iio_device_set_trigger(const struct iio_device *dev,
295 const struct iio_device *trigger)
296{
297 if (trigger && !iio_device_is_trigger(trigger))
298 return -EINVAL;
299 else if (dev->ctx->ops->set_trigger)
300 return dev->ctx->ops->set_trigger(dev, trigger);
301 else
302 return -ENOSYS;
303}
304
Paul Cercueil3156f632014-03-10 11:22:55 +0100305int iio_trigger_get_rate(const struct iio_device *trigger, unsigned long *rate)
306{
307 char buf[1024], *end;
308 ssize_t ret;
309 unsigned long value;
310
311 if (!iio_device_is_trigger(trigger))
312 return -EINVAL;
313
314 ret = iio_device_attr_read(trigger, "frequency", buf, sizeof(buf));
315 if (ret < 0)
316 return (int) ret;
317
318 value = strtoul(buf, &end, 10);
319 if (buf == end)
320 return -EBADF;
321
322 *rate = value;
323 return 0;
324}
325
326int iio_trigger_set_rate(const struct iio_device *trigger, unsigned long rate)
327{
328 char buf[1024];
329 ssize_t ret;
330
331 if (!iio_device_is_trigger(trigger))
332 return -EINVAL;
333
334 sprintf(buf, "%lu", rate);
335 ret = iio_device_attr_write(trigger, "frequency", buf);
336 if (ret < 0)
337 return (int) ret;
338 else
339 return 0;
340}
341
Paul Cercueil00236242014-02-18 15:09:06 +0100342void free_device(struct iio_device *dev)
343{
344 unsigned int i;
345 for (i = 0; i < dev->nb_attrs; i++)
346 free((char *) dev->attrs[i]);
347 if (dev->nb_attrs)
348 free(dev->attrs);
349 for (i = 0; i < dev->nb_channels; i++)
350 free_channel(dev->channels[i]);
351 if (dev->nb_channels)
352 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100353 if (dev->mask)
354 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100355 if (dev->name)
356 free((char *) dev->name);
357 if (dev->id)
358 free((char *) dev->id);
359 free(dev);
360}
Paul Cercueil1a474732014-03-17 11:38:34 +0100361
Paul Cercueil645ab972014-03-24 14:36:12 +0100362ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil1a474732014-03-17 11:38:34 +0100363 uint32_t *mask, size_t words)
364{
365 ssize_t size = 0;
366 unsigned int i;
367
368 if (words != (dev->nb_channels + 31) / 32)
369 return -EINVAL;
370
371 for (i = 0; i < dev->nb_channels; i++) {
372 const struct iio_channel *chn = dev->channels[i];
373 unsigned int length = chn->format.length / 8;
374
375 if (chn->index < 0)
376 break;
377 if (!TEST_BIT(mask, chn->index))
378 continue;
379
380 if (size % length)
381 size += 2 * length - (size % length);
382 else
383 size += length;
384 }
385 return size;
386}
Paul Cercueil46825942014-03-18 14:28:49 +0100387
Paul Cercueil645ab972014-03-24 14:36:12 +0100388ssize_t iio_device_get_sample_size(const struct iio_device *dev)
389{
390 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
391}
392
Paul Cercueil46825942014-03-18 14:28:49 +0100393ssize_t iio_device_process_samples(const struct iio_device *dev,
394 uint32_t *mask, size_t words, void *buf, size_t len,
395 ssize_t (*cb)(const struct iio_channel *, void *, void *),
396 void *data)
397{
398 const void *end = buf + len;
399 unsigned int i;
400 ssize_t processed = 0,
Paul Cercueil645ab972014-03-24 14:36:12 +0100401 sample_size = iio_device_get_sample_size_mask(dev, mask, words);
Paul Cercueil46825942014-03-18 14:28:49 +0100402 if (sample_size <= 0)
403 return -EINVAL;
404
405 while (end - buf >= sample_size) {
406 for (i = 0; i < dev->nb_channels; i++) {
407 const struct iio_channel *chn = dev->channels[i];
408 unsigned int length = chn->format.length / 8;
409 ssize_t ret;
410
411 if (chn->index < 0) {
412 ERROR("Channel %s has negative index\n",
413 chn->id);
414 break;
415 }
416
417 if (!TEST_BIT(mask, chn->index))
418 continue;
419
420 if ((uintptr_t) buf % length)
421 buf += length - ((uintptr_t) buf % length);
422
423 ret = cb(chn, buf, data);
424 if (ret < 0)
425 return ret;
426 else
427 processed += ret;
428 buf += length;
429 }
430 }
431 return processed;
432}
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200433
434int iio_device_attr_read_longlong(const struct iio_device *dev,
435 const char *attr, long long *val)
436{
437 char *end, buf[1024];
438 long long value;
439 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
440 if (ret < 0)
441 return (int) ret;
442
443 value = strtoll(buf, &end, 0);
444 if (end == buf)
445 return -EINVAL;
446 *val = value;
447 return 0;
448}
449
450int iio_device_attr_read_bool(const struct iio_device *dev,
451 const char *attr, bool *val)
452{
453 long long value;
454 int ret = iio_device_attr_read_longlong(dev, attr, &value);
455 if (ret < 0)
456 return ret;
457
458 *val = !!value;
459 return 0;
460}
461
462int iio_device_attr_read_double(const struct iio_device *dev,
463 const char *attr, double *val)
464{
465 char *end, buf[1024];
466 double value;
467 ssize_t ret = iio_device_attr_read(dev, attr, buf, sizeof(buf));
468 if (ret < 0)
469 return (int) ret;
470
471 value = strtod(buf, &end);
472 if (end == buf)
473 return -EINVAL;
474 *val = value;
475 return 0;
476}
477
478int iio_device_attr_write_longlong(const struct iio_device *dev,
479 const char *attr, long long val)
480{
481 char buf[1024];
482 snprintf(buf, sizeof(buf), "%lld", val);
483 return iio_device_attr_write(dev, attr, buf);
484}
485
486int iio_device_attr_write_double(const struct iio_device *dev,
487 const char *attr, double val)
488{
489 char buf[1024];
490 snprintf(buf, sizeof(buf), "%lf", val);
491 return iio_device_attr_write(dev, attr, buf);
492}
493
494int iio_device_attr_write_bool(const struct iio_device *dev,
495 const char *attr, bool val)
496{
497 if (val)
498 return iio_device_attr_write(dev, attr, "1");
499 else
500 return iio_device_attr_write(dev, attr, "0");
501}