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