blob: eb6699a482f5f9fe988b20df3eff578237c16d72 [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 "debug.h"
20#include "iio-private.h"
21
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +020022#include <arpa/inet.h>
Paul Cercueil1be57832014-03-11 16:27:16 +010023#include <dirent.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010024#include <errno.h>
Paul Cercueile1e0a8f2014-06-10 15:40:29 +020025#include <poll.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010026#include <stdbool.h>
Paul Cercueil1be57832014-03-11 16:27:16 +010027#include <stddef.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010028#include <stdio.h>
29#include <string.h>
Paul Cercueil92f46df2014-04-28 13:17:53 +020030#include <sys/ioctl.h>
31#include <sys/mman.h>
Paul Cercueil1be57832014-03-11 16:27:16 +010032#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
Lars-Peter Clausenac9e3282014-07-14 13:36:46 +020035#include <string.h>
Lars-Peter Clausen00f80092014-07-01 17:52:05 +020036#include <sys/utsname.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010037
Paul Cercueile1e0a8f2014-06-10 15:40:29 +020038#define DEFAULT_TIMEOUT_MS 1000
39
Paul Cercueil92f46df2014-04-28 13:17:53 +020040#define NB_BLOCKS 4
41
42#define BLOCK_ALLOC_IOCTL _IOWR('i', 0xa0, struct block_alloc_req)
43#define BLOCK_FREE_IOCTL _IO('i', 0xa1)
44#define BLOCK_QUERY_IOCTL _IOWR('i', 0xa2, struct block)
45#define BLOCK_ENQUEUE_IOCTL _IOWR('i', 0xa3, struct block)
46#define BLOCK_DEQUEUE_IOCTL _IOWR('i', 0xa4, struct block)
47
Paul Cercueil71694c72014-05-22 14:02:13 +020048#define BLOCK_FLAG_CYCLIC BIT(1)
49
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +020050/* Forward declarations */
51static ssize_t local_read_dev_attr(const struct iio_device *dev,
52 const char *attr, char *dst, size_t len, bool is_debug);
53static ssize_t local_read_chn_attr(const struct iio_channel *chn,
54 const char *attr, char *dst, size_t len);
Paul Cercueil1da28122014-05-22 10:59:49 +020055static ssize_t local_write_dev_attr(const struct iio_device *dev,
56 const char *attr, const char *src, size_t len, bool is_debug);
57static ssize_t local_write_chn_attr(const struct iio_channel *chn,
58 const char *attr, const char *src, size_t len);
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +020059
Paul Cercueil92f46df2014-04-28 13:17:53 +020060struct block_alloc_req {
61 uint32_t type,
62 size,
63 count,
64 id;
65};
66
67struct block {
68 uint32_t id,
69 size,
70 bytes_used,
71 type,
72 flags,
73 offset;
74 uint64_t timestamp;
75};
76
Paul Cercueileaab6582014-02-21 09:35:59 +010077struct iio_device_pdata {
Paul Cercueil44010ea2014-02-21 11:47:04 +010078 FILE *f;
Paul Cercueil71694c72014-05-22 14:02:13 +020079 unsigned int samples_count, nb_blocks;
Paul Cercueil92f46df2014-04-28 13:17:53 +020080
81 struct block blocks[NB_BLOCKS];
82 void *addrs[NB_BLOCKS];
83 int last_dequeued;
Paul Cercueil6ea8a752014-06-03 11:35:35 +020084 bool is_high_speed, cyclic, cyclic_buffer_enqueued, buffer_enabled;
Paul Cercueileaab6582014-02-21 09:35:59 +010085};
86
Paul Cercueil0b2ce712014-02-17 15:04:18 +010087static const char * const device_attrs_blacklist[] = {
88 "dev",
89 "uevent",
90};
91
92static const char * const modifier_names[] = {
93 [IIO_MOD_X] = "x",
94 [IIO_MOD_Y] = "y",
95 [IIO_MOD_Z] = "z",
96 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
97 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
98 [IIO_MOD_LIGHT_BOTH] = "both",
99 [IIO_MOD_LIGHT_IR] = "ir",
100 [IIO_MOD_LIGHT_CLEAR] = "clear",
101 [IIO_MOD_LIGHT_RED] = "red",
102 [IIO_MOD_LIGHT_GREEN] = "green",
103 [IIO_MOD_LIGHT_BLUE] = "blue",
Lars-Peter Clausen60aa4042015-03-27 13:34:55 +0100104 [IIO_MOD_I] = "i",
105 [IIO_MOD_Q] = "q",
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100106};
107
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100108/*
109 * Looks for a IIO channel modifier at the beginning of the string s. If a
110 * modifier was found the symbolic constant (IIO_MOD_*) is returned, otherwise
111 * IIO_NO_MOD is returned. If a modifier was found len_p will be update with the
112 * length of the modifier.
113 */
114static unsigned int find_modifier(const char *s, size_t *len_p)
115{
116 unsigned int i;
117 size_t len;
118
119 for (i = 0; i < ARRAY_SIZE(modifier_names); i++) {
120 if (!modifier_names[i])
121 continue;
122 len = strlen(modifier_names[i]);
Lars-Peter Clausenf18f3d52015-03-27 13:42:09 +0100123 if (strncmp(s, modifier_names[i], len) == 0 && s[len] == '_') {
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100124 if (len_p)
125 *len_p = len;
126 return i;
127 }
128 }
129
130 return IIO_NO_MOD;
131}
132
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100133static void local_shutdown(struct iio_context *ctx)
134{
Paul Cercueil42d12352014-05-05 16:11:58 +0200135 /* Free the backend data stored in every device structure */
Paul Cercueil167d3112014-02-18 12:23:53 +0100136 unsigned int i;
Paul Cercueil42d12352014-05-05 16:11:58 +0200137 for (i = 0; i < ctx->nb_devices; i++)
138 free(ctx->devices[i]->pdata);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100139}
140
Michael Hennerich1c8aa572014-11-06 17:42:30 +0100141/** Shrinks the first nb characters of a string
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100142 * e.g. strcut("foobar", 4) replaces the content with "ar". */
143static void strcut(char *str, int nb)
144{
145 char *ptr = str + nb;
146 while (*ptr)
147 *str++ = *ptr++;
148 *str = 0;
149}
150
151static int set_channel_name(struct iio_channel *chn)
152{
Lars-Peter Clausen816c4262015-03-27 15:57:43 +0100153 size_t prefix_len = 0;
154 const char *attr0;
155 const char *ptr;
156 unsigned int i;
157
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100158 if (chn->nb_attrs < 2)
159 return 0;
160
Lars-Peter Clausen816c4262015-03-27 15:57:43 +0100161 attr0 = ptr = chn->attrs[0].name;
162
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100163 while (true) {
164 bool can_fix = true;
Lars-Peter Clausen816c4262015-03-27 15:57:43 +0100165 size_t len;
166
167 ptr = strchr(ptr, '_');
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100168 if (!ptr)
169 break;
170
171 len = ptr - attr0;
172 for (i = 1; can_fix && i < chn->nb_attrs; i++)
Paul Cercueilb34e0222014-05-05 15:32:38 +0200173 can_fix = !strncmp(attr0, chn->attrs[i].name, len);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100174
175 if (!can_fix)
176 break;
177
Lars-Peter Clausen816c4262015-03-27 15:57:43 +0100178 prefix_len = len;
179 ptr = ptr + 1;
180 }
181
182 if (prefix_len) {
183 char *name;
184
185 name = malloc(prefix_len + 1);
186 if (!name)
187 return -ENOMEM;
188 strncpy(name, attr0, prefix_len);
189 name[prefix_len] = '\0';
190 DEBUG("Setting name of channel %s to %s\n", chn->id, name);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100191 chn->name = name;
192
193 /* Shrink the attribute name */
194 for (i = 0; i < chn->nb_attrs; i++)
Lars-Peter Clausen816c4262015-03-27 15:57:43 +0100195 strcut(chn->attrs[i].name, prefix_len + 1);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100196 }
197
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100198 return 0;
199}
200
Paul Cercueile1e0a8f2014-06-10 15:40:29 +0200201static int device_check_ready(const struct iio_device *dev, bool do_write)
202{
203 struct pollfd pollfd = {
204 .fd = fileno(dev->pdata->f),
205 .events = do_write ? POLLOUT : POLLIN,
206 };
207 int ret = poll(&pollfd, 1, dev->ctx->rw_timeout_ms);
208 if (ret < 0)
209 return -errno;
210 if (!ret)
211 return -ETIMEDOUT;
212 if (pollfd.revents & POLLNVAL)
213 return -EBADF;
214 if (!(pollfd.revents & (do_write ? POLLOUT : POLLIN)))
215 return -EIO;
216 return 0;
217}
218
Paul Cercueil45c575d2014-03-20 15:14:01 +0100219static ssize_t local_read(const struct iio_device *dev,
220 void *dst, size_t len, uint32_t *mask, size_t words)
Paul Cercueil44010ea2014-02-21 11:47:04 +0100221{
222 ssize_t ret;
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200223 struct iio_device_pdata *pdata = dev->pdata;
224 FILE *f = pdata->f;
Paul Cercueil44010ea2014-02-21 11:47:04 +0100225 if (!f)
226 return -EBADF;
Paul Cercueilff778232014-03-24 14:23:08 +0100227 if (words != dev->words)
Paul Cercueil45c575d2014-03-20 15:14:01 +0100228 return -EINVAL;
229
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200230 if (!pdata->buffer_enabled) {
231 ret = local_write_dev_attr(dev,
232 "buffer/enable", "1", 2, false);
233 if (ret < 0)
234 return ret;
235 else
236 pdata->buffer_enabled = true;
237 }
238
Lars-Peter Clausen666cfe52014-07-14 11:43:15 +0200239 ret = device_check_ready(dev, false);
240 if (ret < 0)
241 return ret;
242
Paul Cercueilff778232014-03-24 14:23:08 +0100243 memcpy(mask, dev->mask, words);
Paul Cercueil44010ea2014-02-21 11:47:04 +0100244 ret = fread(dst, 1, len, f);
Paul Cercueilf466c6d2014-06-02 17:41:02 +0200245 fflush(f);
246 if (ferror(f))
247 ret = -errno;
248 return ret ? ret : -EIO;
Paul Cercueil44010ea2014-02-21 11:47:04 +0100249}
250
251static ssize_t local_write(const struct iio_device *dev,
252 const void *src, size_t len)
253{
254 ssize_t ret;
Paul Cercueilafc17cc2014-05-26 15:18:21 +0200255 struct iio_device_pdata *pdata = dev->pdata;
256 FILE *f = pdata->f;
Paul Cercueil44010ea2014-02-21 11:47:04 +0100257 if (!f)
258 return -EBADF;
Paul Cercueilafc17cc2014-05-26 15:18:21 +0200259
Paul Cercueil91d25ac2014-05-27 10:52:42 +0200260 /* Writing is forbidden in cyclic mode with devices without the
261 * high-speed mmap interface, except for the devices starting with
262 * "cf-": in this case only cyclic mode is allowed. */
Paul Cercueild9d9e4d2014-05-27 11:49:35 +0200263 if (!pdata->is_high_speed && pdata->cyclic !=
264 (dev->name && !strncmp(dev->name, "cf-", 3)))
Paul Cercueilafc17cc2014-05-26 15:18:21 +0200265 return -EACCES;
266
Paul Cercueilafff89b2014-06-12 14:12:42 +0200267 /* We use write() instead of fwrite() here, to avoid the internal
268 * buffering of the FILE API. This ensures that a waveform written in
269 * cyclic mode will be written in only one system call, as the kernel
270 * sizes the buffer according to the length of the first write. */
Paul Cercueil82139cc2014-09-02 15:51:00 +0200271 if (pdata->cyclic) {
Paul Cercueil58b93ea2014-09-02 16:42:39 +0200272 ret = device_check_ready(dev, true);
273 if (ret < 0)
274 return ret;
275
Paul Cercueil82139cc2014-09-02 15:51:00 +0200276 ret = write(fileno(f), src, len);
277 if (ret < 0)
278 return -errno;
279 }
280
281 if (!pdata->buffer_enabled) {
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200282 ssize_t err = local_write_dev_attr(dev,
283 "buffer/enable", "1", 2, false);
284 if (err < 0)
285 return err;
286 else
287 pdata->buffer_enabled = true;
288 }
Paul Cercueil82139cc2014-09-02 15:51:00 +0200289
290 /* In cyclic mode, the buffer must be enabled after writing the samples.
291 * In non-cyclic mode, it must be enabled before writing the samples. */
Paul Cercueil58b93ea2014-09-02 16:42:39 +0200292 if (!pdata->cyclic) {
293 ret = device_check_ready(dev, true);
294 if (ret < 0)
295 return ret;
296
Paul Cercueil82139cc2014-09-02 15:51:00 +0200297 ret = write(fileno(f), src, len);
Paul Cercueil58b93ea2014-09-02 16:42:39 +0200298 }
Paul Cercueil82139cc2014-09-02 15:51:00 +0200299
Paul Cercueilf466c6d2014-06-02 17:41:02 +0200300 return ret ? ret : -EIO;
Paul Cercueil44010ea2014-02-21 11:47:04 +0100301}
302
Paul Cercueil92f46df2014-04-28 13:17:53 +0200303static ssize_t local_get_buffer(const struct iio_device *dev,
Paul Cercueil76ca8842015-03-05 11:16:16 +0100304 void **addr_ptr, size_t bytes_used,
305 uint32_t *mask, size_t words)
Paul Cercueil92f46df2014-04-28 13:17:53 +0200306{
307 struct block block;
308 struct iio_device_pdata *pdata = dev->pdata;
309 FILE *f = pdata->f;
310 ssize_t ret;
311
312 if (!pdata->is_high_speed)
313 return -ENOSYS;
314 if (!f)
315 return -EBADF;
Paul Cercueil3b6ad442014-05-12 17:43:31 +0200316 if (!addr_ptr)
Paul Cercueil92f46df2014-04-28 13:17:53 +0200317 return -EINVAL;
318
Paul Cercueil92f46df2014-04-28 13:17:53 +0200319 if (pdata->last_dequeued >= 0) {
Paul Cercueil3b6ad442014-05-12 17:43:31 +0200320 struct block *last_block = &pdata->blocks[pdata->last_dequeued];
Paul Cercueil71694c72014-05-22 14:02:13 +0200321
322 if (pdata->cyclic) {
323 if (pdata->cyclic_buffer_enqueued)
324 return -EBUSY;
325 pdata->blocks[0].flags |= BLOCK_FLAG_CYCLIC;
326 pdata->cyclic_buffer_enqueued = true;
327 }
328
Paul Cercueil3b6ad442014-05-12 17:43:31 +0200329 last_block->bytes_used = bytes_used;
330 ret = (ssize_t) ioctl(fileno(f),
331 BLOCK_ENQUEUE_IOCTL, last_block);
Paul Cercueil92f46df2014-04-28 13:17:53 +0200332 if (ret) {
333 ret = (ssize_t) -errno;
334 ERROR("Unable to enqueue block: %s\n", strerror(errno));
335 return ret;
336 }
Paul Cercueil71694c72014-05-22 14:02:13 +0200337
338 if (pdata->cyclic) {
339 *addr_ptr = pdata->addrs[pdata->last_dequeued];
340 return (ssize_t) last_block->bytes_used;
341 }
Paul Cercueil92f46df2014-04-28 13:17:53 +0200342 }
343
344 ret = (ssize_t) ioctl(fileno(f), BLOCK_DEQUEUE_IOCTL, &block);
345 if (ret) {
346 ret = (ssize_t) -errno;
347 ERROR("Unable to dequeue block: %s\n", strerror(errno));
348 return ret;
349 }
350
Paul Cercueil558ade42014-11-27 10:59:48 +0100351 /* Requested buffer size is too big! */
352 if (pdata->last_dequeued < 0 && bytes_used != block.size)
353 return -EFBIG;
354
Paul Cercueil92f46df2014-04-28 13:17:53 +0200355 pdata->last_dequeued = block.id;
356 *addr_ptr = pdata->addrs[block.id];
357 return (ssize_t) block.bytes_used;
358}
359
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200360static ssize_t local_read_all_dev_attrs(const struct iio_device *dev,
361 char *dst, size_t len, bool is_debug)
362{
363 unsigned int i, nb = is_debug ? dev->nb_debug_attrs : dev->nb_attrs;
364 char **attrs = is_debug ? dev->debug_attrs : dev->attrs;
365 char *ptr = dst;
366
367 for (i = 0; len >= 4 && i < nb; i++) {
368 /* Recursive! */
369 ssize_t ret = local_read_dev_attr(dev, attrs[i],
370 ptr + 4, len - 4, is_debug);
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200371 *(uint32_t *) ptr = htonl(ret);
Paul Cercueil13fb2622014-06-05 15:53:20 +0200372
373 /* Align the length to 4 bytes */
374 if (ret > 0 && ret & 3)
375 ret = ((ret >> 2) + 1) << 2;
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200376 ptr += 4 + (ret < 0 ? 0 : ret);
377 len -= 4 + (ret < 0 ? 0 : ret);
378 }
379
380 return ptr - dst;
381}
382
383static ssize_t local_read_all_chn_attrs(const struct iio_channel *chn,
384 char *dst, size_t len)
385{
386 unsigned int i;
387 char *ptr = dst;
388
389 for (i = 0; len >= 4 && i < chn->nb_attrs; i++) {
390 /* Recursive! */
391 ssize_t ret = local_read_chn_attr(chn,
392 chn->attrs[i].name, ptr + 4, len - 4);
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200393 *(uint32_t *) ptr = htonl(ret);
Paul Cercueil13fb2622014-06-05 15:53:20 +0200394
395 /* Align the length to 4 bytes */
396 if (ret > 0 && ret & 3)
397 ret = ((ret >> 2) + 1) << 2;
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200398 ptr += 4 + (ret < 0 ? 0 : ret);
399 len -= 4 + (ret < 0 ? 0 : ret);
400 }
401
402 return ptr - dst;
403}
404
Paul Cercueil1da28122014-05-22 10:59:49 +0200405static int local_buffer_analyze(unsigned int nb, const char *src, size_t len)
406{
407 while (nb--) {
408 int32_t val;
409
410 if (len < 4)
411 return -EINVAL;
412
413 val = (int32_t) ntohl(*(uint32_t *) src);
414 src += 4;
415 len -= 4;
416
417 if (val > 0) {
418 if ((uint32_t) val > len)
419 return -EINVAL;
Paul Cercueil33f21452014-06-10 13:57:41 +0200420
421 /* Align the length to 4 bytes */
422 if (val & 3)
423 val = ((val >> 2) + 1) << 2;
Paul Cercueil1da28122014-05-22 10:59:49 +0200424 len -= val;
425 src += val;
426 }
427 }
428
429 /* We should have analyzed the whole buffer by now */
430 return !len ? 0 : -EINVAL;
431}
432
433static ssize_t local_write_all_dev_attrs(const struct iio_device *dev,
434 const char *src, size_t len, bool is_debug)
435{
436 unsigned int i, nb = is_debug ? dev->nb_debug_attrs : dev->nb_attrs;
437 char **attrs = is_debug ? dev->debug_attrs : dev->attrs;
438 const char *ptr = src;
439
440 /* First step: Verify that the buffer is in the correct format */
441 if (local_buffer_analyze(nb, src, len))
442 return -EINVAL;
443
444 /* Second step: write the attributes */
445 for (i = 0; i < nb; i++) {
446 int32_t val = (int32_t) ntohl(*(uint32_t *) ptr);
447 ptr += 4;
448
449 if (val > 0) {
450 local_write_dev_attr(dev, attrs[i], ptr, val, is_debug);
Paul Cercueil13fb2622014-06-05 15:53:20 +0200451
452 /* Align the length to 4 bytes */
453 if (val & 3)
454 val = ((val >> 2) + 1) << 2;
Paul Cercueil1da28122014-05-22 10:59:49 +0200455 ptr += val;
456 }
457 }
458
459 return ptr - src;
460}
461
462static ssize_t local_write_all_chn_attrs(const struct iio_channel *chn,
463 const char *src, size_t len)
464{
465 unsigned int i, nb = chn->nb_attrs;
466 const char *ptr = src;
467
468 /* First step: Verify that the buffer is in the correct format */
469 if (local_buffer_analyze(nb, src, len))
470 return -EINVAL;
471
472 /* Second step: write the attributes */
473 for (i = 0; i < nb; i++) {
474 int32_t val = (int32_t) ntohl(*(uint32_t *) ptr);
475 ptr += 4;
476
477 if (val > 0) {
478 local_write_chn_attr(chn, chn->attrs[i].name, ptr, val);
Paul Cercueil13fb2622014-06-05 15:53:20 +0200479
480 /* Align the length to 4 bytes */
481 if (val & 3)
482 val = ((val >> 2) + 1) << 2;
Paul Cercueil1da28122014-05-22 10:59:49 +0200483 ptr += val;
484 }
485 }
486
487 return ptr - src;
488}
489
Paul Cercueil167d3112014-02-18 12:23:53 +0100490static ssize_t local_read_dev_attr(const struct iio_device *dev,
Paul Cercueil50c762a2014-04-14 15:55:43 +0200491 const char *attr, char *dst, size_t len, bool is_debug)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100492{
Paul Cercueil3e898302014-02-17 16:17:11 +0100493 FILE *f;
494 char buf[1024];
495 ssize_t ret;
496
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200497 if (!attr)
498 return local_read_all_dev_attrs(dev, dst, len, is_debug);
499
Paul Cercueil50c762a2014-04-14 15:55:43 +0200500 if (is_debug)
501 snprintf(buf, sizeof(buf), "/sys/kernel/debug/iio/%s/%s",
502 dev->id, attr);
503 else
504 snprintf(buf, sizeof(buf), "/sys/bus/iio/devices/%s/%s",
505 dev->id, attr);
Paul Cercueil3e898302014-02-17 16:17:11 +0100506 f = fopen(buf, "r");
507 if (!f)
508 return -errno;
509
510 ret = fread(dst, 1, len, f);
511 if (ret > 0)
512 dst[ret - 1] = '\0';
Paul Cercueil96dfedd2014-03-11 09:53:09 +0100513 fflush(f);
514 if (ferror(f))
Paul Cercueilf466c6d2014-06-02 17:41:02 +0200515 ret = -errno;
Paul Cercueil3e898302014-02-17 16:17:11 +0100516 fclose(f);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200517 return ret ? ret : -EIO;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100518}
519
Paul Cercueil167d3112014-02-18 12:23:53 +0100520static ssize_t local_write_dev_attr(const struct iio_device *dev,
Paul Cercueilcecda352014-05-06 18:14:29 +0200521 const char *attr, const char *src, size_t len, bool is_debug)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100522{
Paul Cercueil3e898302014-02-17 16:17:11 +0100523 FILE *f;
524 char buf[1024];
525 ssize_t ret;
Paul Cercueil3e898302014-02-17 16:17:11 +0100526
Paul Cercueil1da28122014-05-22 10:59:49 +0200527 if (!attr)
528 return local_write_all_dev_attrs(dev, src, len, is_debug);
529
Paul Cercueil50c762a2014-04-14 15:55:43 +0200530 if (is_debug)
531 snprintf(buf, sizeof(buf), "/sys/kernel/debug/iio/%s/%s",
532 dev->id, attr);
533 else
534 snprintf(buf, sizeof(buf), "/sys/bus/iio/devices/%s/%s",
535 dev->id, attr);
Andrea Galbusera7f83b832014-07-25 18:23:36 +0200536 f = fopen(buf, "w");
Paul Cercueil3e898302014-02-17 16:17:11 +0100537 if (!f)
538 return -errno;
539
540 ret = fwrite(src, 1, len, f);
Paul Cercueil96dfedd2014-03-11 09:53:09 +0100541 fflush(f);
542 if (ferror(f))
Paul Cercueilf466c6d2014-06-02 17:41:02 +0200543 ret = -errno;
Paul Cercueil3e898302014-02-17 16:17:11 +0100544 fclose(f);
Paul Cercueil6e7f79e2014-04-04 12:27:24 +0200545 return ret ? ret : -EIO;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100546}
547
Paul Cercueil167d3112014-02-18 12:23:53 +0100548static const char * get_filename(const struct iio_channel *chn,
549 const char *attr)
550{
Paul Cercueil167d3112014-02-18 12:23:53 +0100551 unsigned int i;
Paul Cercueil42d12352014-05-05 16:11:58 +0200552 for (i = 0; i < chn->nb_attrs; i++)
553 if (!strcmp(attr, chn->attrs[i].name))
554 return chn->attrs[i].filename;
Paul Cercueil167d3112014-02-18 12:23:53 +0100555 return attr;
556}
557
558static ssize_t local_read_chn_attr(const struct iio_channel *chn,
559 const char *attr, char *dst, size_t len)
560{
Paul Cercueil4ca6ddc2014-05-21 14:51:50 +0200561 if (!attr)
562 return local_read_all_chn_attrs(chn, dst, len);
563
Paul Cercueil167d3112014-02-18 12:23:53 +0100564 attr = get_filename(chn, attr);
Paul Cercueil50c762a2014-04-14 15:55:43 +0200565 return local_read_dev_attr(chn->dev, attr, dst, len, false);
Paul Cercueil167d3112014-02-18 12:23:53 +0100566}
567
568static ssize_t local_write_chn_attr(const struct iio_channel *chn,
Paul Cercueilcecda352014-05-06 18:14:29 +0200569 const char *attr, const char *src, size_t len)
Paul Cercueil167d3112014-02-18 12:23:53 +0100570{
Paul Cercueil1da28122014-05-22 10:59:49 +0200571 if (!attr)
572 return local_write_all_chn_attrs(chn, src, len);
573
Paul Cercueil167d3112014-02-18 12:23:53 +0100574 attr = get_filename(chn, attr);
Paul Cercueilcecda352014-05-06 18:14:29 +0200575 return local_write_dev_attr(chn->dev, attr, src, len, false);
Paul Cercueil167d3112014-02-18 12:23:53 +0100576}
577
Paul Cercueilff778232014-03-24 14:23:08 +0100578static int channel_write_state(const struct iio_channel *chn)
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100579{
Paul Cercueilff778232014-03-24 14:23:08 +0100580 char *en = iio_channel_is_enabled(chn) ? "1" : "0";
Paul Cercueilcecda352014-05-06 18:14:29 +0200581 ssize_t ret = local_write_chn_attr(chn, "en", en, 2);
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100582 if (ret < 0)
583 return (int) ret;
584 else
585 return 0;
586}
587
Paul Cercueil92f46df2014-04-28 13:17:53 +0200588static int enable_high_speed(const struct iio_device *dev)
589{
590 struct block_alloc_req req;
591 struct iio_device_pdata *pdata = dev->pdata;
592 unsigned int i;
593 int ret, fd = fileno(pdata->f);
594
Paul Cercueil71694c72014-05-22 14:02:13 +0200595 if (pdata->cyclic) {
596 pdata->nb_blocks = 1;
597 DEBUG("Enabling cyclic mode\n");
598 } else {
599 pdata->nb_blocks = NB_BLOCKS;
600 DEBUG("Cyclic mode not enabled\n");
601 }
602
Paul Cercueil1fa913d2015-04-28 16:30:53 +0200603 req.id = 0;
Paul Cercueil92f46df2014-04-28 13:17:53 +0200604 req.type = 0;
605 req.size = pdata->samples_count *
606 iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
Paul Cercueil71694c72014-05-22 14:02:13 +0200607 req.count = pdata->nb_blocks;
Paul Cercueil92f46df2014-04-28 13:17:53 +0200608
609 ret = ioctl(fd, BLOCK_ALLOC_IOCTL, &req);
610 if (ret < 0)
611 return -errno;
612
Lars-Peter Clausenc27cc532014-07-08 10:47:26 +0200613 /* We might get less blocks than what we asked for */
614 pdata->nb_blocks = req.count;
615
Paul Cercueil92f46df2014-04-28 13:17:53 +0200616 /* mmap all the blocks */
Paul Cercueil71694c72014-05-22 14:02:13 +0200617 for (i = 0; i < pdata->nb_blocks; i++) {
Paul Cercueil92f46df2014-04-28 13:17:53 +0200618 pdata->blocks[i].id = i;
619 ret = ioctl(fd, BLOCK_QUERY_IOCTL, &pdata->blocks[i]);
620 if (ret) {
621 ret = -errno;
622 goto err_munmap;
623 }
624
625 ret = ioctl(fd, BLOCK_ENQUEUE_IOCTL, &pdata->blocks[i]);
626 if (ret) {
627 ret = -errno;
628 goto err_munmap;
629 }
630
Paul Cercueil032a5652014-05-12 17:11:19 +0200631 pdata->addrs[i] = mmap(0, pdata->blocks[i].size,
632 PROT_READ | PROT_WRITE,
Paul Cercueil92f46df2014-04-28 13:17:53 +0200633 MAP_SHARED, fd, pdata->blocks[i].offset);
634 if (pdata->addrs[i] == MAP_FAILED) {
635 ret = -errno;
636 goto err_munmap;
637 }
638 }
639
Paul Cercueil4a702d32014-05-12 17:02:37 +0200640 pdata->last_dequeued = -1;
Paul Cercueil92f46df2014-04-28 13:17:53 +0200641 return 0;
642
643err_munmap:
644 for (; i > 0; i--)
645 munmap(pdata->addrs[i - 1], pdata->blocks[i - 1].size);
646 ioctl(fd, BLOCK_FREE_IOCTL, 0);
647 return ret;
648}
649
Lars-Peter Clausenac9e3282014-07-14 13:36:46 +0200650/* Some broken drivers expect length in bytes rather than samples */
651static bool local_length_in_bytes(const struct iio_device *dev)
652{
653 const char *name = iio_device_get_name(dev);
654
655 if (!strncmp("ad-mc-", name, 5))
656 return true;
657
658 return false;
659}
660
Paul Cercueil92f15c22015-04-20 11:36:51 +0200661static int local_open(const struct iio_device *dev,
662 size_t samples_count, bool cyclic)
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100663{
664 unsigned int i;
665 int ret;
666 char buf[1024];
667 struct iio_device_pdata *pdata = dev->pdata;
Lars-Peter Clausen00f80092014-07-01 17:52:05 +0200668 bool write_scan_elements = true;
669
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100670 if (pdata->f)
671 return -EBUSY;
672
Paul Cercueilcecda352014-05-06 18:14:29 +0200673 ret = local_write_dev_attr(dev, "buffer/enable", "0", 2, false);
Paul Cercueilf0aeae32014-04-02 13:52:26 +0200674 if (ret < 0)
Paul Cercueil48e39452014-03-14 09:37:53 +0100675 return ret;
676
Lars-Peter Clausenac9e3282014-07-14 13:36:46 +0200677 if (local_length_in_bytes(dev))
Paul Cercueil92f15c22015-04-20 11:36:51 +0200678 snprintf(buf, sizeof(buf), "%zu", samples_count *
679 iio_device_get_sample_size(dev));
Lars-Peter Clausenac9e3282014-07-14 13:36:46 +0200680 else
Paul Cercueil92f15c22015-04-20 11:36:51 +0200681 snprintf(buf, sizeof(buf), "%zu", samples_count);
Paul Cercueil71694c72014-05-22 14:02:13 +0200682 ret = local_write_dev_attr(dev, "buffer/length",
683 buf, strlen(buf) + 1, false);
684 if (ret < 0)
685 return ret;
Paul Cercueile6ebf492014-04-02 13:57:36 +0200686
Paul Cercueil8c29e412014-04-07 09:46:45 +0200687 snprintf(buf, sizeof(buf), "/dev/%s", dev->id);
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100688 pdata->f = fopen(buf, "r+");
689 if (!pdata->f)
690 return -errno;
691
Lars-Peter Clausen00f80092014-07-01 17:52:05 +0200692 /* There was a bug in older kernel versions that cause the kernel to
693 * crash if the scan_elements _en file for a channel was set to 1, so
694 * try to avoid that */
695 if (cyclic) {
696 unsigned int major, minor;
697 struct utsname uts;
698 uname(&uts);
699 sscanf(uts.release, "%u.%u", &major, &minor);
700 if (major < 2 || (major == 3 && minor < 14))
701 write_scan_elements = false;
702 }
703
704
705 if (write_scan_elements) {
Lars-Peter Clausen15d7e152015-03-04 15:59:47 +0100706 /* Disable channels */
707 for (i = 0; i < dev->nb_channels; i++) {
708 struct iio_channel *chn = dev->channels[i];
709 if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
710 ret = channel_write_state(chn);
711 if (ret < 0)
712 goto err_close;
713 }
714 }
Lars-Peter Clausen00f80092014-07-01 17:52:05 +0200715 /* Enable channels */
716 for (i = 0; i < dev->nb_channels; i++) {
717 struct iio_channel *chn = dev->channels[i];
Lars-Peter Clausen15d7e152015-03-04 15:59:47 +0100718 if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
Lars-Peter Clausen00f80092014-07-01 17:52:05 +0200719 ret = channel_write_state(chn);
720 if (ret < 0)
721 goto err_close;
722 }
Paul Cercueile1311222014-03-12 15:46:16 +0100723 }
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100724 }
725
Paul Cercueil71694c72014-05-22 14:02:13 +0200726 pdata->cyclic = cyclic;
727 pdata->cyclic_buffer_enqueued = false;
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200728 pdata->buffer_enabled = false;
Paul Cercueilb762fc62014-05-12 16:56:09 +0200729 pdata->samples_count = samples_count;
Paul Cercueil71694c72014-05-22 14:02:13 +0200730 pdata->is_high_speed = !enable_high_speed(dev);
Paul Cercueilb762fc62014-05-12 16:56:09 +0200731
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200732 if (!pdata->is_high_speed) {
Paul Cercueil032a5652014-05-12 17:11:19 +0200733 WARNING("High-speed mode not enabled\n");
Paul Cercueil6ea8a752014-06-03 11:35:35 +0200734 } else {
735 /* NOTE: The low-speed interface will enable the buffer after
736 * the first samples are written */
737 ret = local_write_dev_attr(dev, "buffer/enable", "1", 2, false);
738 if (ret < 0)
739 goto err_close;
740 pdata->buffer_enabled = true;
741 }
Paul Cercueil45c575d2014-03-20 15:14:01 +0100742
Paul Cercueil45c575d2014-03-20 15:14:01 +0100743 return 0;
Paul Cercueile1311222014-03-12 15:46:16 +0100744err_close:
745 fclose(pdata->f);
746 pdata->f = NULL;
747 return ret;
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100748}
749
750static int local_close(const struct iio_device *dev)
751{
752 struct iio_device_pdata *pdata = dev->pdata;
Paul Cercueilfc8ec4a2014-03-17 16:42:22 +0100753 int ret;
754
755 if (!pdata->f)
756 return -EBADF;
757
Paul Cercueil92f46df2014-04-28 13:17:53 +0200758 if (pdata->is_high_speed) {
759 unsigned int i;
Paul Cercueil71694c72014-05-22 14:02:13 +0200760 for (i = 0; i < pdata->nb_blocks; i++)
Paul Cercueil92f46df2014-04-28 13:17:53 +0200761 munmap(pdata->addrs[i], pdata->blocks[i].size);
762 ioctl(fileno(pdata->f), BLOCK_FREE_IOCTL, 0);
763 }
764
Paul Cercueilfc8ec4a2014-03-17 16:42:22 +0100765 ret = fclose(pdata->f);
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100766 if (ret)
767 return ret;
768
769 pdata->f = NULL;
Paul Cercueil71694c72014-05-22 14:02:13 +0200770 ret = local_write_dev_attr(dev, "buffer/enable", "0", 2, false);
771 return (ret < 0) ? ret : 0;
Paul Cercueil8a7975e2014-03-12 12:53:43 +0100772}
773
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100774static int local_get_trigger(const struct iio_device *dev,
775 const struct iio_device **trigger)
776{
777 char buf[1024];
778 unsigned int i;
779 ssize_t nb = local_read_dev_attr(dev, "trigger/current_trigger",
Paul Cercueil50c762a2014-04-14 15:55:43 +0200780 buf, sizeof(buf), false);
Paul Cercueild09322a2014-04-02 13:50:18 +0200781 if (nb < 0) {
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100782 *trigger = NULL;
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100783 return (int) nb;
Paul Cercueild09322a2014-04-02 13:50:18 +0200784 }
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100785
Lars-Peter Clausenb5cdc102014-08-21 14:45:52 +0200786 if (buf[0] == '\0') {
787 *trigger = NULL;
788 return 0;
789 }
790
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100791 nb = dev->ctx->nb_devices;
Paul Cercueil4e2f6652014-04-04 12:41:45 +0200792 for (i = 0; i < (size_t) nb; i++) {
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100793 const struct iio_device *cur = dev->ctx->devices[i];
794 if (cur->name && !strcmp(cur->name, buf)) {
795 *trigger = cur;
796 return 0;
797 }
798 }
799 return -ENXIO;
800}
801
802static int local_set_trigger(const struct iio_device *dev,
803 const struct iio_device *trigger)
804{
805 ssize_t nb;
806 const char *value = trigger ? trigger->name : "";
Paul Cercueilcecda352014-05-06 18:14:29 +0200807 nb = local_write_dev_attr(dev, "trigger/current_trigger",
808 value, strlen(value) + 1, false);
Paul Cercueil096e9aa2014-03-10 12:48:51 +0100809 if (nb < 0)
810 return (int) nb;
811 else
812 return 0;
813}
814
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100815static bool is_channel(const char *attr)
816{
817 unsigned int i;
818 char *ptr = NULL;
Paul Cercueilec6857d2014-03-11 17:23:49 +0100819 if (!strncmp(attr, "in_timestamp_", sizeof("in_timestamp_") - 1))
820 return true;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100821 if (!strncmp(attr, "in_", 3))
822 ptr = strchr(attr + 3, '_');
823 else if (!strncmp(attr, "out_", 4))
824 ptr = strchr(attr + 4, '_');
825 if (!ptr)
826 return false;
827 if (*(ptr - 1) >= '0' && *(ptr - 1) <= '9')
828 return true;
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100829
830 if (find_modifier(ptr + 1, NULL) != IIO_NO_MOD)
831 return true;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100832 return false;
833}
834
835static char * get_channel_id(const char *attr)
836{
837 char *res, *ptr;
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100838 size_t len;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100839
840 attr = strchr(attr, '_') + 1;
841 ptr = strchr(attr, '_');
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100842 if (find_modifier(ptr + 1, &len) != IIO_NO_MOD)
843 ptr += len + 1;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100844
845 res = malloc(ptr - attr + 1);
846 if (!res)
847 return NULL;
848
849 memcpy(res, attr, ptr - attr);
850 res[ptr - attr] = 0;
851 return res;
852}
853
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200854static char * get_short_attr_name(struct iio_channel *chn, const char *attr)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100855{
856 char *ptr = strchr(attr, '_') + 1;
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100857 size_t len;
Lars-Peter Clausen82390f52014-07-30 15:34:56 +0200858
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100859 ptr = strchr(ptr, '_') + 1;
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +0100860 if (find_modifier(ptr, &len) != IIO_NO_MOD)
861 ptr += len + 1;
Lars-Peter Clausen82390f52014-07-30 15:34:56 +0200862
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200863 if (chn->name) {
864 size_t len = strlen(chn->name);
865 if (strncmp(chn->name, ptr, len) == 0 && ptr[len] == '_')
866 ptr += len + 1;
867 }
868
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100869 return strdup(ptr);
870}
871
872static int read_device_name(struct iio_device *dev)
873{
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100874 char buf[1024];
Paul Cercueil8c29e412014-04-07 09:46:45 +0200875 ssize_t ret = iio_device_attr_read(dev, "name", buf, sizeof(buf));
Paul Cercueil30430c72014-02-17 16:52:37 +0100876 if (ret < 0)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100877 return ret;
Paul Cercueil30430c72014-02-17 16:52:37 +0100878 else if (ret == 0)
879 return -EIO;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100880
Paul Cercueil30430c72014-02-17 16:52:37 +0100881 dev->name = strdup(buf);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100882 if (!dev->name)
883 return -ENOMEM;
Paul Cercueil30430c72014-02-17 16:52:37 +0100884 else
885 return 0;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100886}
887
888static int add_attr_to_device(struct iio_device *dev, const char *attr)
889{
Paul Cercueilbb618272014-02-20 11:35:52 +0100890 char **attrs, *name;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100891 unsigned int i;
892
893 for (i = 0; i < ARRAY_SIZE(device_attrs_blacklist); i++)
894 if (!strcmp(device_attrs_blacklist[i], attr))
895 return 0;
896
897 if (!strcmp(attr, "name"))
898 return read_device_name(dev);
899
900 name = strdup(attr);
901 if (!name)
902 return -ENOMEM;
903
904 attrs = realloc(dev->attrs, (1 + dev->nb_attrs) * sizeof(char *));
905 if (!attrs) {
906 free(name);
907 return -ENOMEM;
908 }
909
910 attrs[dev->nb_attrs++] = name;
911 dev->attrs = attrs;
912 DEBUG("Added attr \'%s\' to device \'%s\'\n", attr, dev->id);
913 return 0;
914}
915
Paul Cercueile3fbd952014-03-11 16:58:33 +0100916static int add_attr_to_channel(struct iio_channel *chn,
917 const char *attr, const char *path)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100918{
Paul Cercueilb34e0222014-05-05 15:32:38 +0200919 struct iio_channel_attr *attrs;
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200920 char *fn, *name = get_short_attr_name(chn, attr);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100921 if (!name)
922 return -ENOMEM;
923
Paul Cercueile3fbd952014-03-11 16:58:33 +0100924 fn = strdup(path);
Paul Cercueil167d3112014-02-18 12:23:53 +0100925 if (!fn)
926 goto err_free_name;
927
Paul Cercueilb34e0222014-05-05 15:32:38 +0200928 attrs = realloc(chn->attrs, (1 + chn->nb_attrs) *
929 sizeof(struct iio_channel_attr));
Paul Cercueil167d3112014-02-18 12:23:53 +0100930 if (!attrs)
931 goto err_free_fn;
932
Paul Cercueil42d12352014-05-05 16:11:58 +0200933 attrs[chn->nb_attrs].filename = fn;
Paul Cercueilb34e0222014-05-05 15:32:38 +0200934 attrs[chn->nb_attrs++].name = name;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100935 chn->attrs = attrs;
936 DEBUG("Added attr \'%s\' to channel \'%s\'\n", name, chn->id);
937 return 0;
Paul Cercueil167d3112014-02-18 12:23:53 +0100938
Paul Cercueil167d3112014-02-18 12:23:53 +0100939err_free_fn:
940 free(fn);
941err_free_name:
942 free(name);
943 return -ENOMEM;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100944}
945
946static int add_channel_to_device(struct iio_device *dev,
947 struct iio_channel *chn)
948{
949 struct iio_channel **channels = realloc(dev->channels,
950 (dev->nb_channels + 1) * sizeof(struct iio_channel *));
951 if (!channels)
952 return -ENOMEM;
953
954 channels[dev->nb_channels++] = chn;
955 dev->channels = channels;
956 DEBUG("Added channel \'%s\' to device \'%s\'\n", chn->id, dev->id);
957 return 0;
958}
959
960static int add_device_to_context(struct iio_context *ctx,
961 struct iio_device *dev)
962{
963 struct iio_device **devices = realloc(ctx->devices,
964 (ctx->nb_devices + 1) * sizeof(struct iio_device *));
965 if (!devices)
966 return -ENOMEM;
967
968 devices[ctx->nb_devices++] = dev;
969 ctx->devices = devices;
970 DEBUG("Added device \'%s\' to context \'%s\'\n", dev->id, ctx->name);
971 return 0;
972}
973
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200974/*
975 * Possible return values:
976 * 0 = Attribute should not be moved to the channel
977 * 1 = Attribute should be moved to the channel and it is a shared attribute
978 * 2 = Attribute should be moved to the channel and it is a private attribute
979 */
980static unsigned int is_global_attr(struct iio_channel *chn, const char *attr)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100981{
982 unsigned int i, len;
983 char *ptr;
984
Paul Cercueil35a01312014-02-20 10:56:57 +0100985 if (!chn->is_output && !strncmp(attr, "in_", 3))
986 attr += 3;
987 else if (chn->is_output && !strncmp(attr, "out_", 4))
988 attr += 4;
989 else
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200990 return 0;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100991
992 ptr = strchr(attr, '_');
993 if (!ptr)
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200994 return 0;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100995
996 len = ptr - attr;
997
998 if (strncmp(chn->id, attr, len))
Lars-Peter Clausende6faf02014-08-25 15:42:51 +0200999 return 0;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001000
1001 DEBUG("Found match: %s and %s\n", chn->id, attr);
Lars-Peter Clausende6faf02014-08-25 15:42:51 +02001002 if (chn->id[len] >= '0' && chn->id[len] <= '9') {
1003 if (chn->name) {
1004 size_t name_len = strlen(chn->name);
1005 if (strncmp(chn->name, attr + len + 1, name_len) == 0 &&
1006 attr[len + 1 + name_len] == '_')
1007 return 2;
1008 }
1009 return 1;
1010 } else if (chn->id[len] != '_') {
1011 return 0;
1012 }
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001013
Lars-Peter Clausen2d620de2015-03-27 13:33:55 +01001014 if (find_modifier(chn->id + len + 1, NULL) != IIO_NO_MOD)
1015 return 1;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001016
Lars-Peter Clausende6faf02014-08-25 15:42:51 +02001017 return 0;
1018}
1019
1020static int detect_global_attr(struct iio_device *dev, const char *attr,
1021 unsigned int level, bool *match)
1022{
1023 unsigned int i;
1024
1025 *match = false;
1026 for (i = 0; i < dev->nb_channels; i++) {
1027 struct iio_channel *chn = dev->channels[i];
1028 if (is_global_attr(chn, attr) == level) {
1029 int ret;
1030 *match = true;
1031 ret = add_attr_to_channel(chn, attr, attr);
1032 if (ret)
1033 return ret;
1034 }
1035 }
1036
1037 return 0;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001038}
1039
1040static int detect_and_move_global_attrs(struct iio_device *dev)
1041{
1042 unsigned int i;
Paul Cercueilbb618272014-02-20 11:35:52 +01001043 char **ptr = dev->attrs;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001044
1045 for (i = 0; i < dev->nb_attrs; i++) {
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001046 const char *attr = dev->attrs[i];
Lars-Peter Clausende6faf02014-08-25 15:42:51 +02001047 bool match;
1048 int ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001049
Lars-Peter Clausende6faf02014-08-25 15:42:51 +02001050 ret = detect_global_attr(dev, attr, 2, &match);
1051 if (ret)
1052 return ret;
1053
1054 if (!match) {
1055 ret = detect_global_attr(dev, attr, 1, &match);
1056 if (ret)
1057 return ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001058 }
1059
Lars-Peter Clausende6faf02014-08-25 15:42:51 +02001060 if (match) {
Paul Cercueilbb618272014-02-20 11:35:52 +01001061 free(dev->attrs[i]);
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001062 dev->attrs[i] = NULL;
1063 }
1064 }
1065
1066 for (i = 0; i < dev->nb_attrs; i++) {
1067 if (dev->attrs[i])
1068 *ptr++ = dev->attrs[i];
1069 }
1070
1071 dev->nb_attrs = ptr - dev->attrs;
1072 return 0;
1073}
1074
1075static struct iio_channel *create_channel(struct iio_device *dev,
Paul Cercueile3fbd952014-03-11 16:58:33 +01001076 char *id, const char *attr, const char *path)
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001077{
1078 struct iio_channel *chn = calloc(1, sizeof(*chn));
1079 if (!chn)
1080 return NULL;
1081
Paul Cercueileaab6582014-02-21 09:35:59 +01001082 if (!strncmp(attr, "out_", 4))
Paul Cercueil35a01312014-02-20 10:56:57 +01001083 chn->is_output = true;
Paul Cercueileaab6582014-02-21 09:35:59 +01001084 else if (strncmp(attr, "in_", 3))
Paul Cercueil42d12352014-05-05 16:11:58 +02001085 goto err_free_chn;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001086
1087 chn->dev = dev;
1088 chn->id = id;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001089
Paul Cercueile3fbd952014-03-11 16:58:33 +01001090 if (!add_attr_to_channel(chn, attr, path))
Paul Cercueileaab6582014-02-21 09:35:59 +01001091 return chn;
1092
Paul Cercueileaab6582014-02-21 09:35:59 +01001093err_free_chn:
1094 free(chn);
1095 return NULL;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001096}
1097
Paul Cercueile3fbd952014-03-11 16:58:33 +01001098static int add_attr_or_channel_helper(struct iio_device *dev,
Paul Cercueila91358e2014-04-24 16:40:19 +02001099 const char *path, bool dir_is_scan_elements)
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001100{
Paul Cercueil1be57832014-03-11 16:27:16 +01001101 int ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001102 unsigned int i;
Paul Cercueil1be57832014-03-11 16:27:16 +01001103 struct iio_channel *chn;
Paul Cercueile3fbd952014-03-11 16:58:33 +01001104 char buf[1024], *channel_id;
Paul Cercueil1be57832014-03-11 16:27:16 +01001105 const char *name = strrchr(path, '/') + 1;
Paul Cercueila91358e2014-04-24 16:40:19 +02001106
1107 if (dir_is_scan_elements) {
1108 snprintf(buf, sizeof(buf), "scan_elements/%s", name);
Paul Cercueile3fbd952014-03-11 16:58:33 +01001109 path = buf;
Paul Cercueila91358e2014-04-24 16:40:19 +02001110 } else {
1111 path = name;
Paul Cercueile3fbd952014-03-11 16:58:33 +01001112 }
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001113
Paul Cercueil1be57832014-03-11 16:27:16 +01001114 if (!is_channel(name))
1115 return add_attr_to_device(dev, name);
1116
1117 channel_id = get_channel_id(name);
1118 if (!channel_id)
1119 return -ENOMEM;
1120
1121 for (i = 0; i < dev->nb_channels; i++) {
1122 chn = dev->channels[i];
Paul Cercueil5248e792014-03-31 14:39:10 +02001123 if (!strcmp(chn->id, channel_id)
1124 && chn->is_output == (name[0] == 'o')) {
Paul Cercueil1be57832014-03-11 16:27:16 +01001125 free(channel_id);
Paul Cercueila91358e2014-04-24 16:40:19 +02001126 ret = add_attr_to_channel(chn, name, path);
1127 chn->is_scan_element = dir_is_scan_elements && !ret;
1128 return ret;
Paul Cercueil1be57832014-03-11 16:27:16 +01001129 }
1130 }
1131
Paul Cercueile3fbd952014-03-11 16:58:33 +01001132 chn = create_channel(dev, channel_id, name, path);
Paul Cercueil1be57832014-03-11 16:27:16 +01001133 if (!chn) {
1134 free(channel_id);
1135 return -ENXIO;
1136 }
1137 ret = add_channel_to_device(dev, chn);
1138 if (ret)
1139 free_channel(chn);
Paul Cercueila91358e2014-04-24 16:40:19 +02001140 else
1141 chn->is_scan_element = dir_is_scan_elements;
Paul Cercueil1be57832014-03-11 16:27:16 +01001142 return ret;
1143}
1144
Paul Cercueile3fbd952014-03-11 16:58:33 +01001145static int add_attr_or_channel(void *d, const char *path)
1146{
Paul Cercueila91358e2014-04-24 16:40:19 +02001147 return add_attr_or_channel_helper((struct iio_device *) d, path, false);
Paul Cercueile3fbd952014-03-11 16:58:33 +01001148}
1149
1150static int add_scan_element(void *d, const char *path)
1151{
Paul Cercueila91358e2014-04-24 16:40:19 +02001152 return add_attr_or_channel_helper((struct iio_device *) d, path, true);
Paul Cercueile3fbd952014-03-11 16:58:33 +01001153}
1154
Paul Cercueil1be57832014-03-11 16:27:16 +01001155static int foreach_in_dir(void *d, const char *path, bool is_dir,
1156 int (*callback)(void *, const char *))
1157{
1158 long name_max;
1159 struct dirent *entry, *result;
1160 DIR *dir = opendir(path);
1161 if (!dir)
1162 return -errno;
1163
1164 name_max = pathconf(path, _PC_NAME_MAX);
1165 if (name_max == -1)
1166 name_max = 255;
1167 entry = malloc(offsetof(struct dirent, d_name) + name_max + 1);
1168 if (!entry) {
1169 closedir(dir);
1170 return -ENOMEM;
1171 }
1172
1173 while (true) {
1174 struct stat st;
1175 char buf[1024];
1176 int ret = readdir_r(dir, entry, &result);
1177 if (ret) {
1178 strerror_r(ret, buf, sizeof(buf));
1179 ERROR("Unable to open directory %s: %s\n", path, buf);
1180 free(entry);
1181 closedir(dir);
Paul Cercueilc57da332015-03-16 17:09:48 +01001182 return -ret;
Paul Cercueil1be57832014-03-11 16:27:16 +01001183 }
1184 if (!result)
1185 break;
1186
1187 snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
1188 if (stat(buf, &st) < 0) {
1189 ret = -errno;
Paul Cercueilc21300c2014-03-13 09:54:14 +01001190 strerror_r(errno, buf, sizeof(buf));
Paul Cercueil1be57832014-03-11 16:27:16 +01001191 ERROR("Unable to stat file: %s\n", buf);
1192 free(entry);
1193 closedir(dir);
1194 return ret;
1195 }
1196
1197 if (is_dir && S_ISDIR(st.st_mode) && entry->d_name[0] != '.')
1198 ret = callback(d, buf);
1199 else if (!is_dir && S_ISREG(st.st_mode))
1200 ret = callback(d, buf);
1201 else
1202 continue;
1203
1204 if (ret < 0) {
1205 free(entry);
1206 closedir(dir);
1207 return ret;
1208 }
1209 }
1210
1211 free(entry);
1212 closedir(dir);
1213 return 0;
1214}
1215
Paul Cercueile3fbd952014-03-11 16:58:33 +01001216static int add_scan_elements(struct iio_device *dev, const char *devpath)
1217{
1218 struct stat st;
1219 char buf[1024];
1220 snprintf(buf, sizeof(buf), "%s/scan_elements", devpath);
1221
1222 if (!stat(buf, &st) && S_ISDIR(st.st_mode)) {
1223 int ret = foreach_in_dir(dev, buf, false, add_scan_element);
1224 if (ret < 0)
1225 return ret;
1226 }
1227
1228 return 0;
1229}
1230
Paul Cercueil1be57832014-03-11 16:27:16 +01001231static int create_device(void *d, const char *path)
1232{
Paul Cercueilff778232014-03-24 14:23:08 +01001233 uint32_t *mask = NULL;
Paul Cercueil1be57832014-03-11 16:27:16 +01001234 unsigned int i;
1235 int ret;
1236 struct iio_context *ctx = d;
1237 struct iio_device *dev = calloc(1, sizeof(*dev));
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001238 if (!dev)
Paul Cercueil1be57832014-03-11 16:27:16 +01001239 return -ENOMEM;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001240
Paul Cercueileaab6582014-02-21 09:35:59 +01001241 dev->pdata = calloc(1, sizeof(*dev->pdata));
1242 if (!dev->pdata) {
1243 free(dev);
Paul Cercueil1be57832014-03-11 16:27:16 +01001244 return -ENOMEM;
Paul Cercueileaab6582014-02-21 09:35:59 +01001245 }
1246
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001247 dev->ctx = ctx;
Paul Cercueil1be57832014-03-11 16:27:16 +01001248 dev->id = strdup(strrchr(path, '/') + 1);
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001249 if (!dev->id) {
Paul Cercueileaab6582014-02-21 09:35:59 +01001250 free(dev->pdata);
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001251 free(dev);
Paul Cercueil1be57832014-03-11 16:27:16 +01001252 return -ENOMEM;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001253 }
1254
Paul Cercueil1be57832014-03-11 16:27:16 +01001255 ret = foreach_in_dir(dev, path, false, add_attr_or_channel);
1256 if (ret < 0) {
1257 free_device(dev);
1258 return ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001259 }
1260
Paul Cercueil54913ac2014-03-31 14:48:19 +02001261 for (i = 0; i < dev->nb_channels; i++)
1262 set_channel_name(dev->channels[i]);
1263
Michael Hennerichebe49662014-11-07 10:32:44 +01001264 ret = add_scan_elements(dev, path);
Paul Cercueile3fbd952014-03-11 16:58:33 +01001265 if (ret < 0) {
1266 free_device(dev);
1267 return ret;
1268 }
1269
Michael Hennerichebe49662014-11-07 10:32:44 +01001270 ret = detect_and_move_global_attrs(dev);
Paul Cercueil1be57832014-03-11 16:27:16 +01001271 if (ret < 0) {
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001272 free_device(dev);
Paul Cercueil1be57832014-03-11 16:27:16 +01001273 return ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001274 }
1275
Paul Cercueilff778232014-03-24 14:23:08 +01001276 dev->words = (dev->nb_channels + 31) / 32;
1277 if (dev->words) {
1278 mask = calloc(dev->words, sizeof(*mask));
Paul Cercueil45c575d2014-03-20 15:14:01 +01001279 if (!mask) {
1280 free_device(dev);
1281 return ret;
1282 }
Paul Cercueil45c575d2014-03-20 15:14:01 +01001283 }
1284
Paul Cercueilff778232014-03-24 14:23:08 +01001285 dev->mask = mask;
Paul Cercueil45c575d2014-03-20 15:14:01 +01001286
Paul Cercueil1be57832014-03-11 16:27:16 +01001287 ret = add_device_to_context(ctx, dev);
1288 if (ret < 0)
1289 free_device(dev);
1290 return ret;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001291}
1292
Paul Cercueilddaa26a2014-04-14 17:32:18 +02001293static int add_debug_attr(void *d, const char *path)
1294{
1295 struct iio_device *dev = d;
1296 const char *attr = strrchr(path, '/') + 1;
1297 char **attrs, *name = strdup(attr);
1298 if (!name)
1299 return -ENOMEM;
1300
1301 attrs = realloc(dev->debug_attrs,
1302 (1 + dev->nb_debug_attrs) * sizeof(char *));
1303 if (!attrs) {
1304 free(name);
1305 return -ENOMEM;
1306 }
1307
1308 attrs[dev->nb_debug_attrs++] = name;
1309 dev->debug_attrs = attrs;
1310 DEBUG("Added debug attr \'%s\' to device \'%s\'\n", name, dev->id);
1311 return 0;
1312}
1313
1314static int add_debug(void *d, const char *path)
1315{
1316 struct iio_context *ctx = d;
1317 const char *name = strrchr(path, '/') + 1;
1318 struct iio_device *dev = iio_context_find_device(ctx, name);
1319 if (!dev)
1320 return -ENODEV;
1321 else
1322 return foreach_in_dir(dev, path, false, add_debug_attr);
1323}
1324
Paul Cercueile1e0a8f2014-06-10 15:40:29 +02001325static int local_set_timeout(struct iio_context *ctx, unsigned int timeout)
1326{
1327 ctx->rw_timeout_ms = timeout;
1328 return 0;
1329}
1330
Paul Cercueil0865e802014-10-28 14:35:19 +01001331static struct iio_context * local_clone(
1332 const struct iio_context *ctx __attribute__((unused)))
1333{
Paul Cercueil63e52182014-12-11 12:52:48 +01001334 return local_create_context();
Paul Cercueil0865e802014-10-28 14:35:19 +01001335}
1336
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001337static struct iio_backend_ops local_ops = {
Paul Cercueil0865e802014-10-28 14:35:19 +01001338 .clone = local_clone,
Paul Cercueil44010ea2014-02-21 11:47:04 +01001339 .open = local_open,
1340 .close = local_close,
1341 .read = local_read,
1342 .write = local_write,
Paul Cercueil92f46df2014-04-28 13:17:53 +02001343 .get_buffer = local_get_buffer,
Paul Cercueil167d3112014-02-18 12:23:53 +01001344 .read_device_attr = local_read_dev_attr,
1345 .write_device_attr = local_write_dev_attr,
1346 .read_channel_attr = local_read_chn_attr,
1347 .write_channel_attr = local_write_chn_attr,
Paul Cercueil096e9aa2014-03-10 12:48:51 +01001348 .get_trigger = local_get_trigger,
1349 .set_trigger = local_set_trigger,
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001350 .shutdown = local_shutdown,
Paul Cercueile1e0a8f2014-06-10 15:40:29 +02001351 .set_timeout = local_set_timeout,
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001352};
1353
Paul Cercueilcac16ac2014-06-11 14:32:17 +02001354static void init_index(struct iio_channel *chn)
1355{
1356 char buf[1024];
Paul Cercueil97679ac2014-06-12 10:08:20 +02001357 long id = -ENOENT;
1358
1359 if (chn->is_scan_element) {
1360 id = (long) local_read_chn_attr(chn, "index", buf, sizeof(buf));
1361 if (id > 0)
1362 id = atol(buf);
1363 }
1364 chn->index = id;
Paul Cercueilcac16ac2014-06-11 14:32:17 +02001365}
1366
1367static void init_data_format(struct iio_channel *chn)
1368{
1369 char buf[1024];
1370 ssize_t ret;
1371
1372 if (chn->is_scan_element) {
1373 ret = local_read_chn_attr(chn, "type", buf, sizeof(buf));
1374 if (ret < 0) {
1375 chn->format.length = 0;
1376 } else {
1377 char endian, sign;
1378
1379 sscanf(buf, "%ce:%c%u/%u>>%u", &endian, &sign,
1380 &chn->format.bits, &chn->format.length,
1381 &chn->format.shift);
Michael Hennerichfa3c6f62014-08-13 11:21:23 +02001382 chn->format.is_signed = (sign == 's' || sign == 'S');
1383 chn->format.is_fully_defined =
1384 (sign == 'S' || sign == 'U'||
1385 chn->format.bits == chn->format.length);
Paul Cercueilcac16ac2014-06-11 14:32:17 +02001386 chn->format.is_be = endian == 'b';
1387 }
1388 }
1389
1390 ret = iio_channel_attr_read(chn, "scale", buf, sizeof(buf));
1391 if (ret < 0) {
1392 chn->format.with_scale = false;
1393 } else {
1394 chn->format.with_scale = true;
1395 chn->format.scale = atof(buf);
1396 }
1397}
1398
1399static void init_scan_elements(struct iio_context *ctx)
1400{
1401 unsigned int i, j;
1402
1403 for (i = 0; i < ctx->nb_devices; i++) {
1404 struct iio_device *dev = ctx->devices[i];
1405
1406 for (j = 0; j < dev->nb_channels; j++) {
1407 struct iio_channel *chn = dev->channels[j];
Paul Cercueil97679ac2014-06-12 10:08:20 +02001408 init_index(chn);
Paul Cercueilcac16ac2014-06-11 14:32:17 +02001409 init_data_format(chn);
1410 }
1411 }
1412}
1413
Paul Cercueil63e52182014-12-11 12:52:48 +01001414struct iio_context * local_create_context(void)
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001415{
Paul Cercueil1be57832014-03-11 16:27:16 +01001416 int ret;
Paul Cercueilc957d9f2015-01-08 15:05:42 +01001417 unsigned int len;
1418 struct utsname uts;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001419 struct iio_context *ctx = calloc(1, sizeof(*ctx));
Paul Cercueil3ad8e372015-03-16 17:07:37 +01001420 if (!ctx)
1421 goto err_set_errno_enomem;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001422
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001423 ctx->ops = &local_ops;
1424 ctx->name = "local";
Paul Cercueile1e0a8f2014-06-10 15:40:29 +02001425 local_set_timeout(ctx, DEFAULT_TIMEOUT_MS);
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001426
Paul Cercueilc957d9f2015-01-08 15:05:42 +01001427 uname(&uts);
1428 len = strlen(uts.sysname) + strlen(uts.nodename) + strlen(uts.release)
1429 + strlen(uts.version) + strlen(uts.machine);
1430 ctx->description = malloc(len + 5); /* 4 spaces + EOF */
1431 if (!ctx->description) {
Paul Cercueilc957d9f2015-01-08 15:05:42 +01001432 free(ctx);
Paul Cercueil3ad8e372015-03-16 17:07:37 +01001433 goto err_set_errno_enomem;
Paul Cercueilc957d9f2015-01-08 15:05:42 +01001434 }
1435
1436 snprintf(ctx->description, len + 5, "%s %s %s %s %s", uts.sysname,
1437 uts.nodename, uts.release, uts.version, uts.machine);
1438
Paul Cercueil1be57832014-03-11 16:27:16 +01001439 ret = foreach_in_dir(ctx, "/sys/bus/iio/devices", true, create_device);
1440 if (ret < 0) {
Paul Cercueil1be57832014-03-11 16:27:16 +01001441 iio_context_destroy(ctx);
Paul Cercueil3ad8e372015-03-16 17:07:37 +01001442 errno = -ret;
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001443 return NULL;
1444 }
1445
Paul Cercueilddaa26a2014-04-14 17:32:18 +02001446 foreach_in_dir(ctx, "/sys/kernel/debug/iio", true, add_debug);
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001447
Paul Cercueilcac16ac2014-06-11 14:32:17 +02001448 init_scan_elements(ctx);
Paul Cercueil97679ac2014-06-12 10:08:20 +02001449 iio_context_init(ctx);
Paul Cercueilddaa26a2014-04-14 17:32:18 +02001450
Paul Cercueilc1ed8482014-06-11 16:29:43 +02001451 ctx->xml = iio_context_create_xml(ctx);
1452 if (!ctx->xml) {
Paul Cercueil4c6729d2014-04-04 17:24:41 +02001453 iio_context_destroy(ctx);
Paul Cercueil3ad8e372015-03-16 17:07:37 +01001454 goto err_set_errno_enomem;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001455 }
Paul Cercueilae88fde2014-03-12 11:47:10 +01001456
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001457 return ctx;
Paul Cercueil3ad8e372015-03-16 17:07:37 +01001458
1459err_set_errno_enomem:
1460 errno = ENOMEM;
1461 return NULL;
Paul Cercueil0b2ce712014-02-17 15:04:18 +01001462}