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