1 /*
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 
19 #include "debug.h"
20 #include "iio-private.h"
21 
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 static const char * const iio_chan_type_name_spec[] = {
27 	[IIO_VOLTAGE] = "voltage",
28 	[IIO_CURRENT] = "current",
29 	[IIO_POWER] = "power",
30 	[IIO_ACCEL] = "accel",
31 	[IIO_ANGL_VEL] = "anglvel",
32 	[IIO_MAGN] = "magn",
33 	[IIO_LIGHT] = "illuminance",
34 	[IIO_INTENSITY] = "intensity",
35 	[IIO_PROXIMITY] = "proximity",
36 	[IIO_TEMP] = "temp",
37 	[IIO_INCLI] = "incli",
38 	[IIO_ROT] = "rot",
39 	[IIO_ANGL] = "angl",
40 	[IIO_TIMESTAMP] = "timestamp",
41 	[IIO_CAPACITANCE] = "capacitance",
42 	[IIO_ALTVOLTAGE] = "altvoltage",
43 	[IIO_CCT] = "cct",
44 	[IIO_PRESSURE] = "pressure",
45 	[IIO_HUMIDITYRELATIVE] = "humidityrelative",
46 	[IIO_ACTIVITY] = "activity",
47 	[IIO_STEPS] = "steps",
48 	[IIO_ENERGY] = "energy",
49 	[IIO_DISTANCE] = "distance",
50 	[IIO_VELOCITY] = "velocity",
51 	[IIO_CONCENTRATION] = "concentration",
52 	[IIO_RESISTANCE] = "resistance",
53 	[IIO_PH] = "ph",
54 	[IIO_UVINDEX] = "uvindex",
55 	[IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
56 	[IIO_COUNT] = "count",
57 	[IIO_INDEX] = "index",
58 	[IIO_GRAVITY] = "gravity",
59 	[IIO_POSITIONRELATIVE] = "positionrelative",
60 	[IIO_PHASE] = "phase",
61 	[IIO_MASSCONCENTRATION] = "massconcentration",
62 };
63 
64 static const char * const modifier_names[] = {
65 	[IIO_MOD_X] = "x",
66 	[IIO_MOD_Y] = "y",
67 	[IIO_MOD_Z] = "z",
68 	[IIO_MOD_X_AND_Y] = "x&y",
69 	[IIO_MOD_X_AND_Z] = "x&z",
70 	[IIO_MOD_Y_AND_Z] = "y&z",
71 	[IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
72 	[IIO_MOD_X_OR_Y] = "x|y",
73 	[IIO_MOD_X_OR_Z] = "x|z",
74 	[IIO_MOD_Y_OR_Z] = "y|z",
75 	[IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
76 	[IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
77 	[IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
78 	[IIO_MOD_LIGHT_BOTH] = "both",
79 	[IIO_MOD_LIGHT_IR] = "ir",
80 	[IIO_MOD_LIGHT_CLEAR] = "clear",
81 	[IIO_MOD_LIGHT_RED] = "red",
82 	[IIO_MOD_LIGHT_GREEN] = "green",
83 	[IIO_MOD_LIGHT_BLUE] = "blue",
84 	[IIO_MOD_LIGHT_UV] = "uv",
85 	[IIO_MOD_LIGHT_DUV] = "duv",
86 	[IIO_MOD_QUATERNION] = "quaternion",
87 	[IIO_MOD_TEMP_AMBIENT] = "ambient",
88 	[IIO_MOD_TEMP_OBJECT] = "object",
89 	[IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
90 	[IIO_MOD_NORTH_TRUE] = "from_north_true",
91 	[IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
92 	[IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
93 	[IIO_MOD_RUNNING] = "running",
94 	[IIO_MOD_JOGGING] = "jogging",
95 	[IIO_MOD_WALKING] = "walking",
96 	[IIO_MOD_STILL] = "still",
97 	[IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
98 	[IIO_MOD_I] = "i",
99 	[IIO_MOD_Q] = "q",
100 	[IIO_MOD_CO2] = "co2",
101 	[IIO_MOD_ETHANOL] = "ethanol",
102 	[IIO_MOD_H2] = "h2",
103 	[IIO_MOD_VOC] = "voc",
104 	[IIO_MOD_PM1] = "pm1",
105 	[IIO_MOD_PM2P5] = "pm2p5",
106 	[IIO_MOD_PM4] = "pm4",
107 	[IIO_MOD_PM10] = "pm10",
108 };
109 
110 /*
111  * Looks for a IIO channel modifier at the beginning of the string s. If a
112  * modifier was found the symbolic constant (IIO_MOD_*) is returned, otherwise
113  * IIO_NO_MOD is returned. If a modifier was found len_p will be updated with
114  * the length of the modifier.
115  */
find_channel_modifier(const char * s,size_t * len_p)116 unsigned int find_channel_modifier(const char *s, size_t *len_p)
117 {
118 	unsigned int i;
119 	size_t len;
120 
121 	for (i = 0; i < ARRAY_SIZE(modifier_names); i++) {
122 		if (!modifier_names[i])
123 			continue;
124 		len = strlen(modifier_names[i]);
125 		if (strncmp(s, modifier_names[i], len) == 0 &&
126 				(s[len] == '\0' || s[len] == '_')) {
127 			if (len_p)
128 				*len_p = len;
129 			return i;
130 		}
131 	}
132 
133 	return IIO_NO_MOD;
134 }
135 
136 /*
137  * Initializes all auto-detected fields of the channel struct. Must be called
138  * after the channel has been otherwise fully initialized.
139  */
iio_channel_init_finalize(struct iio_channel * chn)140 void iio_channel_init_finalize(struct iio_channel *chn)
141 {
142 	unsigned int i;
143 	size_t len;
144 	char *mod;
145 
146 	chn->type = IIO_CHAN_TYPE_UNKNOWN;
147 	chn->modifier = IIO_NO_MOD;
148 
149 	for (i = 0; i < ARRAY_SIZE(iio_chan_type_name_spec); i++) {
150 		len = strlen(iio_chan_type_name_spec[i]);
151 		if (strncmp(iio_chan_type_name_spec[i], chn->id, len) != 0)
152 			continue;
153 		/* Type must be followed by one of a '\0', a '_', or a digit */
154 		if (chn->id[len] != '\0' && chn->id[len] != '_' &&
155 				(chn->id[len] < '0' || chn->id[len] > '9'))
156 			continue;
157 
158 		chn->type = (enum iio_chan_type) i;
159 	}
160 
161 	mod = strchr(chn->id, '_');
162 	if (!mod)
163 		return;
164 
165 	mod++;
166 
167 	for (i = 0; i < ARRAY_SIZE(modifier_names); i++) {
168 		if (!modifier_names[i])
169 			continue;
170 		len = strlen(modifier_names[i]);
171 		if (strncmp(modifier_names[i], mod, len) != 0)
172 			continue;
173 
174 		chn->modifier = (enum iio_modifier) i;
175 		break;
176 	}
177 }
178 
get_attr_xml(struct iio_channel_attr * attr,size_t * length)179 static char *get_attr_xml(struct iio_channel_attr *attr, size_t *length)
180 {
181 	char *str;
182 	size_t len;
183 
184 	len = strnlen(attr->name, MAX_ATTR_NAME);
185 	len += sizeof("<attribute name=\"\" />") - 1;
186 
187 	if (attr->filename) {
188 		len += strnlen(attr->filename, NAME_MAX);
189 		len += sizeof(" filename=\"\"") - 1;
190 	}
191 
192 	*length = len; /* just the chars */
193 	len++;         /* room for terminating NULL */
194 	str = malloc(len);
195 	if (!str)
196 		return NULL;
197 
198 	if (attr->filename)
199 		iio_snprintf(str, len, "<attribute name=\"%s\" filename=\"%s\" />",
200 				attr->name, attr->filename);
201 	else
202 		iio_snprintf(str, len, "<attribute name=\"%s\" />", attr->name);
203 
204 	return str;
205 }
206 
get_scan_element(const struct iio_channel * chn,size_t * length)207 static char * get_scan_element(const struct iio_channel *chn, size_t *length)
208 {
209 	char buf[1024], repeat[12] = "", *str;
210 	char processed = (chn->format.is_fully_defined ? 'A' - 'a' : 0);
211 
212 	if (chn->format.repeat > 1)
213 		iio_snprintf(repeat, sizeof(repeat), "X%u", chn->format.repeat);
214 
215 	iio_snprintf(buf, sizeof(buf), "<scan-element index=\"%li\" "
216 			"format=\"%ce:%c%u/%u%s&gt;&gt;%u\" />",
217 			chn->index, chn->format.is_be ? 'b' : 'l',
218 			chn->format.is_signed ? 's' + processed : 'u' + processed,
219 			chn->format.bits, chn->format.length, repeat,
220 			chn->format.shift);
221 
222 	if (chn->format.with_scale) {
223 		char *ptr = strrchr(buf, '\0');
224 		iio_snprintf(ptr - 2, buf + sizeof(buf) - ptr + 2,
225 				"scale=\"%f\" />", chn->format.scale);
226 	}
227 
228 	str = iio_strdup(buf);
229 	if (str)
230 		*length = strlen(str);
231 	return str;
232 }
233 
234 /* Returns a string containing the XML representation of this channel */
iio_channel_get_xml(const struct iio_channel * chn,size_t * length)235 char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
236 {
237 	ssize_t len;
238 	char *ptr, *eptr, *str, **attrs, *scan_element = NULL;
239 	size_t *attrs_len, scan_element_len = 0;
240 	unsigned int i;
241 
242 	len = sizeof("<channel id=\"\" type=\"\" ></channel>") - 1;
243 	len += strnlen(chn->id, MAX_CHN_ID);
244 	len += (chn->is_output ? sizeof("output") : sizeof("input")) - 1;
245 	if (chn->name) {
246 		len += sizeof(" name=\"\"") - 1;
247 		len += strnlen(chn->name, MAX_CHN_NAME);
248 	}
249 
250 	if (chn->is_scan_element) {
251 		scan_element = get_scan_element(chn, &scan_element_len);
252 		if (!scan_element)
253 			return NULL;
254 		else
255 			len += scan_element_len;
256 	}
257 
258 	attrs_len = malloc(chn->nb_attrs * sizeof(*attrs_len));
259 	if (!attrs_len)
260 		goto err_free_scan_element;
261 
262 	attrs = malloc(chn->nb_attrs * sizeof(*attrs));
263 	if (!attrs)
264 		goto err_free_attrs_len;
265 
266 	for (i = 0; i < chn->nb_attrs; i++) {
267 		char *xml = get_attr_xml(&chn->attrs[i], &attrs_len[i]);
268 		if (!xml)
269 			goto err_free_attrs;
270 		attrs[i] = xml;
271 		len += attrs_len[i];
272 	}
273 
274 	len++;  /* room for terminating NULL */
275 	str = malloc(len);
276 	if (!str)
277 		goto err_free_attrs;
278 	ptr = str;
279 	eptr = str + len;
280 
281 	if (len > 0) {
282 		ptr += iio_snprintf(str, len, "<channel id=\"%s\"", chn->id);
283 		len = eptr - ptr;
284 	}
285 
286 	if (chn->name && len > 0) {
287 		ptr += iio_snprintf(ptr, len, " name=\"%s\"", chn->name);
288 		len = eptr - ptr;
289 	}
290 
291 	if (len > 0) {
292 		ptr += iio_snprintf(ptr, len, " type=\"%s\" >", chn->is_output ? "output" : "input");
293 		len = eptr - ptr;
294 	}
295 
296 	if (chn->is_scan_element && len > (ssize_t) scan_element_len) {
297 		memcpy(ptr, scan_element, scan_element_len); /* Flawfinder: ignore */
298 		ptr += scan_element_len;
299 		len -= scan_element_len;
300 	}
301 
302 	for (i = 0; i < chn->nb_attrs; i++) {
303 		if (len > (ssize_t) attrs_len[i]) {
304 			memcpy(ptr, attrs[i], attrs_len[i]); /* Flawfinder: ignore */
305 			ptr += attrs_len[i];
306 			len -= attrs_len[i];
307 		}
308 		free(attrs[i]);
309 	}
310 
311 	free(scan_element);
312 	free(attrs);
313 	free(attrs_len);
314 
315 	if (len > 0) {
316 		ptr += iio_strlcpy(ptr, "</channel>", len);
317 		len -= sizeof("</channel>") -1;
318 	}
319 
320 	*length = ptr - str;
321 
322 	/* NULL char should be left, and that is it */
323 	if (len != 1) {
324 		IIO_ERROR("Internal libIIO error: iio_channel_get_xml str length issue\n");
325 		free(str);
326 		return NULL;
327 	}
328 
329 	return str;
330 
331 err_free_attrs:
332 	while (i--)
333 		free(attrs[i]);
334 	free(attrs);
335 err_free_attrs_len:
336 	free(attrs_len);
337 err_free_scan_element:
338 	if (chn->is_scan_element)
339 		free(scan_element);
340 	return NULL;
341 }
342 
iio_channel_get_id(const struct iio_channel * chn)343 const char * iio_channel_get_id(const struct iio_channel *chn)
344 {
345 	return chn->id;
346 }
347 
iio_channel_get_name(const struct iio_channel * chn)348 const char * iio_channel_get_name(const struct iio_channel *chn)
349 {
350 	return chn->name;
351 }
352 
iio_channel_is_output(const struct iio_channel * chn)353 bool iio_channel_is_output(const struct iio_channel *chn)
354 {
355 	return chn->is_output;
356 }
357 
iio_channel_is_scan_element(const struct iio_channel * chn)358 bool iio_channel_is_scan_element(const struct iio_channel *chn)
359 {
360 	return chn->is_scan_element;
361 }
362 
iio_channel_get_modifier(const struct iio_channel * chn)363 enum iio_modifier iio_channel_get_modifier(const struct iio_channel *chn)
364 {
365 	return chn->modifier;
366 }
367 
iio_channel_get_type(const struct iio_channel * chn)368 enum iio_chan_type iio_channel_get_type(const struct iio_channel *chn)
369 {
370 	return chn->type;
371 }
372 
iio_channel_get_attrs_count(const struct iio_channel * chn)373 unsigned int iio_channel_get_attrs_count(const struct iio_channel *chn)
374 {
375 	return chn->nb_attrs;
376 }
377 
iio_channel_get_attr(const struct iio_channel * chn,unsigned int index)378 const char * iio_channel_get_attr(const struct iio_channel *chn,
379 		unsigned int index)
380 {
381 	if (index >= chn->nb_attrs)
382 		return NULL;
383 	else
384 		return chn->attrs[index].name;
385 }
386 
iio_channel_find_attr(const struct iio_channel * chn,const char * name)387 const char * iio_channel_find_attr(const struct iio_channel *chn,
388 		const char *name)
389 {
390 	unsigned int i;
391 	for (i = 0; i < chn->nb_attrs; i++) {
392 		const char *attr = chn->attrs[i].name;
393 		if (!strcmp(attr, name))
394 			return attr;
395 	}
396 	return NULL;
397 }
398 
iio_channel_attr_read(const struct iio_channel * chn,const char * attr,char * dst,size_t len)399 ssize_t iio_channel_attr_read(const struct iio_channel *chn,
400 		const char *attr, char *dst, size_t len)
401 {
402 	if (chn->dev->ctx->ops->read_channel_attr)
403 		return chn->dev->ctx->ops->read_channel_attr(chn,
404 				attr, dst, len);
405 	else
406 		return -ENOSYS;
407 }
408 
iio_channel_attr_write_raw(const struct iio_channel * chn,const char * attr,const void * src,size_t len)409 ssize_t iio_channel_attr_write_raw(const struct iio_channel *chn,
410 		const char *attr, const void *src, size_t len)
411 {
412 	if (chn->dev->ctx->ops->write_channel_attr)
413 		return chn->dev->ctx->ops->write_channel_attr(chn,
414 				attr, src, len);
415 	else
416 		return -ENOSYS;
417 }
418 
iio_channel_attr_write(const struct iio_channel * chn,const char * attr,const char * src)419 ssize_t iio_channel_attr_write(const struct iio_channel *chn,
420 		const char *attr, const char *src)
421 {
422 	return iio_channel_attr_write_raw(chn, attr, src, strlen(src) + 1);
423 }
424 
iio_channel_set_data(struct iio_channel * chn,void * data)425 void iio_channel_set_data(struct iio_channel *chn, void *data)
426 {
427 	chn->userdata = data;
428 }
429 
iio_channel_get_data(const struct iio_channel * chn)430 void * iio_channel_get_data(const struct iio_channel *chn)
431 {
432 	return chn->userdata;
433 }
434 
iio_channel_get_index(const struct iio_channel * chn)435 long iio_channel_get_index(const struct iio_channel *chn)
436 {
437 	return chn->index;
438 }
439 
iio_channel_get_data_format(const struct iio_channel * chn)440 const struct iio_data_format * iio_channel_get_data_format(
441 		const struct iio_channel *chn)
442 {
443 	return &chn->format;
444 }
445 
iio_channel_is_enabled(const struct iio_channel * chn)446 bool iio_channel_is_enabled(const struct iio_channel *chn)
447 {
448 	return chn->index >= 0 && chn->dev->mask &&
449 		TEST_BIT(chn->dev->mask, chn->number);
450 }
451 
iio_channel_enable(struct iio_channel * chn)452 void iio_channel_enable(struct iio_channel *chn)
453 {
454 	if (chn->is_scan_element && chn->index >= 0 && chn->dev->mask)
455 		SET_BIT(chn->dev->mask, chn->number);
456 }
457 
iio_channel_disable(struct iio_channel * chn)458 void iio_channel_disable(struct iio_channel *chn)
459 {
460 	if (chn->index >= 0 && chn->dev->mask)
461 		CLEAR_BIT(chn->dev->mask, chn->number);
462 }
463 
free_channel(struct iio_channel * chn)464 void free_channel(struct iio_channel *chn)
465 {
466 	size_t i;
467 	for (i = 0; i < chn->nb_attrs; i++) {
468 		free(chn->attrs[i].name);
469 		free(chn->attrs[i].filename);
470 	}
471 	if (chn->nb_attrs)
472 		free(chn->attrs);
473 	if (chn->name)
474 		free(chn->name);
475 	if (chn->id)
476 		free(chn->id);
477 	free(chn);
478 }
479 
byte_swap(uint8_t * dst,const uint8_t * src,size_t len)480 static void byte_swap(uint8_t *dst, const uint8_t *src, size_t len)
481 {
482 	size_t i;
483 	for (i = 0; i < len; i++)
484 		dst[i] = src[len - i - 1];
485 }
486 
shift_bits(uint8_t * dst,size_t shift,size_t len,bool left)487 static void shift_bits(uint8_t *dst, size_t shift, size_t len, bool left)
488 {
489 	size_t i, shift_bytes = shift / 8;
490 	shift %= 8;
491 
492 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
493 	if (!left)
494 #else
495 	if (left)
496 #endif
497 	{
498 		if (shift_bytes) {
499 			memmove(dst, dst + shift_bytes, len - shift_bytes);
500 			memset(dst + len - shift_bytes, 0, shift_bytes);
501 		}
502 		if (shift) {
503 			for (i = 0; i < len; i++) {
504 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
505 				dst[i] >>= shift;
506 				if (i < len - 1)
507 					dst[i] |= dst[i + 1] << (8 - shift);
508 #else
509 				dst[i] <<= shift;
510 				if (i < len - 1)
511 					dst[i] |= dst[i + 1] >> (8 - shift);
512 #endif
513 			}
514 		}
515 	} else {
516 		if (shift_bytes) {
517 			memmove(dst + shift_bytes, dst, len - shift_bytes);
518 			memset(dst, 0, shift_bytes);
519 		}
520 		if (shift) {
521 			for (i = len; i > 0; i--) {
522 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
523 				dst[i - 1] <<= shift;
524 				if (i > 1)
525 					dst[i - 1] |= dst[i - 2] >> (8 - shift);
526 #else
527 				dst[i - 1] >>= shift;
528 				if (i > 1)
529 					dst[i - 1] |= dst[i - 2] << (8 - shift);
530 #endif
531 			}
532 		}
533 	}
534 }
535 
sign_extend(uint8_t * dst,size_t bits,size_t len)536 static void sign_extend(uint8_t *dst, size_t bits, size_t len)
537 {
538 	size_t upper_bytes = ((len * 8 - bits) / 8);
539 	uint8_t msb, msb_bit = 1 << ((bits - 1) % 8);
540 
541 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
542 	msb = dst[len - 1 - upper_bytes] & msb_bit;
543 	if (upper_bytes)
544 		memset(dst + len - upper_bytes, msb ? 0xff : 0x00, upper_bytes);
545 	if (msb)
546 		dst[len - 1 - upper_bytes] |= ~(msb_bit - 1);
547 	else
548 		dst[len - 1 - upper_bytes] &= (msb_bit - 1);
549 #else
550 	/* XXX: untested */
551 	msb = dst[upper_bytes] & msb_bit;
552 	if (upper_bytes)
553 		memset(dst, msb ? 0xff : 0x00, upper_bytes);
554 	if (msb)
555 		dst[upper_bytes] |= ~(msb_bit - 1);
556 #endif
557 }
558 
mask_upper_bits(uint8_t * dst,size_t bits,size_t len)559 static void mask_upper_bits(uint8_t *dst, size_t bits, size_t len)
560 {
561 	size_t i;
562 
563 	/* Clear upper bits */
564 	if (bits % 8)
565 		dst[bits / 8] &= (1 << (bits % 8)) - 1;
566 
567 	/* Clear upper bytes */
568 	for (i = (bits + 7) / 8; i < len; i++)
569 		dst[i] = 0;
570 }
571 
572 
iio_channel_convert(const struct iio_channel * chn,void * dst,const void * src)573 void iio_channel_convert(const struct iio_channel *chn,
574 		void *dst, const void *src)
575 {
576 	uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst;
577 	unsigned int len = chn->format.length / 8;
578 	ptrdiff_t end = len * chn->format.repeat;
579 	uintptr_t end_ptr = src_ptr + end;
580 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
581 	bool swap = chn->format.is_be;
582 #else
583 	bool swap = !chn->format.is_be;
584 #endif
585 
586 	for (src_ptr = (uintptr_t) src; src_ptr < end_ptr;
587 			src_ptr += len, dst_ptr += len) {
588 		if (len == 1 || !swap)
589 			memcpy((void *) dst_ptr, (const void *) src_ptr, len);
590 		else
591 			byte_swap((void *) dst_ptr, (const void *) src_ptr,
592 				len);
593 
594 		if (chn->format.shift)
595 			shift_bits((void *) dst_ptr, chn->format.shift, len,
596 				false);
597 
598 		if (!chn->format.is_fully_defined) {
599 			if (chn->format.is_signed)
600 				sign_extend((void *) dst_ptr,
601 					chn->format.bits, len);
602 			else
603 				mask_upper_bits((void *) dst_ptr,
604 					chn->format.bits, len);
605 		}
606 	}
607 }
608 
iio_channel_convert_inverse(const struct iio_channel * chn,void * dst,const void * src)609 void iio_channel_convert_inverse(const struct iio_channel *chn,
610 		void *dst, const void *src)
611 {
612 	uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst;
613 	unsigned int len = chn->format.length / 8;
614 	ptrdiff_t end = len * chn->format.repeat;
615 	uintptr_t end_ptr = dst_ptr + end;
616 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
617 	bool swap = chn->format.is_be;
618 #else
619 	bool swap = !chn->format.is_be;
620 #endif
621 	uint8_t buf[1024];
622 
623 	/* Somehow I doubt we will have samples of 8192 bits each. */
624 	if (len > sizeof(buf))
625 		return;
626 
627 	for (dst_ptr = (uintptr_t) dst; dst_ptr < end_ptr;
628 			src_ptr += len, dst_ptr += len) {
629 		memcpy(buf, (const void *) src_ptr, len);
630 		mask_upper_bits(buf, chn->format.bits, len);
631 
632 		if (chn->format.shift)
633 			shift_bits(buf, chn->format.shift, len, true);
634 
635 		if (len == 1 || !swap)
636 			memcpy((void *) dst_ptr, buf, len);
637 		else
638 			byte_swap((void *) dst_ptr, buf, len);
639 	}
640 }
641 
iio_channel_read_raw(const struct iio_channel * chn,struct iio_buffer * buf,void * dst,size_t len)642 size_t iio_channel_read_raw(const struct iio_channel *chn,
643 		struct iio_buffer *buf, void *dst, size_t len)
644 {
645 	uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
646 	unsigned int length = chn->format.length / 8 * chn->format.repeat;
647 	uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
648 	ptrdiff_t buf_step = iio_buffer_step(buf);
649 
650 	for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
651 			src_ptr < buf_end && dst_ptr + length <= end;
652 			src_ptr += buf_step, dst_ptr += length)
653 		memcpy((void *) dst_ptr, (const void *) src_ptr, length);
654 	return dst_ptr - (uintptr_t) dst;
655 }
656 
iio_channel_read(const struct iio_channel * chn,struct iio_buffer * buf,void * dst,size_t len)657 size_t iio_channel_read(const struct iio_channel *chn,
658 		struct iio_buffer *buf, void *dst, size_t len)
659 {
660 	uintptr_t src_ptr, dst_ptr = (uintptr_t) dst, end = dst_ptr + len;
661 	unsigned int length = chn->format.length / 8 * chn->format.repeat;
662 	uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
663 	ptrdiff_t buf_step = iio_buffer_step(buf);
664 
665 	for (src_ptr = (uintptr_t) iio_buffer_first(buf, chn);
666 			src_ptr < buf_end && dst_ptr + length <= end;
667 			src_ptr += buf_step, dst_ptr += length)
668 		iio_channel_convert(chn,
669 				(void *) dst_ptr, (const void *) src_ptr);
670 	return dst_ptr - (uintptr_t) dst;
671 }
672 
iio_channel_write_raw(const struct iio_channel * chn,struct iio_buffer * buf,const void * src,size_t len)673 size_t iio_channel_write_raw(const struct iio_channel *chn,
674 		struct iio_buffer *buf, const void *src, size_t len)
675 {
676 	uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
677 	unsigned int length = chn->format.length / 8 * chn->format.repeat;
678 	uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
679 	ptrdiff_t buf_step = iio_buffer_step(buf);
680 
681 	for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
682 			dst_ptr < buf_end && src_ptr + length <= end;
683 			dst_ptr += buf_step, src_ptr += length)
684 		memcpy((void *) dst_ptr, (const void *) src_ptr, length);
685 	return src_ptr - (uintptr_t) src;
686 }
687 
iio_channel_write(const struct iio_channel * chn,struct iio_buffer * buf,const void * src,size_t len)688 size_t iio_channel_write(const struct iio_channel *chn,
689 		struct iio_buffer *buf, const void *src, size_t len)
690 {
691 	uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
692 	unsigned int length = chn->format.length / 8 * chn->format.repeat;
693 	uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
694 	ptrdiff_t buf_step = iio_buffer_step(buf);
695 
696 	for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
697 			dst_ptr < buf_end && src_ptr + length <= end;
698 			dst_ptr += buf_step, src_ptr += length)
699 		iio_channel_convert_inverse(chn,
700 				(void *) dst_ptr, (const void *) src_ptr);
701 	return src_ptr - (uintptr_t) src;
702 }
703 
iio_channel_attr_read_longlong(const struct iio_channel * chn,const char * attr,long long * val)704 int iio_channel_attr_read_longlong(const struct iio_channel *chn,
705 		const char *attr, long long *val)
706 {
707 	char *end, buf[1024];
708 	long long value;
709 	ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
710 	if (ret < 0)
711 		return (int) ret;
712 
713 	errno = 0;
714 	value = strtoll(buf, &end, 0);
715 	if (end == buf || errno == ERANGE)
716 		return -EINVAL;
717 	*val = value;
718 	return 0;
719 }
720 
iio_channel_attr_read_bool(const struct iio_channel * chn,const char * attr,bool * val)721 int iio_channel_attr_read_bool(const struct iio_channel *chn,
722 		const char *attr, bool *val)
723 {
724 	long long value;
725 	int ret = iio_channel_attr_read_longlong(chn, attr, &value);
726 	if (ret < 0)
727 		return ret;
728 
729 	*val = !!value;
730 	return 0;
731 }
732 
iio_channel_attr_read_double(const struct iio_channel * chn,const char * attr,double * val)733 int iio_channel_attr_read_double(const struct iio_channel *chn,
734 		const char *attr, double *val)
735 {
736 	char buf[1024];
737 	ssize_t ret = iio_channel_attr_read(chn, attr, buf, sizeof(buf));
738 	if (ret < 0)
739 		return (int) ret;
740 	else
741 		return read_double(buf, val);
742 }
743 
iio_channel_attr_write_longlong(const struct iio_channel * chn,const char * attr,long long val)744 int iio_channel_attr_write_longlong(const struct iio_channel *chn,
745 		const char *attr, long long val)
746 {
747 	int ret;
748 	char buf[1024];
749 	iio_snprintf(buf, sizeof(buf), "%lld", val);
750 	ret = (int) iio_channel_attr_write(chn, attr, buf);
751 	return ret < 0 ? ret : 0;
752 }
753 
iio_channel_attr_write_double(const struct iio_channel * chn,const char * attr,double val)754 int iio_channel_attr_write_double(const struct iio_channel *chn,
755 		const char *attr, double val)
756 {
757 	int ret;
758 	char buf[1024];
759 
760 	ret = write_double(buf, sizeof(buf), val);
761 	if (!ret)
762 		ret = (int) iio_channel_attr_write(chn, attr, buf);
763 	return ret < 0 ? ret : 0;
764 }
765 
iio_channel_attr_write_bool(const struct iio_channel * chn,const char * attr,bool val)766 int iio_channel_attr_write_bool(const struct iio_channel *chn,
767 		const char *attr, bool val)
768 {
769 	int ret;
770 	if (val)
771 		ret = (int) iio_channel_attr_write_raw(chn, attr, "1", 2);
772 	else
773 		ret = (int) iio_channel_attr_write_raw(chn, attr, "0", 2);
774 	return ret < 0 ? ret : 0;
775 }
776 
iio_channel_attr_get_filename(const struct iio_channel * chn,const char * attr)777 const char * iio_channel_attr_get_filename(
778 		const struct iio_channel *chn, const char *attr)
779 {
780 	unsigned int i;
781 	for (i = 0; i < chn->nb_attrs; i++) {
782 		if (!strcmp(chn->attrs[i].name, attr))
783 			return chn->attrs[i].filename;
784 	}
785 	return NULL;
786 }
787 
iio_channel_attr_read_all(struct iio_channel * chn,int (* cb)(struct iio_channel * chn,const char * attr,const char * val,size_t len,void * d),void * data)788 int iio_channel_attr_read_all(struct iio_channel *chn,
789 		int (*cb)(struct iio_channel *chn,
790 			const char *attr, const char *val, size_t len, void *d),
791 		void *data)
792 {
793 	int ret, buf_size;
794 	char *buf, *ptr;
795 	unsigned int i;
796 
797 	/* We need a big buffer here; 1 MiB should be enough */
798 	buf = malloc(0x100000);
799 	if (!buf)
800 		return -ENOMEM;
801 
802 	ret = (int) iio_channel_attr_read(chn, NULL, buf, 0x100000);
803 	if (ret < 0)
804 		goto err_free_buf;
805 
806 	ptr = buf;
807 	buf_size = ret;
808 
809 	for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
810 		const char *attr = iio_channel_get_attr(chn, i);
811 		int32_t len;
812 
813 		if (buf_size < 4) {
814 			ret = -EPROTO;
815 			break;
816 		}
817 
818 		len = (int32_t) iio_be32toh(*(uint32_t *) ptr);
819 		ptr += 4;
820 		buf_size -= 4;
821 
822 		if (len > 0 && buf_size < len) {
823 			ret = -EPROTO;
824 			break;
825 		}
826 
827 		if (len > 0) {
828 			ret = cb(chn, attr, ptr, (size_t) len, data);
829 			if (ret < 0)
830 				goto err_free_buf;
831 
832 			if (len & 0x3)
833 				len = ((len >> 2) + 1) << 2;
834 			ptr += len;
835 			if (len >= buf_size)
836 				buf_size = 0;
837 			else
838 				buf_size -= len;
839 		}
840 	}
841 
842 err_free_buf:
843 	free(buf);
844 	return ret < 0 ? ret : 0;
845 }
846 
iio_channel_attr_write_all(struct iio_channel * chn,ssize_t (* cb)(struct iio_channel * chn,const char * attr,void * buf,size_t len,void * d),void * data)847 int iio_channel_attr_write_all(struct iio_channel *chn,
848 		ssize_t (*cb)(struct iio_channel *chn,
849 			const char *attr, void *buf, size_t len, void *d),
850 		void *data)
851 {
852 	char *buf, *ptr;
853 	unsigned int i;
854 	size_t len = 0x100000;
855 	int ret;
856 
857 	/* We need a big buffer here; 1 MiB should be enough */
858 	buf = malloc(len);
859 	if (!buf)
860 		return -ENOMEM;
861 
862 	ptr = buf;
863 
864 	for (i = 0; i < iio_channel_get_attrs_count(chn); i++) {
865 		const char *attr = iio_channel_get_attr(chn, i);
866 
867 		ret = (int) cb(chn, attr, ptr + 4, len - 4, data);
868 		if (ret < 0)
869 			goto err_free_buf;
870 
871 		*(int32_t *) ptr = (int32_t) iio_htobe32((uint32_t) ret);
872 		ptr += 4;
873 		len -= 4;
874 
875 		if (ret > 0) {
876 			if (ret & 0x3)
877 				ret = ((ret >> 2) + 1) << 2;
878 			ptr += ret;
879 			len -= ret;
880 		}
881 	}
882 
883 	ret = (int) iio_channel_attr_write_raw(chn, NULL, buf, ptr - buf);
884 
885 err_free_buf:
886 	free(buf);
887 	return ret < 0 ? ret : 0;
888 }
889 
iio_channel_get_device(const struct iio_channel * chn)890 const struct iio_device * iio_channel_get_device(const struct iio_channel *chn)
891 {
892 	return chn->dev;
893 }
894