blob: f8b39c0eb741c8043a068417a81ddd0532d87437 [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,
134 const char *name)
135{
136 unsigned int i;
137 for (i = 0; i < dev->nb_channels; i++) {
138 struct iio_channel *chn = dev->channels[i];
139 if (!strcmp(chn->id, name) ||
140 (chn->name && !strcmp(chn->name, name)))
141 return chn;
142 }
143 return NULL;
144}
145
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100146unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
147{
148 return dev->nb_attrs;
149}
150
151const char * iio_device_get_attr(const struct iio_device *dev,
152 unsigned int index)
153{
154 if (index >= dev->nb_attrs)
155 return NULL;
156 else
157 return dev->attrs[index];
158}
159
Paul Cercueil3cc3a002014-03-24 13:44:11 +0100160static int iio_device_open_mask(const struct iio_device *dev,
Paul Cercueile1311222014-03-12 15:46:16 +0100161 uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100162{
163 if (dev->ctx->ops->open)
Paul Cercueile1311222014-03-12 15:46:16 +0100164 return dev->ctx->ops->open(dev, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100165 else
166 return -ENOSYS;
167}
168
Paul Cercueile1311222014-03-12 15:46:16 +0100169int iio_device_open(const struct iio_device *dev)
170{
171 size_t nb = (dev->nb_channels + 31) / 32;
172 uint32_t *mask = NULL;
173 unsigned int i;
174 int ret;
175
176 if (nb > 0) {
177 mask = calloc(nb, sizeof(*mask));
178 if (!mask)
179 return -ENOMEM;
180 }
181
182 for (i = 0; i < dev->nb_channels; i++) {
183 struct iio_channel *chn = dev->channels[i];
184 if (iio_channel_is_enabled(chn) && chn->index >= 0)
185 SET_BIT(mask, chn->index);
186 }
187
188 ret = iio_device_open_mask(dev, mask, nb);
189 free(mask);
190 return ret;
191}
192
Paul Cercueilec1760d2014-02-21 11:31:20 +0100193int iio_device_close(const struct iio_device *dev)
194{
195 if (dev->ctx->ops->close)
196 return dev->ctx->ops->close(dev);
197 else
198 return -ENOSYS;
199}
200
201ssize_t iio_device_read_raw(const struct iio_device *dev,
Paul Cercueil45c575d2014-03-20 15:14:01 +0100202 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100203{
204 if (dev->ctx->ops->read)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100205 return dev->ctx->ops->read(dev, dst, len, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100206 else
207 return -ENOSYS;
208}
209
210ssize_t iio_device_write_raw(const struct iio_device *dev,
211 const void *src, size_t len)
212{
213 if (dev->ctx->ops->write)
214 return dev->ctx->ops->write(dev, src, len);
215 else
216 return -ENOSYS;
217}
218
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100219ssize_t iio_device_attr_read(const struct iio_device *dev,
220 const char *attr, char *dst, size_t len)
221{
Paul Cercueil6a013602014-02-19 12:37:39 +0100222 if (dev->ctx->ops->read_device_attr)
223 return dev->ctx->ops->read_device_attr(dev, attr, dst, len);
224 else
225 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100226}
227
228ssize_t iio_device_attr_write(const struct iio_device *dev,
229 const char *attr, const char *src)
230{
Paul Cercueil6a013602014-02-19 12:37:39 +0100231 if (dev->ctx->ops->write_device_attr)
232 return dev->ctx->ops->write_device_attr(dev, attr, src);
233 else
234 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100235}
Paul Cercueil00236242014-02-18 15:09:06 +0100236
Paul Cercueild96e61f2014-03-07 16:13:37 +0100237void iio_device_set_data(struct iio_device *dev, void *data)
238{
239 dev->userdata = data;
240}
241
242void * iio_device_get_data(const struct iio_device *dev)
243{
244 return dev->userdata;
245}
246
Paul Cercueil3156f632014-03-10 11:22:55 +0100247bool iio_device_is_trigger(const struct iio_device *dev)
248{
249 /* A trigger has a name, an id which starts by "trigger",
250 * and zero channels. */
251
252 unsigned int nb = iio_device_get_channels_count(dev);
253 const char *name = iio_device_get_name(dev),
254 *id = iio_device_get_id(dev);
255 return ((nb == 0) && !!name &&
256 !strncmp(id, "trigger", sizeof("trigger") - 1));
257}
258
Paul Cercueil24ffa532014-03-10 12:39:58 +0100259int iio_device_get_trigger(const struct iio_device *dev,
260 const struct iio_device **trigger)
261{
262 if (!trigger)
263 return -EINVAL;
264 else if (dev->ctx->ops->get_trigger)
265 return dev->ctx->ops->get_trigger(dev, trigger);
266 else
267 return -ENOSYS;
268}
269
270int iio_device_set_trigger(const struct iio_device *dev,
271 const struct iio_device *trigger)
272{
273 if (trigger && !iio_device_is_trigger(trigger))
274 return -EINVAL;
275 else if (dev->ctx->ops->set_trigger)
276 return dev->ctx->ops->set_trigger(dev, trigger);
277 else
278 return -ENOSYS;
279}
280
Paul Cercueil3156f632014-03-10 11:22:55 +0100281int iio_trigger_get_rate(const struct iio_device *trigger, unsigned long *rate)
282{
283 char buf[1024], *end;
284 ssize_t ret;
285 unsigned long value;
286
287 if (!iio_device_is_trigger(trigger))
288 return -EINVAL;
289
290 ret = iio_device_attr_read(trigger, "frequency", buf, sizeof(buf));
291 if (ret < 0)
292 return (int) ret;
293
294 value = strtoul(buf, &end, 10);
295 if (buf == end)
296 return -EBADF;
297
298 *rate = value;
299 return 0;
300}
301
302int iio_trigger_set_rate(const struct iio_device *trigger, unsigned long rate)
303{
304 char buf[1024];
305 ssize_t ret;
306
307 if (!iio_device_is_trigger(trigger))
308 return -EINVAL;
309
310 sprintf(buf, "%lu", rate);
311 ret = iio_device_attr_write(trigger, "frequency", buf);
312 if (ret < 0)
313 return (int) ret;
314 else
315 return 0;
316}
317
Paul Cercueil00236242014-02-18 15:09:06 +0100318void free_device(struct iio_device *dev)
319{
320 unsigned int i;
321 for (i = 0; i < dev->nb_attrs; i++)
322 free((char *) dev->attrs[i]);
323 if (dev->nb_attrs)
324 free(dev->attrs);
325 for (i = 0; i < dev->nb_channels; i++)
326 free_channel(dev->channels[i]);
327 if (dev->nb_channels)
328 free(dev->channels);
Paul Cercueilff778232014-03-24 14:23:08 +0100329 if (dev->mask)
330 free(dev->mask);
Paul Cercueil00236242014-02-18 15:09:06 +0100331 if (dev->name)
332 free((char *) dev->name);
333 if (dev->id)
334 free((char *) dev->id);
335 free(dev);
336}
Paul Cercueil1a474732014-03-17 11:38:34 +0100337
Paul Cercueil645ab972014-03-24 14:36:12 +0100338ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev,
Paul Cercueil1a474732014-03-17 11:38:34 +0100339 uint32_t *mask, size_t words)
340{
341 ssize_t size = 0;
342 unsigned int i;
343
344 if (words != (dev->nb_channels + 31) / 32)
345 return -EINVAL;
346
347 for (i = 0; i < dev->nb_channels; i++) {
348 const struct iio_channel *chn = dev->channels[i];
349 unsigned int length = chn->format.length / 8;
350
351 if (chn->index < 0)
352 break;
353 if (!TEST_BIT(mask, chn->index))
354 continue;
355
356 if (size % length)
357 size += 2 * length - (size % length);
358 else
359 size += length;
360 }
361 return size;
362}
Paul Cercueil46825942014-03-18 14:28:49 +0100363
Paul Cercueil645ab972014-03-24 14:36:12 +0100364ssize_t iio_device_get_sample_size(const struct iio_device *dev)
365{
366 return iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
367}
368
Paul Cercueil46825942014-03-18 14:28:49 +0100369ssize_t iio_device_process_samples(const struct iio_device *dev,
370 uint32_t *mask, size_t words, void *buf, size_t len,
371 ssize_t (*cb)(const struct iio_channel *, void *, void *),
372 void *data)
373{
374 const void *end = buf + len;
375 unsigned int i;
376 ssize_t processed = 0,
Paul Cercueil645ab972014-03-24 14:36:12 +0100377 sample_size = iio_device_get_sample_size_mask(dev, mask, words);
Paul Cercueil46825942014-03-18 14:28:49 +0100378 if (sample_size <= 0)
379 return -EINVAL;
380
381 while (end - buf >= sample_size) {
382 for (i = 0; i < dev->nb_channels; i++) {
383 const struct iio_channel *chn = dev->channels[i];
384 unsigned int length = chn->format.length / 8;
385 ssize_t ret;
386
387 if (chn->index < 0) {
388 ERROR("Channel %s has negative index\n",
389 chn->id);
390 break;
391 }
392
393 if (!TEST_BIT(mask, chn->index))
394 continue;
395
396 if ((uintptr_t) buf % length)
397 buf += length - ((uintptr_t) buf % length);
398
399 ret = cb(chn, buf, data);
400 if (ret < 0)
401 return ret;
402 else
403 processed += ret;
404 buf += length;
405 }
406 }
407 return processed;
408}