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