xref: /linux/tools/iio/iio_utils.c (revision 93df8a1ed6231727c5db94a80b1a6bd5ee67cec3)
1 /* IIO - useful set of util functionality
2  *
3  * Copyright (c) 2008 Jonathan Cameron
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  */
9 #ifndef _IIO_UTILS_H
10 #define _IIO_UTILS_H
11 
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <dirent.h>
17 #include <errno.h>
18 #include <ctype.h>
19 #include "iio_utils.h"
20 
21 const char *iio_dir = "/sys/bus/iio/devices/";
22 
23 static char * const iio_direction[] = {
24 	"in",
25 	"out",
26 };
27 
28 /**
29  * iioutils_break_up_name() - extract generic name from full channel name
30  * @full_name: the full channel name
31  * @generic_name: the output generic channel name
32  *
33  * Returns 0 on success, or a negative error code if string extraction failed.
34  **/
35 int iioutils_break_up_name(const char *full_name,
36 				  char **generic_name)
37 {
38 	char *current;
39 	char *w, *r;
40 	char *working, *prefix = "";
41 	int i, ret;
42 
43 	for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
44 		if (!strncmp(full_name, iio_direction[i],
45 			     strlen(iio_direction[i]))) {
46 			prefix = iio_direction[i];
47 			break;
48 		}
49 
50 	current = strdup(full_name + strlen(prefix) + 1);
51 	if (!current)
52 		return -ENOMEM;
53 
54 	working = strtok(current, "_\0");
55 	if (!working) {
56 		free(current);
57 		return -EINVAL;
58 	}
59 
60 	w = working;
61 	r = working;
62 
63 	while (*r != '\0') {
64 		if (!isdigit(*r)) {
65 			*w = *r;
66 			w++;
67 		}
68 		r++;
69 	}
70 	*w = '\0';
71 	ret = asprintf(generic_name, "%s_%s", prefix, working);
72 	free(current);
73 
74 	return (ret == -1) ? -ENOMEM : 0;
75 }
76 
77 /**
78  * iioutils_get_type() - find and process _type attribute data
79  * @is_signed: output whether channel is signed
80  * @bytes: output how many bytes the channel storage occupies
81  * @bits_used: output number of valid bits of data
82  * @shift: output amount of bits to shift right data before applying bit mask
83  * @mask: output a bit mask for the raw data
84  * @be: output if data in big endian
85  * @device_dir: the IIO device directory
86  * @name: the channel name
87  * @generic_name: the channel type name
88  *
89  * Returns a value >= 0 on success, otherwise a negative error code.
90  **/
91 int iioutils_get_type(unsigned *is_signed,
92 			     unsigned *bytes,
93 			     unsigned *bits_used,
94 			     unsigned *shift,
95 			     uint64_t *mask,
96 			     unsigned *be,
97 			     const char *device_dir,
98 			     const char *name,
99 			     const char *generic_name)
100 {
101 	FILE *sysfsfp;
102 	int ret;
103 	DIR *dp;
104 	char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
105 	char signchar, endianchar;
106 	unsigned padint;
107 	const struct dirent *ent;
108 
109 	ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
110 	if (ret < 0)
111 		return -ENOMEM;
112 
113 	ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
114 	if (ret < 0) {
115 		ret = -ENOMEM;
116 		goto error_free_scan_el_dir;
117 	}
118 	ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
119 	if (ret < 0) {
120 		ret = -ENOMEM;
121 		goto error_free_builtname;
122 	}
123 
124 	dp = opendir(scan_el_dir);
125 	if (dp == NULL) {
126 		ret = -errno;
127 		goto error_free_builtname_generic;
128 	}
129 	ret = -ENOENT;
130 	while (ent = readdir(dp), ent != NULL)
131 		/*
132 		 * Do we allow devices to override a generic name with
133 		 * a specific one?
134 		 */
135 		if ((strcmp(builtname, ent->d_name) == 0) ||
136 		    (strcmp(builtname_generic, ent->d_name) == 0)) {
137 			ret = asprintf(&filename,
138 				       "%s/%s", scan_el_dir, ent->d_name);
139 			if (ret < 0) {
140 				ret = -ENOMEM;
141 				goto error_closedir;
142 			}
143 			sysfsfp = fopen(filename, "r");
144 			if (sysfsfp == NULL) {
145 				ret = -errno;
146 				printf("failed to open %s\n", filename);
147 				goto error_free_filename;
148 			}
149 
150 			ret = fscanf(sysfsfp,
151 				     "%ce:%c%u/%u>>%u",
152 				     &endianchar,
153 				     &signchar,
154 				     bits_used,
155 				     &padint, shift);
156 			if (ret < 0) {
157 				ret = -errno;
158 				printf("failed to pass scan type description\n");
159 				goto error_close_sysfsfp;
160 			} else if (ret != 5) {
161 				ret = -EIO;
162 				printf("scan type description didn't match\n");
163 				goto error_close_sysfsfp;
164 			}
165 			*be = (endianchar == 'b');
166 			*bytes = padint / 8;
167 			if (*bits_used == 64)
168 				*mask = ~0;
169 			else
170 				*mask = (1 << *bits_used) - 1;
171 			*is_signed = (signchar == 's');
172 			if (fclose(sysfsfp)) {
173 				ret = -errno;
174 				printf("Failed to close %s\n", filename);
175 				goto error_free_filename;
176 			}
177 
178 			sysfsfp = 0;
179 			free(filename);
180 
181 			filename = 0;
182 		}
183 error_close_sysfsfp:
184 	if (sysfsfp)
185 		if (fclose(sysfsfp))
186 			perror("iioutils_get_type(): Failed to close file");
187 
188 error_free_filename:
189 	if (filename)
190 		free(filename);
191 error_closedir:
192 	if (closedir(dp) == -1)
193 		perror("iioutils_get_type(): Failed to close directory");
194 
195 error_free_builtname_generic:
196 	free(builtname_generic);
197 error_free_builtname:
198 	free(builtname);
199 error_free_scan_el_dir:
200 	free(scan_el_dir);
201 
202 	return ret;
203 }
204 
205 /**
206  * iioutils_get_param_float() - read a float value from a channel parameter
207  * @output: output the float value
208  * @param_name: the parameter name to read
209  * @device_dir: the IIO device directory in sysfs
210  * @name: the channel name
211  * @generic_name: the channel type name
212  *
213  * Returns a value >= 0 on success, otherwise a negative error code.
214  **/
215 int iioutils_get_param_float(float *output,
216 				    const char *param_name,
217 				    const char *device_dir,
218 				    const char *name,
219 				    const char *generic_name)
220 {
221 	FILE *sysfsfp;
222 	int ret;
223 	DIR *dp;
224 	char *builtname, *builtname_generic;
225 	char *filename = NULL;
226 	const struct dirent *ent;
227 
228 	ret = asprintf(&builtname, "%s_%s", name, param_name);
229 	if (ret < 0)
230 		return -ENOMEM;
231 
232 	ret = asprintf(&builtname_generic,
233 		       "%s_%s", generic_name, param_name);
234 	if (ret < 0) {
235 		ret = -ENOMEM;
236 		goto error_free_builtname;
237 	}
238 	dp = opendir(device_dir);
239 	if (dp == NULL) {
240 		ret = -errno;
241 		goto error_free_builtname_generic;
242 	}
243 	ret = -ENOENT;
244 	while (ent = readdir(dp), ent != NULL)
245 		if ((strcmp(builtname, ent->d_name) == 0) ||
246 		    (strcmp(builtname_generic, ent->d_name) == 0)) {
247 			ret = asprintf(&filename,
248 				       "%s/%s", device_dir, ent->d_name);
249 			if (ret < 0) {
250 				ret = -ENOMEM;
251 				goto error_closedir;
252 			}
253 			sysfsfp = fopen(filename, "r");
254 			if (!sysfsfp) {
255 				ret = -errno;
256 				goto error_free_filename;
257 			}
258 			errno = 0;
259 			if (fscanf(sysfsfp, "%f", output) != 1)
260 				ret = errno ? -errno : -ENODATA;
261 
262 			break;
263 		}
264 error_free_filename:
265 	if (filename)
266 		free(filename);
267 error_closedir:
268 	if (closedir(dp) == -1)
269 		perror("iioutils_get_param_float(): Failed to close directory");
270 
271 error_free_builtname_generic:
272 	free(builtname_generic);
273 error_free_builtname:
274 	free(builtname);
275 
276 	return ret;
277 }
278 
279 /**
280  * bsort_channel_array_by_index() - sort the array in index order
281  * @ci_array: the iio_channel_info array to be sorted
282  * @cnt: the amount of array elements
283  **/
284 
285 void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
286 					 int cnt)
287 {
288 
289 	struct iio_channel_info temp;
290 	int x, y;
291 
292 	for (x = 0; x < cnt; x++)
293 		for (y = 0; y < (cnt - 1); y++)
294 			if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
295 				temp = (*ci_array)[y + 1];
296 				(*ci_array)[y + 1] = (*ci_array)[y];
297 				(*ci_array)[y] = temp;
298 			}
299 }
300 
301 /**
302  * build_channel_array() - function to figure out what channels are present
303  * @device_dir: the IIO device directory in sysfs
304  * @ci_array: output the resulting array of iio_channel_info
305  * @counter: output the amount of array elements
306  *
307  * Returns 0 on success, otherwise a negative error code.
308  **/
309 int build_channel_array(const char *device_dir,
310 			      struct iio_channel_info **ci_array,
311 			      int *counter)
312 {
313 	DIR *dp;
314 	FILE *sysfsfp;
315 	int count = 0, i;
316 	struct iio_channel_info *current;
317 	int ret;
318 	const struct dirent *ent;
319 	char *scan_el_dir;
320 	char *filename;
321 
322 	*counter = 0;
323 	ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
324 	if (ret < 0)
325 		return -ENOMEM;
326 
327 	dp = opendir(scan_el_dir);
328 	if (dp == NULL) {
329 		ret = -errno;
330 		goto error_free_name;
331 	}
332 	while (ent = readdir(dp), ent != NULL)
333 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
334 			   "_en") == 0) {
335 			ret = asprintf(&filename,
336 				       "%s/%s", scan_el_dir, ent->d_name);
337 			if (ret < 0) {
338 				ret = -ENOMEM;
339 				goto error_close_dir;
340 			}
341 			sysfsfp = fopen(filename, "r");
342 			if (sysfsfp == NULL) {
343 				ret = -errno;
344 				free(filename);
345 				goto error_close_dir;
346 			}
347 			errno = 0;
348 			if (fscanf(sysfsfp, "%i", &ret) != 1) {
349 				ret = errno ? -errno : -ENODATA;
350 				if (fclose(sysfsfp))
351 					perror("build_channel_array(): Failed to close file");
352 
353 				free(filename);
354 				goto error_close_dir;
355 			}
356 
357 			if (ret == 1)
358 				(*counter)++;
359 			if (fclose(sysfsfp)) {
360 				ret = -errno;
361 				free(filename);
362 				goto error_close_dir;
363 			}
364 
365 			free(filename);
366 		}
367 	*ci_array = malloc(sizeof(**ci_array) * (*counter));
368 	if (*ci_array == NULL) {
369 		ret = -ENOMEM;
370 		goto error_close_dir;
371 	}
372 	seekdir(dp, 0);
373 	while (ent = readdir(dp), ent != NULL) {
374 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
375 			   "_en") == 0) {
376 			int current_enabled = 0;
377 
378 			current = &(*ci_array)[count++];
379 			ret = asprintf(&filename,
380 				       "%s/%s", scan_el_dir, ent->d_name);
381 			if (ret < 0) {
382 				ret = -ENOMEM;
383 				/* decrement count to avoid freeing name */
384 				count--;
385 				goto error_cleanup_array;
386 			}
387 			sysfsfp = fopen(filename, "r");
388 			if (sysfsfp == NULL) {
389 				ret = -errno;
390 				free(filename);
391 				count--;
392 				goto error_cleanup_array;
393 			}
394 			errno = 0;
395 			if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
396 				ret = errno ? -errno : -ENODATA;
397 				free(filename);
398 				count--;
399 				goto error_cleanup_array;
400 			}
401 
402 			if (fclose(sysfsfp)) {
403 				ret = -errno;
404 				free(filename);
405 				count--;
406 				goto error_cleanup_array;
407 			}
408 
409 			if (!current_enabled) {
410 				free(filename);
411 				count--;
412 				continue;
413 			}
414 
415 			current->scale = 1.0;
416 			current->offset = 0;
417 			current->name = strndup(ent->d_name,
418 						strlen(ent->d_name) -
419 						strlen("_en"));
420 			if (current->name == NULL) {
421 				free(filename);
422 				ret = -ENOMEM;
423 				count--;
424 				goto error_cleanup_array;
425 			}
426 			/* Get the generic and specific name elements */
427 			ret = iioutils_break_up_name(current->name,
428 						     &current->generic_name);
429 			if (ret) {
430 				free(filename);
431 				free(current->name);
432 				count--;
433 				goto error_cleanup_array;
434 			}
435 			ret = asprintf(&filename,
436 				       "%s/%s_index",
437 				       scan_el_dir,
438 				       current->name);
439 			if (ret < 0) {
440 				free(filename);
441 				ret = -ENOMEM;
442 				goto error_cleanup_array;
443 			}
444 			sysfsfp = fopen(filename, "r");
445 			if (sysfsfp == NULL) {
446 				ret = -errno;
447 				printf("failed to open %s\n", filename);
448 				free(filename);
449 				goto error_cleanup_array;
450 			}
451 
452 			errno = 0;
453 			if (fscanf(sysfsfp, "%u", &current->index) != 1) {
454 				ret = errno ? -errno : -ENODATA;
455 				if (fclose(sysfsfp))
456 					perror("build_channel_array(): Failed to close file");
457 
458 				free(filename);
459 				goto error_cleanup_array;
460 			}
461 
462 			if (fclose(sysfsfp)) {
463 				ret = -errno;
464 				free(filename);
465 				goto error_cleanup_array;
466 			}
467 
468 			free(filename);
469 			/* Find the scale */
470 			ret = iioutils_get_param_float(&current->scale,
471 						       "scale",
472 						       device_dir,
473 						       current->name,
474 						       current->generic_name);
475 			if (ret < 0)
476 				goto error_cleanup_array;
477 			ret = iioutils_get_param_float(&current->offset,
478 						       "offset",
479 						       device_dir,
480 						       current->name,
481 						       current->generic_name);
482 			if (ret < 0)
483 				goto error_cleanup_array;
484 			ret = iioutils_get_type(&current->is_signed,
485 						&current->bytes,
486 						&current->bits_used,
487 						&current->shift,
488 						&current->mask,
489 						&current->be,
490 						device_dir,
491 						current->name,
492 						current->generic_name);
493 			if (ret < 0)
494 				goto error_cleanup_array;
495 		}
496 	}
497 
498 	if (closedir(dp) == -1) {
499 		ret = -errno;
500 		goto error_cleanup_array;
501 	}
502 
503 	free(scan_el_dir);
504 	/* reorder so that the array is in index order */
505 	bsort_channel_array_by_index(ci_array, *counter);
506 
507 	return 0;
508 
509 error_cleanup_array:
510 	for (i = count - 1;  i >= 0; i--) {
511 		free((*ci_array)[i].name);
512 		free((*ci_array)[i].generic_name);
513 	}
514 	free(*ci_array);
515 error_close_dir:
516 	if (dp)
517 		if (closedir(dp) == -1)
518 			perror("build_channel_array(): Failed to close dir");
519 
520 error_free_name:
521 	free(scan_el_dir);
522 
523 	return ret;
524 }
525 
526 int calc_digits(int num)
527 {
528 	int count = 0;
529 
530 	while (num != 0) {
531 		num /= 10;
532 		count++;
533 	}
534 
535 	return count;
536 }
537 
538 /**
539  * find_type_by_name() - function to match top level types by name
540  * @name: top level type instance name
541  * @type: the type of top level instance being searched
542  *
543  * Returns the device number of a matched IIO device on success, otherwise a
544  * negative error code.
545  * Typical types this is used for are device and trigger.
546  **/
547 int find_type_by_name(const char *name, const char *type)
548 {
549 	const struct dirent *ent;
550 	int number, numstrlen, ret;
551 
552 	FILE *nameFile;
553 	DIR *dp;
554 	char thisname[IIO_MAX_NAME_LENGTH];
555 	char *filename;
556 
557 	dp = opendir(iio_dir);
558 	if (dp == NULL) {
559 		printf("No industrialio devices available\n");
560 		return -ENODEV;
561 	}
562 
563 	while (ent = readdir(dp), ent != NULL) {
564 		if (strcmp(ent->d_name, ".") != 0 &&
565 			strcmp(ent->d_name, "..") != 0 &&
566 			strlen(ent->d_name) > strlen(type) &&
567 			strncmp(ent->d_name, type, strlen(type)) == 0) {
568 			errno = 0;
569 			ret = sscanf(ent->d_name + strlen(type), "%d", &number);
570 			if (ret < 0) {
571 				ret = -errno;
572 				printf("failed to read element number\n");
573 				goto error_close_dir;
574 			} else if (ret != 1) {
575 				ret = -EIO;
576 				printf("failed to match element number\n");
577 				goto error_close_dir;
578 			}
579 
580 			numstrlen = calc_digits(number);
581 			/* verify the next character is not a colon */
582 			if (strncmp(ent->d_name + strlen(type) + numstrlen,
583 					":",
584 					1) != 0) {
585 				filename = malloc(strlen(iio_dir)
586 						+ strlen(type)
587 						+ numstrlen
588 						+ 6);
589 				if (filename == NULL) {
590 					ret = -ENOMEM;
591 					goto error_close_dir;
592 				}
593 
594 				ret = sprintf(filename, "%s%s%d/name", iio_dir,
595 					      type, number);
596 				if (ret < 0) {
597 					free(filename);
598 					goto error_close_dir;
599 				}
600 
601 				nameFile = fopen(filename, "r");
602 				if (!nameFile) {
603 					free(filename);
604 					continue;
605 				}
606 				free(filename);
607 				errno = 0;
608 				if (fscanf(nameFile, "%s", thisname) != 1) {
609 					ret = errno ? -errno : -ENODATA;
610 					goto error_close_dir;
611 				}
612 
613 				if (fclose(nameFile)) {
614 					ret = -errno;
615 					goto error_close_dir;
616 				}
617 
618 				if (strcmp(name, thisname) == 0) {
619 					if (closedir(dp) == -1)
620 						return -errno;
621 					return number;
622 				}
623 			}
624 		}
625 	}
626 	if (closedir(dp) == -1)
627 		return -errno;
628 
629 	return -ENODEV;
630 
631 error_close_dir:
632 	if (closedir(dp) == -1)
633 		perror("find_type_by_name(): Failed to close directory");
634 	return ret;
635 }
636 
637 static int _write_sysfs_int(const char *filename, const char *basedir, int val,
638 			    int verify)
639 {
640 	int ret = 0;
641 	FILE *sysfsfp;
642 	int test;
643 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
644 
645 	if (temp == NULL)
646 		return -ENOMEM;
647 	ret = sprintf(temp, "%s/%s", basedir, filename);
648 	if (ret < 0)
649 		goto error_free;
650 
651 	sysfsfp = fopen(temp, "w");
652 	if (sysfsfp == NULL) {
653 		ret = -errno;
654 		printf("failed to open %s\n", temp);
655 		goto error_free;
656 	}
657 	ret = fprintf(sysfsfp, "%d", val);
658 	if (ret < 0) {
659 		if (fclose(sysfsfp))
660 			perror("_write_sysfs_int(): Failed to close dir");
661 
662 		goto error_free;
663 	}
664 
665 	if (fclose(sysfsfp)) {
666 		ret = -errno;
667 		goto error_free;
668 	}
669 
670 	if (verify) {
671 		sysfsfp = fopen(temp, "r");
672 		if (sysfsfp == NULL) {
673 			ret = -errno;
674 			printf("failed to open %s\n", temp);
675 			goto error_free;
676 		}
677 		if (fscanf(sysfsfp, "%d", &test) != 1) {
678 			ret = errno ? -errno : -ENODATA;
679 			if (fclose(sysfsfp))
680 				perror("_write_sysfs_int(): Failed to close dir");
681 
682 			goto error_free;
683 		}
684 
685 		if (fclose(sysfsfp)) {
686 			ret = -errno;
687 			goto error_free;
688 		}
689 
690 		if (test != val) {
691 			printf("Possible failure in int write %d to %s%s\n",
692 				val,
693 				basedir,
694 				filename);
695 			ret = -1;
696 		}
697 	}
698 error_free:
699 	free(temp);
700 	return ret;
701 }
702 
703 /**
704  * write_sysfs_int() - write an integer value to a sysfs file
705  * @filename: name of the file to write to
706  * @basedir: the sysfs directory in which the file is to be found
707  * @val: integer value to write to file
708  *
709  * Returns a value >= 0 on success, otherwise a negative error code.
710  **/
711 int write_sysfs_int(const char *filename, const char *basedir, int val)
712 {
713 	return _write_sysfs_int(filename, basedir, val, 0);
714 }
715 
716 /**
717  * write_sysfs_int_and_verify() - write an integer value to a sysfs file
718  *				  and verify
719  * @filename: name of the file to write to
720  * @basedir: the sysfs directory in which the file is to be found
721  * @val: integer value to write to file
722  *
723  * Returns a value >= 0 on success, otherwise a negative error code.
724  **/
725 int write_sysfs_int_and_verify(const char *filename, const char *basedir,
726 			       int val)
727 {
728 	return _write_sysfs_int(filename, basedir, val, 1);
729 }
730 
731 static int _write_sysfs_string(const char *filename, const char *basedir,
732 			       const char *val, int verify)
733 {
734 	int ret = 0;
735 	FILE  *sysfsfp;
736 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
737 
738 	if (temp == NULL) {
739 		printf("Memory allocation failed\n");
740 		return -ENOMEM;
741 	}
742 	ret = sprintf(temp, "%s/%s", basedir, filename);
743 	if (ret < 0)
744 		goto error_free;
745 
746 	sysfsfp = fopen(temp, "w");
747 	if (sysfsfp == NULL) {
748 		ret = -errno;
749 		printf("Could not open %s\n", temp);
750 		goto error_free;
751 	}
752 	ret = fprintf(sysfsfp, "%s", val);
753 	if (ret < 0) {
754 		if (fclose(sysfsfp))
755 			perror("_write_sysfs_string(): Failed to close dir");
756 
757 		goto error_free;
758 	}
759 
760 	if (fclose(sysfsfp)) {
761 		ret = -errno;
762 		goto error_free;
763 	}
764 
765 	if (verify) {
766 		sysfsfp = fopen(temp, "r");
767 		if (sysfsfp == NULL) {
768 			ret = -errno;
769 			printf("could not open file to verify\n");
770 			goto error_free;
771 		}
772 		if (fscanf(sysfsfp, "%s", temp) != 1) {
773 			ret = errno ? -errno : -ENODATA;
774 			if (fclose(sysfsfp))
775 				perror("_write_sysfs_string(): Failed to close dir");
776 
777 			goto error_free;
778 		}
779 
780 		if (fclose(sysfsfp)) {
781 			ret = -errno;
782 			goto error_free;
783 		}
784 
785 		if (strcmp(temp, val) != 0) {
786 			printf("Possible failure in string write of %s "
787 				"Should be %s "
788 				"written to %s\%s\n",
789 				temp,
790 				val,
791 				basedir,
792 				filename);
793 			ret = -1;
794 		}
795 	}
796 error_free:
797 	free(temp);
798 
799 	return ret;
800 }
801 
802 /**
803  * write_sysfs_string_and_verify() - string write, readback and verify
804  * @filename: name of file to write to
805  * @basedir: the sysfs directory in which the file is to be found
806  * @val: the string to write
807  *
808  * Returns a value >= 0 on success, otherwise a negative error code.
809  **/
810 int write_sysfs_string_and_verify(const char *filename, const char *basedir,
811 				  const char *val)
812 {
813 	return _write_sysfs_string(filename, basedir, val, 1);
814 }
815 
816 /**
817  * write_sysfs_string() - write string to a sysfs file
818  * @filename: name of file to write to
819  * @basedir: the sysfs directory in which the file is to be found
820  * @val: the string to write
821  *
822  * Returns a value >= 0 on success, otherwise a negative error code.
823  **/
824 int write_sysfs_string(const char *filename, const char *basedir,
825 		       const char *val)
826 {
827 	return _write_sysfs_string(filename, basedir, val, 0);
828 }
829 
830 /**
831  * read_sysfs_posint() - read an integer value from file
832  * @filename: name of file to read from
833  * @basedir: the sysfs directory in which the file is to be found
834  *
835  * Returns the read integer value >= 0 on success, otherwise a negative error
836  * code.
837  **/
838 int read_sysfs_posint(const char *filename, const char *basedir)
839 {
840 	int ret;
841 	FILE  *sysfsfp;
842 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
843 
844 	if (temp == NULL) {
845 		printf("Memory allocation failed");
846 		return -ENOMEM;
847 	}
848 	ret = sprintf(temp, "%s/%s", basedir, filename);
849 	if (ret < 0)
850 		goto error_free;
851 
852 	sysfsfp = fopen(temp, "r");
853 	if (sysfsfp == NULL) {
854 		ret = -errno;
855 		goto error_free;
856 	}
857 	errno = 0;
858 	if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
859 		ret = errno ? -errno : -ENODATA;
860 		if (fclose(sysfsfp))
861 			perror("read_sysfs_posint(): Failed to close dir");
862 
863 		goto error_free;
864 	}
865 
866 	if (fclose(sysfsfp))
867 		ret = -errno;
868 
869 error_free:
870 	free(temp);
871 	return ret;
872 }
873 
874 /**
875  * read_sysfs_float() - read a float value from file
876  * @filename: name of file to read from
877  * @basedir: the sysfs directory in which the file is to be found
878  * @val: output the read float value
879  *
880  * Returns a value >= 0 on success, otherwise a negative error code.
881  **/
882 int read_sysfs_float(const char *filename, const char *basedir, float *val)
883 {
884 	int ret = 0;
885 	FILE  *sysfsfp;
886 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
887 
888 	if (temp == NULL) {
889 		printf("Memory allocation failed");
890 		return -ENOMEM;
891 	}
892 	ret = sprintf(temp, "%s/%s", basedir, filename);
893 	if (ret < 0)
894 		goto error_free;
895 
896 	sysfsfp = fopen(temp, "r");
897 	if (sysfsfp == NULL) {
898 		ret = -errno;
899 		goto error_free;
900 	}
901 	errno = 0;
902 	if (fscanf(sysfsfp, "%f\n", val) != 1) {
903 		ret = errno ? -errno : -ENODATA;
904 		if (fclose(sysfsfp))
905 			perror("read_sysfs_float(): Failed to close dir");
906 
907 		goto error_free;
908 	}
909 
910 	if (fclose(sysfsfp))
911 		ret = -errno;
912 
913 error_free:
914 	free(temp);
915 	return ret;
916 }
917 
918 /**
919  * read_sysfs_string() - read a string from file
920  * @filename: name of file to read from
921  * @basedir: the sysfs directory in which the file is to be found
922  * @str: output the read string
923  *
924  * Returns a value >= 0 on success, otherwise a negative error code.
925  **/
926 int read_sysfs_string(const char *filename, const char *basedir, char *str)
927 {
928 	int ret = 0;
929 	FILE  *sysfsfp;
930 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
931 
932 	if (temp == NULL) {
933 		printf("Memory allocation failed");
934 		return -ENOMEM;
935 	}
936 	ret = sprintf(temp, "%s/%s", basedir, filename);
937 	if (ret < 0)
938 		goto error_free;
939 
940 	sysfsfp = fopen(temp, "r");
941 	if (sysfsfp == NULL) {
942 		ret = -errno;
943 		goto error_free;
944 	}
945 	errno = 0;
946 	if (fscanf(sysfsfp, "%s\n", str) != 1) {
947 		ret = errno ? -errno : -ENODATA;
948 		if (fclose(sysfsfp))
949 			perror("read_sysfs_string(): Failed to close dir");
950 
951 		goto error_free;
952 	}
953 
954 	if (fclose(sysfsfp))
955 		ret = -errno;
956 
957 error_free:
958 	free(temp);
959 	return ret;
960 }
961 
962 #endif /* _IIO_UTILS_H */
963