blob: ab1ef91507eb2f40313934b291648b455c73e654 [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
133unsigned int iio_device_get_attrs_count(const struct iio_device *dev)
134{
135 return dev->nb_attrs;
136}
137
138const char * iio_device_get_attr(const struct iio_device *dev,
139 unsigned int index)
140{
141 if (index >= dev->nb_attrs)
142 return NULL;
143 else
144 return dev->attrs[index];
145}
146
Paul Cercueile1311222014-03-12 15:46:16 +0100147int iio_device_open_mask(const struct iio_device *dev,
148 uint32_t *mask, size_t words)
Paul Cercueilec1760d2014-02-21 11:31:20 +0100149{
150 if (dev->ctx->ops->open)
Paul Cercueile1311222014-03-12 15:46:16 +0100151 return dev->ctx->ops->open(dev, mask, words);
Paul Cercueilec1760d2014-02-21 11:31:20 +0100152 else
153 return -ENOSYS;
154}
155
Paul Cercueile1311222014-03-12 15:46:16 +0100156int iio_device_open(const struct iio_device *dev)
157{
158 size_t nb = (dev->nb_channels + 31) / 32;
159 uint32_t *mask = NULL;
160 unsigned int i;
161 int ret;
162
163 if (nb > 0) {
164 mask = calloc(nb, sizeof(*mask));
165 if (!mask)
166 return -ENOMEM;
167 }
168
169 for (i = 0; i < dev->nb_channels; i++) {
170 struct iio_channel *chn = dev->channels[i];
171 if (iio_channel_is_enabled(chn) && chn->index >= 0)
172 SET_BIT(mask, chn->index);
173 }
174
175 ret = iio_device_open_mask(dev, mask, nb);
176 free(mask);
177 return ret;
178}
179
Paul Cercueilec1760d2014-02-21 11:31:20 +0100180int iio_device_close(const struct iio_device *dev)
181{
182 if (dev->ctx->ops->close)
183 return dev->ctx->ops->close(dev);
184 else
185 return -ENOSYS;
186}
187
188ssize_t iio_device_read_raw(const struct iio_device *dev,
189 void *dst, size_t len)
190{
191 if (dev->ctx->ops->read)
192 return dev->ctx->ops->read(dev, dst, len);
193 else
194 return -ENOSYS;
195}
196
197ssize_t iio_device_write_raw(const struct iio_device *dev,
198 const void *src, size_t len)
199{
200 if (dev->ctx->ops->write)
201 return dev->ctx->ops->write(dev, src, len);
202 else
203 return -ENOSYS;
204}
205
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100206ssize_t iio_device_attr_read(const struct iio_device *dev,
207 const char *attr, char *dst, size_t len)
208{
Paul Cercueil6a013602014-02-19 12:37:39 +0100209 if (dev->ctx->ops->read_device_attr)
210 return dev->ctx->ops->read_device_attr(dev, attr, dst, len);
211 else
212 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100213}
214
215ssize_t iio_device_attr_write(const struct iio_device *dev,
216 const char *attr, const char *src)
217{
Paul Cercueil6a013602014-02-19 12:37:39 +0100218 if (dev->ctx->ops->write_device_attr)
219 return dev->ctx->ops->write_device_attr(dev, attr, src);
220 else
221 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100222}
Paul Cercueil00236242014-02-18 15:09:06 +0100223
Paul Cercueild96e61f2014-03-07 16:13:37 +0100224void iio_device_set_data(struct iio_device *dev, void *data)
225{
226 dev->userdata = data;
227}
228
229void * iio_device_get_data(const struct iio_device *dev)
230{
231 return dev->userdata;
232}
233
Paul Cercueil3156f632014-03-10 11:22:55 +0100234bool iio_device_is_trigger(const struct iio_device *dev)
235{
236 /* A trigger has a name, an id which starts by "trigger",
237 * and zero channels. */
238
239 unsigned int nb = iio_device_get_channels_count(dev);
240 const char *name = iio_device_get_name(dev),
241 *id = iio_device_get_id(dev);
242 return ((nb == 0) && !!name &&
243 !strncmp(id, "trigger", sizeof("trigger") - 1));
244}
245
Paul Cercueil24ffa532014-03-10 12:39:58 +0100246int iio_device_get_trigger(const struct iio_device *dev,
247 const struct iio_device **trigger)
248{
249 if (!trigger)
250 return -EINVAL;
251 else if (dev->ctx->ops->get_trigger)
252 return dev->ctx->ops->get_trigger(dev, trigger);
253 else
254 return -ENOSYS;
255}
256
257int iio_device_set_trigger(const struct iio_device *dev,
258 const struct iio_device *trigger)
259{
260 if (trigger && !iio_device_is_trigger(trigger))
261 return -EINVAL;
262 else if (dev->ctx->ops->set_trigger)
263 return dev->ctx->ops->set_trigger(dev, trigger);
264 else
265 return -ENOSYS;
266}
267
Paul Cercueil3156f632014-03-10 11:22:55 +0100268int iio_trigger_get_rate(const struct iio_device *trigger, unsigned long *rate)
269{
270 char buf[1024], *end;
271 ssize_t ret;
272 unsigned long value;
273
274 if (!iio_device_is_trigger(trigger))
275 return -EINVAL;
276
277 ret = iio_device_attr_read(trigger, "frequency", buf, sizeof(buf));
278 if (ret < 0)
279 return (int) ret;
280
281 value = strtoul(buf, &end, 10);
282 if (buf == end)
283 return -EBADF;
284
285 *rate = value;
286 return 0;
287}
288
289int iio_trigger_set_rate(const struct iio_device *trigger, unsigned long rate)
290{
291 char buf[1024];
292 ssize_t ret;
293
294 if (!iio_device_is_trigger(trigger))
295 return -EINVAL;
296
297 sprintf(buf, "%lu", rate);
298 ret = iio_device_attr_write(trigger, "frequency", buf);
299 if (ret < 0)
300 return (int) ret;
301 else
302 return 0;
303}
304
Paul Cercueil00236242014-02-18 15:09:06 +0100305void free_device(struct iio_device *dev)
306{
307 unsigned int i;
308 for (i = 0; i < dev->nb_attrs; i++)
309 free((char *) dev->attrs[i]);
310 if (dev->nb_attrs)
311 free(dev->attrs);
312 for (i = 0; i < dev->nb_channels; i++)
313 free_channel(dev->channels[i]);
314 if (dev->nb_channels)
315 free(dev->channels);
316 if (dev->name)
317 free((char *) dev->name);
318 if (dev->id)
319 free((char *) dev->id);
320 free(dev);
321}
Paul Cercueil1a474732014-03-17 11:38:34 +0100322
323ssize_t iio_device_get_sample_size(const struct iio_device *dev,
324 uint32_t *mask, size_t words)
325{
326 ssize_t size = 0;
327 unsigned int i;
328
329 if (words != (dev->nb_channels + 31) / 32)
330 return -EINVAL;
331
332 for (i = 0; i < dev->nb_channels; i++) {
333 const struct iio_channel *chn = dev->channels[i];
334 unsigned int length = chn->format.length / 8;
335
336 if (chn->index < 0)
337 break;
338 if (!TEST_BIT(mask, chn->index))
339 continue;
340
341 if (size % length)
342 size += 2 * length - (size % length);
343 else
344 size += length;
345 }
346 return size;
347}