]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/iio/iio_utils.c
tools:iio:iio_event_monitor: refactor events output
[karo-tx-linux.git] / tools / iio / iio_utils.c
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                         if (signchar == 's')
172                                 *is_signed = 1;
173                         else
174                                 *is_signed = 0;
175                         if (fclose(sysfsfp)) {
176                                 ret = -errno;
177                                 printf("Failed to close %s\n", filename);
178                                 goto error_free_filename;
179                         }
180
181                         free(filename);
182
183                         filename = 0;
184                         sysfsfp = 0;
185                 }
186 error_close_sysfsfp:
187         if (sysfsfp)
188                 if (fclose(sysfsfp))
189                         perror("iioutils_get_type(): Failed to close file");
190
191 error_free_filename:
192         if (filename)
193                 free(filename);
194 error_closedir:
195         if (closedir(dp) == -1)
196                 perror("iioutils_get_type(): Failed to close directory");
197
198 error_free_builtname_generic:
199         free(builtname_generic);
200 error_free_builtname:
201         free(builtname);
202 error_free_scan_el_dir:
203         free(scan_el_dir);
204
205         return ret;
206 }
207
208 /**
209  * iioutils_get_param_float() - read a float value from a channel parameter
210  * @output: output the float value
211  * @param_name: the parameter name to read
212  * @device_dir: the IIO device directory in sysfs
213  * @name: the channel name
214  * @generic_name: the channel type name
215  *
216  * Returns a value >= 0 on success, otherwise a negative error code.
217  **/
218 int iioutils_get_param_float(float *output,
219                                     const char *param_name,
220                                     const char *device_dir,
221                                     const char *name,
222                                     const char *generic_name)
223 {
224         FILE *sysfsfp;
225         int ret;
226         DIR *dp;
227         char *builtname, *builtname_generic;
228         char *filename = NULL;
229         const struct dirent *ent;
230
231         ret = asprintf(&builtname, "%s_%s", name, param_name);
232         if (ret < 0)
233                 return -ENOMEM;
234
235         ret = asprintf(&builtname_generic,
236                        "%s_%s", generic_name, param_name);
237         if (ret < 0) {
238                 ret = -ENOMEM;
239                 goto error_free_builtname;
240         }
241         dp = opendir(device_dir);
242         if (dp == NULL) {
243                 ret = -errno;
244                 goto error_free_builtname_generic;
245         }
246         ret = -ENOENT;
247         while (ent = readdir(dp), ent != NULL)
248                 if ((strcmp(builtname, ent->d_name) == 0) ||
249                     (strcmp(builtname_generic, ent->d_name) == 0)) {
250                         ret = asprintf(&filename,
251                                        "%s/%s", device_dir, ent->d_name);
252                         if (ret < 0) {
253                                 ret = -ENOMEM;
254                                 goto error_closedir;
255                         }
256                         sysfsfp = fopen(filename, "r");
257                         if (!sysfsfp) {
258                                 ret = -errno;
259                                 goto error_free_filename;
260                         }
261                         errno = 0;
262                         if (fscanf(sysfsfp, "%f", output) != 1)
263                                 ret = errno ? -errno : -ENODATA;
264
265                         break;
266                 }
267 error_free_filename:
268         if (filename)
269                 free(filename);
270 error_closedir:
271         if (closedir(dp) == -1)
272                 perror("iioutils_get_param_float(): Failed to close directory");
273
274 error_free_builtname_generic:
275         free(builtname_generic);
276 error_free_builtname:
277         free(builtname);
278
279         return ret;
280 }
281
282 /**
283  * bsort_channel_array_by_index() - sort the array in index order
284  * @ci_array: the iio_channel_info array to be sorted
285  * @cnt: the amount of array elements
286  **/
287
288 void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
289                                          int cnt)
290 {
291
292         struct iio_channel_info temp;
293         int x, y;
294
295         for (x = 0; x < cnt; x++)
296                 for (y = 0; y < (cnt - 1); y++)
297                         if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
298                                 temp = (*ci_array)[y + 1];
299                                 (*ci_array)[y + 1] = (*ci_array)[y];
300                                 (*ci_array)[y] = temp;
301                         }
302 }
303
304 /**
305  * build_channel_array() - function to figure out what channels are present
306  * @device_dir: the IIO device directory in sysfs
307  * @ci_array: output the resulting array of iio_channel_info
308  * @counter: output the amount of array elements
309  *
310  * Returns 0 on success, otherwise a negative error code.
311  **/
312 int build_channel_array(const char *device_dir,
313                               struct iio_channel_info **ci_array,
314                               int *counter)
315 {
316         DIR *dp;
317         FILE *sysfsfp;
318         int count, i;
319         struct iio_channel_info *current;
320         int ret;
321         const struct dirent *ent;
322         char *scan_el_dir;
323         char *filename;
324
325         *counter = 0;
326         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
327         if (ret < 0)
328                 return -ENOMEM;
329
330         dp = opendir(scan_el_dir);
331         if (dp == NULL) {
332                 ret = -errno;
333                 goto error_free_name;
334         }
335         while (ent = readdir(dp), ent != NULL)
336                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
337                            "_en") == 0) {
338                         ret = asprintf(&filename,
339                                        "%s/%s", scan_el_dir, ent->d_name);
340                         if (ret < 0) {
341                                 ret = -ENOMEM;
342                                 goto error_close_dir;
343                         }
344                         sysfsfp = fopen(filename, "r");
345                         if (sysfsfp == NULL) {
346                                 ret = -errno;
347                                 free(filename);
348                                 goto error_close_dir;
349                         }
350                         errno = 0;
351                         if (fscanf(sysfsfp, "%i", &ret) != 1) {
352                                 ret = errno ? -errno : -ENODATA;
353                                 if (fclose(sysfsfp))
354                                         perror("build_channel_array(): Failed to close file");
355
356                                 free(filename);
357                                 goto error_close_dir;
358                         }
359
360                         if (ret == 1)
361                                 (*counter)++;
362                         if (fclose(sysfsfp)) {
363                                 ret = -errno;
364                                 free(filename);
365                                 goto error_close_dir;
366                         }
367
368                         free(filename);
369                 }
370         *ci_array = malloc(sizeof(**ci_array) * (*counter));
371         if (*ci_array == NULL) {
372                 ret = -ENOMEM;
373                 goto error_close_dir;
374         }
375         seekdir(dp, 0);
376         count = 0;
377         while (ent = readdir(dp), ent != NULL) {
378                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
379                            "_en") == 0) {
380                         int current_enabled = 0;
381
382                         current = &(*ci_array)[count++];
383                         ret = asprintf(&filename,
384                                        "%s/%s", scan_el_dir, ent->d_name);
385                         if (ret < 0) {
386                                 ret = -ENOMEM;
387                                 /* decrement count to avoid freeing name */
388                                 count--;
389                                 goto error_cleanup_array;
390                         }
391                         sysfsfp = fopen(filename, "r");
392                         if (sysfsfp == NULL) {
393                                 ret = -errno;
394                                 free(filename);
395                                 count--;
396                                 goto error_cleanup_array;
397                         }
398                         errno = 0;
399                         if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
400                                 ret = errno ? -errno : -ENODATA;
401                                 free(filename);
402                                 count--;
403                                 goto error_cleanup_array;
404                         }
405
406                         if (fclose(sysfsfp)) {
407                                 ret = -errno;
408                                 free(filename);
409                                 count--;
410                                 goto error_cleanup_array;
411                         }
412
413                         if (!current_enabled) {
414                                 free(filename);
415                                 count--;
416                                 continue;
417                         }
418
419                         current->scale = 1.0;
420                         current->offset = 0;
421                         current->name = strndup(ent->d_name,
422                                                 strlen(ent->d_name) -
423                                                 strlen("_en"));
424                         if (current->name == NULL) {
425                                 free(filename);
426                                 ret = -ENOMEM;
427                                 count--;
428                                 goto error_cleanup_array;
429                         }
430                         /* Get the generic and specific name elements */
431                         ret = iioutils_break_up_name(current->name,
432                                                      &current->generic_name);
433                         if (ret) {
434                                 free(filename);
435                                 free(current->name);
436                                 count--;
437                                 goto error_cleanup_array;
438                         }
439                         ret = asprintf(&filename,
440                                        "%s/%s_index",
441                                        scan_el_dir,
442                                        current->name);
443                         if (ret < 0) {
444                                 free(filename);
445                                 ret = -ENOMEM;
446                                 goto error_cleanup_array;
447                         }
448                         sysfsfp = fopen(filename, "r");
449                         if (sysfsfp == NULL) {
450                                 ret = -errno;
451                                 printf("failed to open %s\n", filename);
452                                 free(filename);
453                                 goto error_cleanup_array;
454                         }
455
456                         errno = 0;
457                         if (fscanf(sysfsfp, "%u", &current->index) != 1) {
458                                 ret = errno ? -errno : -ENODATA;
459                                 if (fclose(sysfsfp))
460                                         perror("build_channel_array(): Failed to close file");
461
462                                 free(filename);
463                                 goto error_cleanup_array;
464                         }
465
466                         if (fclose(sysfsfp)) {
467                                 ret = -errno;
468                                 free(filename);
469                                 goto error_cleanup_array;
470                         }
471
472                         free(filename);
473                         /* Find the scale */
474                         ret = iioutils_get_param_float(&current->scale,
475                                                        "scale",
476                                                        device_dir,
477                                                        current->name,
478                                                        current->generic_name);
479                         if (ret < 0)
480                                 goto error_cleanup_array;
481                         ret = iioutils_get_param_float(&current->offset,
482                                                        "offset",
483                                                        device_dir,
484                                                        current->name,
485                                                        current->generic_name);
486                         if (ret < 0)
487                                 goto error_cleanup_array;
488                         ret = iioutils_get_type(&current->is_signed,
489                                                 &current->bytes,
490                                                 &current->bits_used,
491                                                 &current->shift,
492                                                 &current->mask,
493                                                 &current->be,
494                                                 device_dir,
495                                                 current->name,
496                                                 current->generic_name);
497                         if (ret < 0)
498                                 goto error_cleanup_array;
499                 }
500         }
501
502         if (closedir(dp) == -1) {
503                 ret = -errno;
504                 goto error_cleanup_array;
505         }
506
507         free(scan_el_dir);
508         /* reorder so that the array is in index order */
509         bsort_channel_array_by_index(ci_array, *counter);
510
511         return 0;
512
513 error_cleanup_array:
514         for (i = count - 1;  i >= 0; i--) {
515                 free((*ci_array)[i].name);
516                 free((*ci_array)[i].generic_name);
517         }
518         free(*ci_array);
519 error_close_dir:
520         if (dp)
521                 if (closedir(dp) == -1)
522                         perror("build_channel_array(): Failed to close dir");
523
524 error_free_name:
525         free(scan_el_dir);
526
527         return ret;
528 }
529
530 int calc_digits(int num)
531 {
532         int count = 0;
533
534         while (num != 0) {
535                 num /= 10;
536                 count++;
537         }
538
539         return count;
540 }
541
542 /**
543  * find_type_by_name() - function to match top level types by name
544  * @name: top level type instance name
545  * @type: the type of top level instance being searched
546  *
547  * Returns the device number of a matched IIO device on success, otherwise a
548  * negative error code.
549  * Typical types this is used for are device and trigger.
550  **/
551 int find_type_by_name(const char *name, const char *type)
552 {
553         const struct dirent *ent;
554         int number, numstrlen, ret;
555
556         FILE *nameFile;
557         DIR *dp;
558         char thisname[IIO_MAX_NAME_LENGTH];
559         char *filename;
560
561         dp = opendir(iio_dir);
562         if (dp == NULL) {
563                 printf("No industrialio devices available\n");
564                 return -ENODEV;
565         }
566
567         while (ent = readdir(dp), ent != NULL) {
568                 if (strcmp(ent->d_name, ".") != 0 &&
569                         strcmp(ent->d_name, "..") != 0 &&
570                         strlen(ent->d_name) > strlen(type) &&
571                         strncmp(ent->d_name, type, strlen(type)) == 0) {
572                         errno = 0;
573                         ret = sscanf(ent->d_name + strlen(type), "%d", &number);
574                         if (ret < 0) {
575                                 ret = -errno;
576                                 printf("failed to read element number\n");
577                                 goto error_close_dir;
578                         } else if (ret != 1) {
579                                 ret = -EIO;
580                                 printf("failed to match element number\n");
581                                 goto error_close_dir;
582                         }
583
584                         numstrlen = calc_digits(number);
585                         /* verify the next character is not a colon */
586                         if (strncmp(ent->d_name + strlen(type) + numstrlen,
587                                         ":",
588                                         1) != 0) {
589                                 filename = malloc(strlen(iio_dir)
590                                                 + strlen(type)
591                                                 + numstrlen
592                                                 + 6);
593                                 if (filename == NULL) {
594                                         ret = -ENOMEM;
595                                         goto error_close_dir;
596                                 }
597
598                                 ret = sprintf(filename, "%s%s%d/name", iio_dir,
599                                               type, number);
600                                 if (ret < 0) {
601                                         free(filename);
602                                         goto error_close_dir;
603                                 }
604
605                                 nameFile = fopen(filename, "r");
606                                 if (!nameFile) {
607                                         free(filename);
608                                         continue;
609                                 }
610                                 free(filename);
611                                 errno = 0;
612                                 if (fscanf(nameFile, "%s", thisname) != 1) {
613                                         ret = errno ? -errno : -ENODATA;
614                                         goto error_close_dir;
615                                 }
616
617                                 if (fclose(nameFile)) {
618                                         ret = -errno;
619                                         goto error_close_dir;
620                                 }
621
622                                 if (strcmp(name, thisname) == 0) {
623                                         if (closedir(dp) == -1)
624                                                 return -errno;
625                                         return number;
626                                 }
627                         }
628                 }
629         }
630         if (closedir(dp) == -1)
631                 return -errno;
632
633         return -ENODEV;
634
635 error_close_dir:
636         if (closedir(dp) == -1)
637                 perror("find_type_by_name(): Failed to close directory");
638         return ret;
639 }
640
641 static int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
642 {
643         int ret = 0;
644         FILE *sysfsfp;
645         int test;
646         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
647
648         if (temp == NULL)
649                 return -ENOMEM;
650         ret = sprintf(temp, "%s/%s", basedir, filename);
651         if (ret < 0)
652                 goto error_free;
653
654         sysfsfp = fopen(temp, "w");
655         if (sysfsfp == NULL) {
656                 ret = -errno;
657                 printf("failed to open %s\n", temp);
658                 goto error_free;
659         }
660         ret = fprintf(sysfsfp, "%d", val);
661         if (ret < 0) {
662                 if (fclose(sysfsfp))
663                         perror("_write_sysfs_int(): Failed to close dir");
664
665                 goto error_free;
666         }
667
668         if (fclose(sysfsfp)) {
669                 ret = -errno;
670                 goto error_free;
671         }
672
673         if (verify) {
674                 sysfsfp = fopen(temp, "r");
675                 if (sysfsfp == NULL) {
676                         ret = -errno;
677                         printf("failed to open %s\n", temp);
678                         goto error_free;
679                 }
680                 if (fscanf(sysfsfp, "%d", &test) != 1) {
681                         ret = errno ? -errno : -ENODATA;
682                         if (fclose(sysfsfp))
683                                 perror("_write_sysfs_int(): Failed to close dir");
684
685                         goto error_free;
686                 }
687
688                 if (fclose(sysfsfp)) {
689                         ret = -errno;
690                         goto error_free;
691                 }
692
693                 if (test != val) {
694                         printf("Possible failure in int write %d to %s%s\n",
695                                 val,
696                                 basedir,
697                                 filename);
698                         ret = -1;
699                 }
700         }
701 error_free:
702         free(temp);
703         return ret;
704 }
705
706 /**
707  * write_sysfs_int() - write an integer value to a sysfs file
708  * @filename: name of the file to write to
709  * @basedir: the sysfs directory in which the file is to be found
710  * @val: integer value to write to file
711  *
712  * Returns a value >= 0 on success, otherwise a negative error code.
713  **/
714 int write_sysfs_int(char *filename, char *basedir, int val)
715 {
716         return _write_sysfs_int(filename, basedir, val, 0);
717 }
718
719 /**
720  * write_sysfs_int_and_verify() - write an integer value to a sysfs file
721  *                                and verify
722  * @filename: name of the file to write to
723  * @basedir: the sysfs directory in which the file is to be found
724  * @val: integer value to write to file
725  *
726  * Returns a value >= 0 on success, otherwise a negative error code.
727  **/
728 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
729 {
730         return _write_sysfs_int(filename, basedir, val, 1);
731 }
732
733 static int _write_sysfs_string(char *filename, char *basedir, char *val,
734                                int verify)
735 {
736         int ret = 0;
737         FILE  *sysfsfp;
738         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
739
740         if (temp == NULL) {
741                 printf("Memory allocation failed\n");
742                 return -ENOMEM;
743         }
744         ret = sprintf(temp, "%s/%s", basedir, filename);
745         if (ret < 0)
746                 goto error_free;
747
748         sysfsfp = fopen(temp, "w");
749         if (sysfsfp == NULL) {
750                 ret = -errno;
751                 printf("Could not open %s\n", temp);
752                 goto error_free;
753         }
754         ret = fprintf(sysfsfp, "%s", val);
755         if (ret < 0) {
756                 if (fclose(sysfsfp))
757                         perror("_write_sysfs_string(): Failed to close dir");
758
759                 goto error_free;
760         }
761
762         if (fclose(sysfsfp)) {
763                 ret = -errno;
764                 goto error_free;
765         }
766
767         if (verify) {
768                 sysfsfp = fopen(temp, "r");
769                 if (sysfsfp == NULL) {
770                         ret = -errno;
771                         printf("could not open file to verify\n");
772                         goto error_free;
773                 }
774                 if (fscanf(sysfsfp, "%s", temp) != 1) {
775                         ret = errno ? -errno : -ENODATA;
776                         if (fclose(sysfsfp))
777                                 perror("_write_sysfs_string(): Failed to close dir");
778
779                         goto error_free;
780                 }
781
782                 if (fclose(sysfsfp)) {
783                         ret = -errno;
784                         goto error_free;
785                 }
786
787                 if (strcmp(temp, val) != 0) {
788                         printf("Possible failure in string write of %s "
789                                 "Should be %s "
790                                 "written to %s\%s\n",
791                                 temp,
792                                 val,
793                                 basedir,
794                                 filename);
795                         ret = -1;
796                 }
797         }
798 error_free:
799         free(temp);
800
801         return ret;
802 }
803
804 /**
805  * write_sysfs_string_and_verify() - string write, readback and verify
806  * @filename: name of file to write to
807  * @basedir: the sysfs directory in which the file is to be found
808  * @val: the string to write
809  *
810  * Returns a value >= 0 on success, otherwise a negative error code.
811  **/
812 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
813 {
814         return _write_sysfs_string(filename, basedir, val, 1);
815 }
816
817 /**
818  * write_sysfs_string() - write string to a sysfs file
819  * @filename: name of file to write to
820  * @basedir: the sysfs directory in which the file is to be found
821  * @val: the string to write
822  *
823  * Returns a value >= 0 on success, otherwise a negative error code.
824  **/
825 int write_sysfs_string(char *filename, char *basedir, 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(char *filename, 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(char *filename, 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 */