GNU Linux-libre 4.9.332-gnu1
[releases.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 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <stdint.h>
13 #include <dirent.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include "iio_utils.h"
17
18 const char *iio_dir = "/sys/bus/iio/devices/";
19
20 static char * const iio_direction[] = {
21         "in",
22         "out",
23 };
24
25 /**
26  * iioutils_break_up_name() - extract generic name from full channel name
27  * @full_name: the full channel name
28  * @generic_name: the output generic channel name
29  *
30  * Returns 0 on success, or a negative error code if string extraction failed.
31  **/
32 int iioutils_break_up_name(const char *full_name, char **generic_name)
33 {
34         char *current;
35         char *w, *r;
36         char *working, *prefix = "";
37         int i, ret;
38
39         for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
40                 if (!strncmp(full_name, iio_direction[i],
41                              strlen(iio_direction[i]))) {
42                         prefix = iio_direction[i];
43                         break;
44                 }
45
46         current = strdup(full_name + strlen(prefix) + 1);
47         if (!current)
48                 return -ENOMEM;
49
50         working = strtok(current, "_\0");
51         if (!working) {
52                 free(current);
53                 return -EINVAL;
54         }
55
56         w = working;
57         r = working;
58
59         while (*r != '\0') {
60                 if (!isdigit(*r)) {
61                         *w = *r;
62                         w++;
63                 }
64
65                 r++;
66         }
67         *w = '\0';
68         ret = asprintf(generic_name, "%s_%s", prefix, working);
69         free(current);
70
71         return (ret == -1) ? -ENOMEM : 0;
72 }
73
74 /**
75  * iioutils_get_type() - find and process _type attribute data
76  * @is_signed: output whether channel is signed
77  * @bytes: output how many bytes the channel storage occupies
78  * @bits_used: output number of valid bits of data
79  * @shift: output amount of bits to shift right data before applying bit mask
80  * @mask: output a bit mask for the raw data
81  * @be: output if data in big endian
82  * @device_dir: the IIO device directory
83  * @name: the channel name
84  * @generic_name: the channel type name
85  *
86  * Returns a value >= 0 on success, otherwise a negative error code.
87  **/
88 int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
89                       unsigned *shift, uint64_t *mask, unsigned *be,
90                       const char *device_dir, const char *name,
91                       const char *generic_name)
92 {
93         FILE *sysfsfp;
94         int ret;
95         DIR *dp;
96         char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
97         char signchar, endianchar;
98         unsigned padint;
99         const struct dirent *ent;
100
101         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
102         if (ret < 0)
103                 return -ENOMEM;
104
105         ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
106         if (ret < 0) {
107                 ret = -ENOMEM;
108                 goto error_free_scan_el_dir;
109         }
110         ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
111         if (ret < 0) {
112                 ret = -ENOMEM;
113                 goto error_free_builtname;
114         }
115
116         dp = opendir(scan_el_dir);
117         if (!dp) {
118                 ret = -errno;
119                 goto error_free_builtname_generic;
120         }
121
122         ret = -ENOENT;
123         while (ent = readdir(dp), ent)
124                 if ((strcmp(builtname, ent->d_name) == 0) ||
125                     (strcmp(builtname_generic, ent->d_name) == 0)) {
126                         ret = asprintf(&filename,
127                                        "%s/%s", scan_el_dir, ent->d_name);
128                         if (ret < 0) {
129                                 ret = -ENOMEM;
130                                 goto error_closedir;
131                         }
132
133                         sysfsfp = fopen(filename, "r");
134                         if (!sysfsfp) {
135                                 ret = -errno;
136                                 fprintf(stderr, "failed to open %s\n",
137                                         filename);
138                                 goto error_free_filename;
139                         }
140
141                         ret = fscanf(sysfsfp,
142                                      "%ce:%c%u/%u>>%u",
143                                      &endianchar,
144                                      &signchar,
145                                      bits_used,
146                                      &padint, shift);
147                         if (ret < 0) {
148                                 ret = -errno;
149                                 fprintf(stderr,
150                                         "failed to pass scan type description\n");
151                                 goto error_close_sysfsfp;
152                         } else if (ret != 5) {
153                                 ret = -EIO;
154                                 fprintf(stderr,
155                                         "scan type description didn't match\n");
156                                 goto error_close_sysfsfp;
157                         }
158
159                         *be = (endianchar == 'b');
160                         *bytes = padint / 8;
161                         if (*bits_used == 64)
162                                 *mask = ~(0ULL);
163                         else
164                                 *mask = (1ULL << *bits_used) - 1ULL;
165
166                         *is_signed = (signchar == 's');
167                         if (fclose(sysfsfp)) {
168                                 ret = -errno;
169                                 fprintf(stderr, "Failed to close %s\n",
170                                         filename);
171                                 goto error_free_filename;
172                         }
173
174                         sysfsfp = 0;
175                         free(filename);
176                         filename = 0;
177
178                         /*
179                          * Avoid having a more generic entry overwriting
180                          * the settings.
181                          */
182                         if (strcmp(builtname, ent->d_name) == 0)
183                                 break;
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         *ci_array = NULL;
533         *counter = 0;
534 error_close_dir:
535         if (dp)
536                 if (closedir(dp) == -1)
537                         perror("build_channel_array(): Failed to close dir");
538
539 error_free_name:
540         free(scan_el_dir);
541
542         return ret;
543 }
544
545 static int calc_digits(int num)
546 {
547         int count = 0;
548
549         /* It takes a digit to represent zero */
550         if (!num)
551                 return 1;
552
553         while (num != 0) {
554                 num /= 10;
555                 count++;
556         }
557
558         return count;
559 }
560
561 /**
562  * find_type_by_name() - function to match top level types by name
563  * @name: top level type instance name
564  * @type: the type of top level instance being searched
565  *
566  * Returns the device number of a matched IIO device on success, otherwise a
567  * negative error code.
568  * Typical types this is used for are device and trigger.
569  **/
570 int find_type_by_name(const char *name, const char *type)
571 {
572         const struct dirent *ent;
573         int number, numstrlen, ret;
574
575         FILE *namefp;
576         DIR *dp;
577         char thisname[IIO_MAX_NAME_LENGTH];
578         char *filename;
579
580         dp = opendir(iio_dir);
581         if (!dp) {
582                 fprintf(stderr, "No industrialio devices available\n");
583                 return -ENODEV;
584         }
585
586         while (ent = readdir(dp), ent) {
587                 if (strcmp(ent->d_name, ".") != 0 &&
588                     strcmp(ent->d_name, "..") != 0 &&
589                     strlen(ent->d_name) > strlen(type) &&
590                     strncmp(ent->d_name, type, strlen(type)) == 0) {
591                         errno = 0;
592                         ret = sscanf(ent->d_name + strlen(type), "%d", &number);
593                         if (ret < 0) {
594                                 ret = -errno;
595                                 fprintf(stderr,
596                                         "failed to read element number\n");
597                                 goto error_close_dir;
598                         } else if (ret != 1) {
599                                 ret = -EIO;
600                                 fprintf(stderr,
601                                         "failed to match element number\n");
602                                 goto error_close_dir;
603                         }
604
605                         numstrlen = calc_digits(number);
606                         /* verify the next character is not a colon */
607                         if (strncmp(ent->d_name + strlen(type) + numstrlen,
608                             ":", 1) != 0) {
609                                 filename = malloc(strlen(iio_dir) + strlen(type)
610                                                   + numstrlen + 6);
611                                 if (!filename) {
612                                         ret = -ENOMEM;
613                                         goto error_close_dir;
614                                 }
615
616                                 ret = sprintf(filename, "%s%s%d/name", iio_dir,
617                                               type, number);
618                                 if (ret < 0) {
619                                         free(filename);
620                                         goto error_close_dir;
621                                 }
622
623                                 namefp = fopen(filename, "r");
624                                 if (!namefp) {
625                                         free(filename);
626                                         continue;
627                                 }
628
629                                 free(filename);
630                                 errno = 0;
631                                 if (fscanf(namefp, "%s", thisname) != 1) {
632                                         ret = errno ? -errno : -ENODATA;
633                                         goto error_close_dir;
634                                 }
635
636                                 if (fclose(namefp)) {
637                                         ret = -errno;
638                                         goto error_close_dir;
639                                 }
640
641                                 if (strcmp(name, thisname) == 0) {
642                                         if (closedir(dp) == -1)
643                                                 return -errno;
644
645                                         return number;
646                                 }
647                         }
648                 }
649         }
650         if (closedir(dp) == -1)
651                 return -errno;
652
653         return -ENODEV;
654
655 error_close_dir:
656         if (closedir(dp) == -1)
657                 perror("find_type_by_name(): Failed to close directory");
658
659         return ret;
660 }
661
662 static int _write_sysfs_int(const char *filename, const char *basedir, int val,
663                             int verify)
664 {
665         int ret = 0;
666         FILE *sysfsfp;
667         int test;
668         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
669
670         if (!temp)
671                 return -ENOMEM;
672
673         ret = sprintf(temp, "%s/%s", basedir, filename);
674         if (ret < 0)
675                 goto error_free;
676
677         sysfsfp = fopen(temp, "w");
678         if (!sysfsfp) {
679                 ret = -errno;
680                 fprintf(stderr, "failed to open %s\n", temp);
681                 goto error_free;
682         }
683
684         ret = fprintf(sysfsfp, "%d", val);
685         if (ret < 0) {
686                 if (fclose(sysfsfp))
687                         perror("_write_sysfs_int(): Failed to close dir");
688
689                 goto error_free;
690         }
691
692         if (fclose(sysfsfp)) {
693                 ret = -errno;
694                 goto error_free;
695         }
696
697         if (verify) {
698                 sysfsfp = fopen(temp, "r");
699                 if (!sysfsfp) {
700                         ret = -errno;
701                         fprintf(stderr, "failed to open %s\n", temp);
702                         goto error_free;
703                 }
704
705                 if (fscanf(sysfsfp, "%d", &test) != 1) {
706                         ret = errno ? -errno : -ENODATA;
707                         if (fclose(sysfsfp))
708                                 perror("_write_sysfs_int(): Failed to close dir");
709
710                         goto error_free;
711                 }
712
713                 if (fclose(sysfsfp)) {
714                         ret = -errno;
715                         goto error_free;
716                 }
717
718                 if (test != val) {
719                         fprintf(stderr,
720                                 "Possible failure in int write %d to %s/%s\n",
721                                 val, basedir, filename);
722                         ret = -1;
723                 }
724         }
725
726 error_free:
727         free(temp);
728         return ret;
729 }
730
731 /**
732  * write_sysfs_int() - write an integer value to a sysfs file
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(const char *filename, const char *basedir, int val)
740 {
741         return _write_sysfs_int(filename, basedir, val, 0);
742 }
743
744 /**
745  * write_sysfs_int_and_verify() - write an integer value to a sysfs file
746  *                                and verify
747  * @filename: name of the file to write to
748  * @basedir: the sysfs directory in which the file is to be found
749  * @val: integer value to write to file
750  *
751  * Returns a value >= 0 on success, otherwise a negative error code.
752  **/
753 int write_sysfs_int_and_verify(const char *filename, const char *basedir,
754                                int val)
755 {
756         return _write_sysfs_int(filename, basedir, val, 1);
757 }
758
759 static int _write_sysfs_string(const char *filename, const char *basedir,
760                                const char *val, int verify)
761 {
762         int ret = 0;
763         FILE  *sysfsfp;
764         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
765
766         if (!temp) {
767                 fprintf(stderr, "Memory allocation failed\n");
768                 return -ENOMEM;
769         }
770
771         ret = sprintf(temp, "%s/%s", basedir, filename);
772         if (ret < 0)
773                 goto error_free;
774
775         sysfsfp = fopen(temp, "w");
776         if (!sysfsfp) {
777                 ret = -errno;
778                 fprintf(stderr, "Could not open %s\n", temp);
779                 goto error_free;
780         }
781
782         ret = fprintf(sysfsfp, "%s", val);
783         if (ret < 0) {
784                 if (fclose(sysfsfp))
785                         perror("_write_sysfs_string(): Failed to close dir");
786
787                 goto error_free;
788         }
789
790         if (fclose(sysfsfp)) {
791                 ret = -errno;
792                 goto error_free;
793         }
794
795         if (verify) {
796                 sysfsfp = fopen(temp, "r");
797                 if (!sysfsfp) {
798                         ret = -errno;
799                         fprintf(stderr, "Could not open file to verify\n");
800                         goto error_free;
801                 }
802
803                 if (fscanf(sysfsfp, "%s", temp) != 1) {
804                         ret = errno ? -errno : -ENODATA;
805                         if (fclose(sysfsfp))
806                                 perror("_write_sysfs_string(): Failed to close dir");
807
808                         goto error_free;
809                 }
810
811                 if (fclose(sysfsfp)) {
812                         ret = -errno;
813                         goto error_free;
814                 }
815
816                 if (strcmp(temp, val) != 0) {
817                         fprintf(stderr,
818                                 "Possible failure in string write of %s "
819                                 "Should be %s written to %s/%s\n", temp, val,
820                                 basedir, filename);
821                         ret = -1;
822                 }
823         }
824
825 error_free:
826         free(temp);
827
828         return ret;
829 }
830
831 /**
832  * write_sysfs_string_and_verify() - string write, readback and verify
833  * @filename: name of file to write to
834  * @basedir: the sysfs directory in which the file is to be found
835  * @val: the string to write
836  *
837  * Returns a value >= 0 on success, otherwise a negative error code.
838  **/
839 int write_sysfs_string_and_verify(const char *filename, const char *basedir,
840                                   const char *val)
841 {
842         return _write_sysfs_string(filename, basedir, val, 1);
843 }
844
845 /**
846  * write_sysfs_string() - write string to a sysfs file
847  * @filename: name of file to write to
848  * @basedir: the sysfs directory in which the file is to be found
849  * @val: the string to write
850  *
851  * Returns a value >= 0 on success, otherwise a negative error code.
852  **/
853 int write_sysfs_string(const char *filename, const char *basedir,
854                        const char *val)
855 {
856         return _write_sysfs_string(filename, basedir, val, 0);
857 }
858
859 /**
860  * read_sysfs_posint() - read an integer value from file
861  * @filename: name of file to read from
862  * @basedir: the sysfs directory in which the file is to be found
863  *
864  * Returns the read integer value >= 0 on success, otherwise a negative error
865  * code.
866  **/
867 int read_sysfs_posint(const char *filename, const char *basedir)
868 {
869         int ret;
870         FILE  *sysfsfp;
871         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
872
873         if (!temp) {
874                 fprintf(stderr, "Memory allocation failed");
875                 return -ENOMEM;
876         }
877
878         ret = sprintf(temp, "%s/%s", basedir, filename);
879         if (ret < 0)
880                 goto error_free;
881
882         sysfsfp = fopen(temp, "r");
883         if (!sysfsfp) {
884                 ret = -errno;
885                 goto error_free;
886         }
887
888         errno = 0;
889         if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
890                 ret = errno ? -errno : -ENODATA;
891                 if (fclose(sysfsfp))
892                         perror("read_sysfs_posint(): Failed to close dir");
893
894                 goto error_free;
895         }
896
897         if (fclose(sysfsfp))
898                 ret = -errno;
899
900 error_free:
901         free(temp);
902
903         return ret;
904 }
905
906 /**
907  * read_sysfs_float() - read a float value from file
908  * @filename: name of file to read from
909  * @basedir: the sysfs directory in which the file is to be found
910  * @val: output the read float value
911  *
912  * Returns a value >= 0 on success, otherwise a negative error code.
913  **/
914 int read_sysfs_float(const char *filename, const char *basedir, float *val)
915 {
916         int ret = 0;
917         FILE  *sysfsfp;
918         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
919
920         if (!temp) {
921                 fprintf(stderr, "Memory allocation failed");
922                 return -ENOMEM;
923         }
924
925         ret = sprintf(temp, "%s/%s", basedir, filename);
926         if (ret < 0)
927                 goto error_free;
928
929         sysfsfp = fopen(temp, "r");
930         if (!sysfsfp) {
931                 ret = -errno;
932                 goto error_free;
933         }
934
935         errno = 0;
936         if (fscanf(sysfsfp, "%f\n", val) != 1) {
937                 ret = errno ? -errno : -ENODATA;
938                 if (fclose(sysfsfp))
939                         perror("read_sysfs_float(): Failed to close dir");
940
941                 goto error_free;
942         }
943
944         if (fclose(sysfsfp))
945                 ret = -errno;
946
947 error_free:
948         free(temp);
949
950         return ret;
951 }
952
953 /**
954  * read_sysfs_string() - read a string from file
955  * @filename: name of file to read from
956  * @basedir: the sysfs directory in which the file is to be found
957  * @str: output the read string
958  *
959  * Returns a value >= 0 on success, otherwise a negative error code.
960  **/
961 int read_sysfs_string(const char *filename, const char *basedir, char *str)
962 {
963         int ret = 0;
964         FILE  *sysfsfp;
965         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
966
967         if (!temp) {
968                 fprintf(stderr, "Memory allocation failed");
969                 return -ENOMEM;
970         }
971
972         ret = sprintf(temp, "%s/%s", basedir, filename);
973         if (ret < 0)
974                 goto error_free;
975
976         sysfsfp = fopen(temp, "r");
977         if (!sysfsfp) {
978                 ret = -errno;
979                 goto error_free;
980         }
981
982         errno = 0;
983         if (fscanf(sysfsfp, "%s\n", str) != 1) {
984                 ret = errno ? -errno : -ENODATA;
985                 if (fclose(sysfsfp))
986                         perror("read_sysfs_string(): Failed to close dir");
987
988                 goto error_free;
989         }
990
991         if (fclose(sysfsfp))
992                 ret = -errno;
993
994 error_free:
995         free(temp);
996
997         return ret;
998 }