intel_pstate: fix PCT_TO_HWP macro
[linux-2.6-block.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                         *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 */