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