blob: f555d9206a2ae5916b8a45a29f55d02368268dd1 [file] [log] [blame]
Paul Cercueilbb4401d2014-02-28 16:10:49 +01001/*
2 * libiio - Library for interfacing industrial I/O (IIO) devices
3 *
4 * Copyright (C) 2014 Analog Devices, Inc.
5 * Author: Paul Cercueil <paul.cercueil@analog.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * */
18
Paul Cercueil0b2ce712014-02-17 15:04:18 +010019#include "iio-private.h"
20
Paul Cercueil167d3112014-02-18 12:23:53 +010021#include <errno.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010022#include <stdio.h>
Paul Cercueil167d3112014-02-18 12:23:53 +010023#include <string.h>
Paul Cercueil0b2ce712014-02-17 15:04:18 +010024
Paul Cercueil47d23d02014-06-05 14:46:20 +020025/* Include <winsock2.h> or <arpa/inet.h> for ntohl() */
26#ifdef _WIN32
27#include <winsock2.h>
28#else
29#include <arpa/inet.h>
30#endif
31
Paul Cercueilb0408c22014-06-26 09:38:43 +020032/* winsock2.h defines ERROR, we don't want that */
33#undef ERROR
34
35#include "debug.h"
36
37#ifndef _WIN32
38#define _strdup strdup
39#endif
40
Paul Cercueil42d12352014-05-05 16:11:58 +020041static char *get_attr_xml(struct iio_channel_attr *attr, size_t *length)
Paul Cercueil42090d12014-02-24 12:32:23 +010042{
Paul Cercueil42d12352014-05-05 16:11:58 +020043 char *str;
44 size_t len = strlen(attr->name) + sizeof("<attribute name=\"\" />");
45 if (attr->filename)
46 len += strlen(attr->filename) + sizeof("filename=\"\"");
47
48 str = malloc(len);
Paul Cercueil42090d12014-02-24 12:32:23 +010049 if (!str) {
50 ERROR("Unable to allocate memory\n");
51 return NULL;
52 }
53
54 *length = len - 1; /* Skip the \0 */
Paul Cercueil42d12352014-05-05 16:11:58 +020055 if (attr->filename)
56 snprintf(str, len, "<attribute name=\"%s\" filename=\"%s\" />",
57 attr->name, attr->filename);
58 else
59 snprintf(str, len, "<attribute name=\"%s\" />", attr->name);
Paul Cercueil42090d12014-02-24 12:32:23 +010060 return str;
61}
62
Paul Cercueila7e80022014-06-11 11:41:26 +020063static char * get_scan_element(const struct iio_channel *chn, size_t *length)
64{
65 char buf[1024], *str;
Michael Hennerichfa3c6f62014-08-13 11:21:23 +020066 char processed = (chn->format.is_fully_defined ? 'A' - 'a' : 0);
67
Paul Cercueila7e80022014-06-11 11:41:26 +020068 snprintf(buf, sizeof(buf), "<scan-element index=\"%li\" "
Paul Cercueil6e4bc7a2014-06-11 14:33:48 +020069 "format=\"%ce:%c%u/%u&gt;&gt;%u\" />",
Paul Cercueila7e80022014-06-11 11:41:26 +020070 chn->index, chn->format.is_be ? 'b' : 'l',
Michael Hennerichfa3c6f62014-08-13 11:21:23 +020071 chn->format.is_signed ? 's' + processed : 'u' + processed,
Paul Cercueila7e80022014-06-11 11:41:26 +020072 chn->format.bits, chn->format.length,
73 chn->format.shift);
74
75 if (chn->format.with_scale) {
76 char *ptr = strrchr(buf, '\0');
77 snprintf(ptr - 2, buf + sizeof(buf) - ptr + 2,
Paul Cercueil0b551c82014-06-12 09:48:24 +020078 "scale=\"%lf\" />", chn->format.scale);
Paul Cercueila7e80022014-06-11 11:41:26 +020079 }
80
Paul Cercueilb0408c22014-06-26 09:38:43 +020081 str = _strdup(buf);
Paul Cercueila7e80022014-06-11 11:41:26 +020082 if (!str)
83 ERROR("Unable to allocate memory\n");
84 else
85 *length = strlen(str);
86 return str;
87}
88
Paul Cercueil42090d12014-02-24 12:32:23 +010089/* Returns a string containing the XML representation of this channel */
90char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
91{
92 size_t len = sizeof("<channel id=\"\" name=\"\" "
Paul Cercueila7e80022014-06-11 11:41:26 +020093 "type=\"output\" ></channel>")
Paul Cercueil8c29e412014-04-07 09:46:45 +020094 + strlen(chn->id) + (chn->name ? strlen(chn->name) : 0);
Paul Cercueila7e80022014-06-11 11:41:26 +020095 char *ptr, *str, **attrs, *scan_element = NULL;
96 size_t *attrs_len, scan_element_len = 0;
Paul Cercueil42090d12014-02-24 12:32:23 +010097 unsigned int i;
98
Paul Cercueila7e80022014-06-11 11:41:26 +020099 if (chn->is_scan_element) {
100 scan_element = get_scan_element(chn, &scan_element_len);
Paul Cercueila7e80022014-06-11 11:41:26 +0200101 if (!scan_element)
102 return NULL;
Paul Cercueilb0408c22014-06-26 09:38:43 +0200103 else
104 len += scan_element_len;
Paul Cercueila7e80022014-06-11 11:41:26 +0200105 }
106
Paul Cercueil5822ab62014-04-04 13:29:17 +0200107 attrs_len = malloc(chn->nb_attrs * sizeof(*attrs_len));
108 if (!attrs_len)
Paul Cercueila7e80022014-06-11 11:41:26 +0200109 goto err_free_scan_element;
Paul Cercueil5822ab62014-04-04 13:29:17 +0200110
111 attrs = malloc(chn->nb_attrs * sizeof(*attrs));
112 if (!attrs)
113 goto err_free_attrs_len;
114
Paul Cercueil42090d12014-02-24 12:32:23 +0100115 for (i = 0; i < chn->nb_attrs; i++) {
Paul Cercueil42d12352014-05-05 16:11:58 +0200116 char *xml = get_attr_xml(&chn->attrs[i], &attrs_len[i]);
Paul Cercueil42090d12014-02-24 12:32:23 +0100117 if (!xml)
118 goto err_free_attrs;
119 attrs[i] = xml;
120 len += attrs_len[i];
121 }
122
Paul Cercueil42090d12014-02-24 12:32:23 +0100123 str = malloc(len);
124 if (!str)
125 goto err_free_attrs;
126
Paul Cercueil8c29e412014-04-07 09:46:45 +0200127 snprintf(str, len, "<channel id=\"%s\"", chn->id);
Paul Cercueil42090d12014-02-24 12:32:23 +0100128 ptr = strrchr(str, '\0');
129
130 if (chn->name) {
131 sprintf(ptr, " name=\"%s\"", chn->name);
132 ptr = strrchr(ptr, '\0');
133 }
134
Paul Cercueila7e80022014-06-11 11:41:26 +0200135 sprintf(ptr, " type=\"%s\" >", chn->is_output ? "output" : "input");
Paul Cercueil42090d12014-02-24 12:32:23 +0100136 ptr = strrchr(ptr, '\0');
137
Paul Cercueila7e80022014-06-11 11:41:26 +0200138 if (chn->is_scan_element) {
139 strcpy(ptr, scan_element);
140 ptr += scan_element_len;
141 }
142
Paul Cercueil42090d12014-02-24 12:32:23 +0100143 for (i = 0; i < chn->nb_attrs; i++) {
144 strcpy(ptr, attrs[i]);
145 ptr += attrs_len[i];
146 free(attrs[i]);
147 }
148
Paul Cercueila7e80022014-06-11 11:41:26 +0200149 free(scan_element);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200150 free(attrs);
151 free(attrs_len);
Paul Cercueil8c29e412014-04-07 09:46:45 +0200152
Paul Cercueil42090d12014-02-24 12:32:23 +0100153 strcpy(ptr, "</channel>");
154 *length = ptr - str + sizeof("</channel>") - 1;
155 return str;
156
157err_free_attrs:
158 while (i--)
159 free(attrs[i]);
Paul Cercueil5822ab62014-04-04 13:29:17 +0200160 free(attrs);
161err_free_attrs_len:
162 free(attrs_len);
Paul Cercueila7e80022014-06-11 11:41:26 +0200163err_free_scan_element:
164 if (chn->is_scan_element)
165 free(scan_element);
Paul Cercueil42090d12014-02-24 12:32:23 +0100166 return NULL;
167}
168
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100169const char * iio_channel_get_id(const struct iio_channel *chn)
170{
171 return chn->id;
172}
173
174const char * iio_channel_get_name(const struct iio_channel *chn)
175{
176 return chn->name;
177}
178
Paul Cercueil35a01312014-02-20 10:56:57 +0100179bool iio_channel_is_output(const struct iio_channel *chn)
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100180{
Paul Cercueil35a01312014-02-20 10:56:57 +0100181 return chn->is_output;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100182}
183
Paul Cercueil85aaf482014-04-24 16:39:09 +0200184bool iio_channel_is_scan_element(const struct iio_channel *chn)
185{
186 return chn->is_scan_element;
187}
188
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100189unsigned int iio_channel_get_attrs_count(const struct iio_channel *chn)
190{
191 return chn->nb_attrs;
192}
193
194const char * iio_channel_get_attr(const struct iio_channel *chn,
195 unsigned int index)
196{
197 if (index >= chn->nb_attrs)
198 return NULL;
199 else
Paul Cercueilb34e0222014-05-05 15:32:38 +0200200 return chn->attrs[index].name;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100201}
202
Paul Cercueil4f838d02014-03-28 11:26:15 +0100203const char * iio_channel_find_attr(const struct iio_channel *chn,
204 const char *name)
205{
206 unsigned int i;
207 for (i = 0; i < chn->nb_attrs; i++) {
Paul Cercueilb34e0222014-05-05 15:32:38 +0200208 const char *attr = chn->attrs[i].name;
Paul Cercueil4f838d02014-03-28 11:26:15 +0100209 if (!strcmp(attr, name))
210 return attr;
211 }
212 return NULL;
213}
214
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100215ssize_t iio_channel_attr_read(const struct iio_channel *chn,
216 const char *attr, char *dst, size_t len)
217{
Paul Cercueil6a013602014-02-19 12:37:39 +0100218 if (chn->dev->ctx->ops->read_channel_attr)
219 return chn->dev->ctx->ops->read_channel_attr(chn,
220 attr, dst, len);
221 else
222 return -ENOSYS;
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100223}
224
Paul Cercueilcecda352014-05-06 18:14:29 +0200225ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn,
226 const char *attr, const void *src, size_t len)
227{
228 if (chn->dev->ctx->ops->write_channel_attr)
229 return chn->dev->ctx->ops->write_channel_attr(chn,
230 attr, src, len);
231 else
232 return -ENOSYS;
233}
234
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100235ssize_t iio_channel_attr_write(const struct iio_channel *chn,
236 const char *attr, const char *src)
237{
Paul Cercueilcecda352014-05-06 18:14:29 +0200238 return iio_channel_attr_write_raw(chn, attr, src, strlen(src) + 1);
Paul Cercueil0b2ce712014-02-17 15:04:18 +0100239}
Paul Cercueil00236242014-02-18 15:09:06 +0100240
Paul Cercueild96e61f2014-03-07 16:13:37 +0100241void iio_channel_set_data(struct iio_channel *chn, void *data)
242{
243 chn->userdata = data;
244}
245
246void * iio_channel_get_data(const struct iio_channel *chn)
247{
248 return chn->userdata;
249}
250
Paul Cercueilae88fde2014-03-12 11:47:10 +0100251long iio_channel_get_index(const struct iio_channel *chn)
252{
253 return chn->index;
254}
255
Paul Cercueileb5ce552014-03-14 17:05:35 +0100256const struct iio_data_format * iio_channel_get_data_format(
257 const struct iio_channel *chn)
258{
259 return &chn->format;
260}
261
Paul Cercueil9b5827e2014-03-12 15:31:51 +0100262bool iio_channel_is_enabled(const struct iio_channel *chn)
263{
Paul Cercueilff778232014-03-24 14:23:08 +0100264 return chn->index >= 0 && chn->dev->mask &&
265 TEST_BIT(chn->dev->mask, chn->index);
Paul Cercueil9b5827e2014-03-12 15:31:51 +0100266}
267
268void iio_channel_enable(struct iio_channel *chn)
269{
Paul Cercueila2beb4c2014-04-24 17:23:21 +0200270 if (chn->is_scan_element && chn->index >= 0 && chn->dev->mask)
Paul Cercueilff778232014-03-24 14:23:08 +0100271 SET_BIT(chn->dev->mask, chn->index);
Paul Cercueil9b5827e2014-03-12 15:31:51 +0100272}
273
274void iio_channel_disable(struct iio_channel *chn)
275{
Paul Cercueilff778232014-03-24 14:23:08 +0100276 if (chn->index >= 0 && chn->dev->mask)
277 CLEAR_BIT(chn->dev->mask, chn->index);
Paul Cercueil9b5827e2014-03-12 15:31:51 +0100278}
279
Paul Cercueil00236242014-02-18 15:09:06 +0100280void free_channel(struct iio_channel *chn)
281{
282 unsigned int i;
Paul Cercueil42d12352014-05-05 16:11:58 +0200283 for (i = 0; i < chn->nb_attrs; i++) {
284 free(chn->attrs[i].name);
285 free(chn->attrs[i].filename);
286 }
Paul Cercueil00236242014-02-18 15:09:06 +0100287 if (chn->nb_attrs)
288 free(chn->attrs);
289 if (chn->name)
Paul Cercueil42d12352014-05-05 16:11:58 +0200290 free(chn->name);
Paul Cercueil00236242014-02-18 15:09:06 +0100291 if (chn->id)
Paul Cercueil42d12352014-05-05 16:11:58 +0200292 free(chn->id);
Paul Cercueil00236242014-02-18 15:09:06 +0100293 free(chn);
294}
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100295
296static void byte_swap(uint8_t *dst, const uint8_t *src, size_t len)
297{
298 unsigned int i;
299 for (i = 0; i < len; i++)
300 dst[i] = src[len - i - 1];
301}
302
Paul Cercueild840d4c2014-04-07 19:38:58 +0200303static void shift_bits(uint8_t *dst, size_t shift, size_t len, bool left)
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100304{
305 unsigned int i;
306 size_t shift_bytes = shift / 8;
307 shift %= 8;
308
Paul Cercueil5ecb8ac2014-04-04 12:38:21 +0200309#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Paul Cercueild840d4c2014-04-07 19:38:58 +0200310 if (!left)
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100311#else
Paul Cercueild840d4c2014-04-07 19:38:58 +0200312 if (left)
313#endif
314 {
315 if (shift_bytes) {
316 memmove(dst, dst + shift_bytes, len - shift_bytes);
317 memset(dst + len - shift_bytes, 0, shift_bytes);
318 }
319 if (shift) {
320 for (i = 0; i < len; i++) {
321#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
322 dst[i] >>= shift;
323 if (i < len - 1)
324 dst[i] |= dst[i + 1] << (8 - shift);
325#else
326 dst[i] <<= shift;
327 if (i < len - 1)
328 dst[i] |= dst[i + 1] >> (8 - shift);
329#endif
330 }
331 }
332 } else {
333 if (shift_bytes) {
334 memmove(dst + shift_bytes, dst, len - shift_bytes);
335 memset(dst, 0, shift_bytes);
336 }
337 if (shift) {
338 for (i = len; i > 0; i--) {
339#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
340 dst[i - 1] <<= shift;
341 if (i > 1)
342 dst[i - 1] |= dst[i - 2] >> (8 - shift);
343#else
344 dst[i - 1] >>= shift;
345 if (i > 1)
346 dst[i - 1] |= dst[i - 2] << (8 - shift);
347#endif
348 }
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100349 }
350 }
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100351}
352
Paul Cercueil0524d0a2014-03-25 11:57:24 +0100353static void sign_extend(uint8_t *dst, size_t bits, size_t len)
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100354{
355 size_t upper_bytes = ((len * 8 - bits) / 8);
356 uint8_t msb, msb_bit = 1 << ((bits - 1) % 8);
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100357
Paul Cercueil5ecb8ac2014-04-04 12:38:21 +0200358#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100359 msb = dst[len - 1 - upper_bytes] & msb_bit;
360 if (upper_bytes)
361 memset(dst + len - upper_bytes, msb ? 0xff : 0x00, upper_bytes);
362 if (msb)
363 dst[len - 1 - upper_bytes] |= ~(msb_bit - 1);
Lars-Peter Clausena56fb702014-07-30 15:28:39 +0200364 else
365 dst[len - 1 - upper_bytes] &= (msb_bit - 1);
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100366#else
367 /* XXX: untested */
368 msb = dst[upper_bytes] & msb_bit;
369 if (upper_bytes)
370 memset(dst, msb ? 0xff : 0x00, upper_bytes);
371 if (msb)
372 dst[upper_bytes] |= ~(msb_bit - 1);
373#endif
374}
375
Lars-Peter Clausena56fb702014-07-30 15:28:39 +0200376static void mask_upper_bits(uint8_t *dst, size_t bits, size_t len)
377{
Paul Cercueil3ef78fb2014-09-03 11:36:00 +0200378 unsigned int i;
Lars-Peter Clausena56fb702014-07-30 15:28:39 +0200379
Paul Cercueil3ef78fb2014-09-03 11:36:00 +0200380 /* Clear upper bits */
381 if (bits % 8)
382 dst[bits / 8] &= (1 << (bits % 8)) - 1;
383
384 /* Clear upper bytes */
385 for (i = (bits + 7) / 8; i < len; i++)
386 dst[i] = 0;
Lars-Peter Clausena56fb702014-07-30 15:28:39 +0200387}
388
389
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100390void iio_channel_convert(const struct iio_channel *chn,
391 void *dst, const void *src)
392{
393 unsigned int len = chn->format.length / 8;
Paul Cercueil5ecb8ac2014-04-04 12:38:21 +0200394#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100395 bool swap = chn->format.is_be;
396#else
397 bool swap = !chn->format.is_be;
398#endif
399
400 if (len == 1 || !swap)
401 memcpy(dst, src, len);
402 else
403 byte_swap(dst, src, len);
404
405 if (chn->format.shift)
Paul Cercueild840d4c2014-04-07 19:38:58 +0200406 shift_bits(dst, chn->format.shift, len, false);
Michael Hennerichfa3c6f62014-08-13 11:21:23 +0200407
408 if (!chn->format.is_fully_defined) {
409 if (chn->format.is_signed)
410 sign_extend(dst, chn->format.bits, len);
411 else
412 mask_upper_bits(dst, chn->format.bits, len);
413 }
Paul Cercueil2917ffb2014-03-21 15:47:12 +0100414}
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200415
Paul Cercueild840d4c2014-04-07 19:38:58 +0200416void iio_channel_convert_inverse(const struct iio_channel *chn,
417 void *dst, const void *src)
418{
419 unsigned int len = chn->format.length / 8;
Paul Cercueild840d4c2014-04-07 19:38:58 +0200420#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
421 bool swap = chn->format.is_be;
422#else
423 bool swap = !chn->format.is_be;
424#endif
425 uint8_t buf[1024];
426
427 /* Somehow I doubt we will have samples of 8192 bits each. */
428 if (len > sizeof(buf))
429 return;
430
431 memcpy(buf, src, len);
Paul Cercueil3ef78fb2014-09-03 11:36:00 +0200432 mask_upper_bits(buf, chn->format.bits, len);
Paul Cercueild840d4c2014-04-07 19:38:58 +0200433
434 if (chn->format.shift)
435 shift_bits(buf, chn->format.shift, len, true);
436
437 if (len == 1 || !swap)
438 memcpy(dst, buf, len);
439 else
440 byte_swap(dst, buf, len);
441}
442
Paul Cercueil59a7d4c2014-04-07 17:34:53 +0200443size_t iio_channel_read_raw(const struct iio_channel *chn,
444 struct iio_buffer *buf, void *dst, size_t len)
445{
446 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
447 unsigned int length = chn->format.length / 8;
448
449 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
450 src_ptr < (uintptr_t) iio_buffer_end(buf) &&
Paul Cercueil43e36ed2014-04-23 17:05:14 +0200451 dst_ptr + length <= end;
Paul Cercueil59a7d4c2014-04-07 17:34:53 +0200452 src_ptr += iio_buffer_step(buf),
453 dst_ptr += length)
454 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
455 return dst_ptr - (uintptr_t) dst;
456}
457
Paul Cercueilbf221692014-04-07 19:40:53 +0200458size_t iio_channel_read(const struct iio_channel *chn,
459 struct iio_buffer *buf, void *dst, size_t len)
460{
461 uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
462 unsigned int length = chn->format.length / 8;
463
464 for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
465 src_ptr < (uintptr_t) iio_buffer_end(buf) &&
Paul Cercueil43e36ed2014-04-23 17:05:14 +0200466 dst_ptr + length <= end;
Paul Cercueilbf221692014-04-07 19:40:53 +0200467 src_ptr += iio_buffer_step(buf),
468 dst_ptr += length)
469 iio_channel_convert(chn,
470 (void *) dst_ptr, (const void *) src_ptr);
471 return dst_ptr - (uintptr_t) dst;
472}
473
Paul Cercueil59a7d4c2014-04-07 17:34:53 +0200474size_t iio_channel_write_raw(const struct iio_channel *chn,
475 struct iio_buffer *buf, const void *src, size_t len)
476{
477 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
478 unsigned int length = chn->format.length / 8;
479
480 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
481 dst_ptr < (uintptr_t) iio_buffer_end(buf) &&
Paul Cercueil43e36ed2014-04-23 17:05:14 +0200482 src_ptr + length <= end;
Paul Cercueil58fad3b2014-04-11 13:18:16 +0200483 dst_ptr += iio_buffer_step(buf),
484 src_ptr += length)
Paul Cercueil59a7d4c2014-04-07 17:34:53 +0200485 memcpy((void *) dst_ptr, (const void *) src_ptr, length);
486 return src_ptr - (uintptr_t) src;
487}
488
Paul Cercueilbf221692014-04-07 19:40:53 +0200489size_t iio_channel_write(const struct iio_channel *chn,
490 struct iio_buffer *buf, const void *src, size_t len)
491{
492 uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
493 unsigned int length = chn->format.length / 8;
494
495 for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
496 dst_ptr < (uintptr_t) iio_buffer_end(buf) &&
Paul Cercueil43e36ed2014-04-23 17:05:14 +0200497 src_ptr + length <= end;
Paul Cercueil58fad3b2014-04-11 13:18:16 +0200498 dst_ptr += iio_buffer_step(buf),
499 src_ptr += length)
Paul Cercueilbf221692014-04-07 19:40:53 +0200500 iio_channel_convert_inverse(chn,
501 (void *) dst_ptr, (const void *) src_ptr);
502 return src_ptr - (uintptr_t) src;
503}
504
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200505int iio_channel_attr_read_longlong(const struct iio_channel *chn,
506 const char *attr, long long *val)
507{
508 char *end, buf[1024];
509 long long value;
510 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
511 if (ret < 0)
512 return (int) ret;
513
514 value = strtoll(buf, &end, 0);
515 if (end == buf)
516 return -EINVAL;
517 *val = value;
518 return 0;
519}
520
521int iio_channel_attr_read_bool(const struct iio_channel *chn,
522 const char *attr, bool *val)
523{
524 long long value;
525 int ret = iio_channel_attr_read_longlong(chn, attr, &value);
526 if (ret < 0)
527 return ret;
528
529 *val = !!value;
530 return 0;
531}
532
533int iio_channel_attr_read_double(const struct iio_channel *chn,
534 const char *attr, double *val)
535{
536 char *end, buf[1024];
537 double value;
538 ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
539 if (ret < 0)
540 return (int) ret;
541
542 value = strtod(buf, &end);
543 if (end == buf)
544 return -EINVAL;
545 *val = value;
546 return 0;
547}
548
549int iio_channel_attr_write_longlong(const struct iio_channel *chn,
550 const char *attr, long long val)
551{
Paul Cercueil5e586222014-06-04 10:24:37 +0200552 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200553 char buf[1024];
554 snprintf(buf, sizeof(buf), "%lld", val);
Paul Cercueil5e586222014-06-04 10:24:37 +0200555 ret = iio_channel_attr_write(chn, attr, buf);
556 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200557}
558
559int iio_channel_attr_write_double(const struct iio_channel *chn,
560 const char *attr, double val)
561{
Paul Cercueil5e586222014-06-04 10:24:37 +0200562 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200563 char buf[1024];
564 snprintf(buf, sizeof(buf), "%lf", val);
Paul Cercueil5e586222014-06-04 10:24:37 +0200565 ret = iio_channel_attr_write(chn, attr, buf);
566 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200567}
568
569int iio_channel_attr_write_bool(const struct iio_channel *chn,
570 const char *attr, bool val)
571{
Paul Cercueil5e586222014-06-04 10:24:37 +0200572 ssize_t ret;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200573 if (val)
Paul Cercueil5e586222014-06-04 10:24:37 +0200574 ret = iio_channel_attr_write_raw(chn, attr, "1", 2);
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200575 else
Paul Cercueil5e586222014-06-04 10:24:37 +0200576 ret = iio_channel_attr_write_raw(chn, attr, "0", 2);
577 return ret < 0 ? ret : 0;
Paul Cercueil3dbd47d2014-03-31 11:19:40 +0200578}
Paul Cercueil6f8dbd42014-05-05 17:05:59 +0200579
580const char * iio_channel_attr_get_filename(
581 const struct iio_channel *chn, const char *attr)
582{
583 unsigned int i;
584 for (i = 0; i < chn->nb_attrs; i++) {
585 if (!strcmp(chn->attrs[i].name, attr))
586 return chn->attrs[i].filename;
587 }
588 return NULL;
589}
Paul Cercueil47d23d02014-06-05 14:46:20 +0200590
591int iio_channel_attr_read_all(struct iio_channel *chn,
592 int (*cb)(struct iio_channel *chn,
593 const char *attr, const char *val, size_t len, void *d),
594 void *data)
595{
596 int ret;
597 char *buf, *ptr;
598 unsigned int i;
599
600 /* We need a big buffer here; 1 MiB should be enough */
601 buf = malloc(0x100000);
602 if (!buf)
603 return -ENOMEM;
604
605 ret = (int) iio_channel_attr_read(chn, NULL, buf, 0x100000);
606 if (ret < 0)
607 goto err_free_buf;
608
609 ptr = buf;
610
611 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
612 const char *attr = iio_channel_get_attr(chn, i);
613 int32_t len = (int32_t) ntohl(*(uint32_t *) ptr);
614
615 ptr += 4;
616 if (len > 0) {
617 ret = cb(chn, attr, ptr, (size_t) len, data);
618 if (ret < 0)
619 goto err_free_buf;
620
621 if (len & 0x3)
622 len = ((len >> 2) + 1) << 2;
623 ptr += len;
624 }
625 }
626
627err_free_buf:
628 free(buf);
629 return ret < 0 ? ret : 0;
630}
631
632int iio_channel_attr_write_all(struct iio_channel *chn,
633 ssize_t (*cb)(struct iio_channel *chn,
634 const char *attr, void *buf, size_t len, void *d),
635 void *data)
636{
637 char *buf, *ptr;
638 unsigned int i;
639 size_t len = 0x100000;
640 int ret;
641
642 /* We need a big buffer here; 1 MiB should be enough */
643 buf = malloc(len);
644 if (!buf)
645 return -ENOMEM;
646
647 ptr = buf;
648
649 for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
650 const char *attr = iio_channel_get_attr(chn, i);
651
652 ret = (int) cb(chn, attr, ptr + 4, len - 4, data);
653 if (ret < 0)
654 goto err_free_buf;
655
656 *(int32_t *) ptr = (int32_t) htonl((uint32_t) ret);
657 ptr += 4;
658 len -= 4;
659
660 if (ret > 0) {
661 if (ret & 0x3)
662 ret = ((ret >> 2) + 1) << 2;
663 ptr += ret;
664 len -= ret;
665 }
666 }
667
668 ret = (int) iio_channel_attr_write_raw(chn, NULL, buf, ptr - buf);
669
670err_free_buf:
671 free(buf);
672 return ret < 0 ? ret : 0;
673}