tools: iio: iio_utils: remove unnecessary define guard
[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 #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 error_close_dir:
530         if (dp)
531                 if (closedir(dp) == -1)
532                         perror("build_channel_array(): Failed to close dir");
533
534 error_free_name:
535         free(scan_el_dir);
536
537         return ret;
538 }
539
540 int calc_digits(int num)
541 {
542         int count = 0;
543
544         while (num != 0) {
545                 num /= 10;
546                 count++;
547         }
548
549         return count;
550 }
551
552 /**
553  * find_type_by_name() - function to match top level types by name
554  * @name: top level type instance name
555  * @type: the type of top level instance being searched
556  *
557  * Returns the device number of a matched IIO device on success, otherwise a
558  * negative error code.
559  * Typical types this is used for are device and trigger.
560  **/
561 int find_type_by_name(const char *name, const char *type)
562 {
563         const struct dirent *ent;
564         int number, numstrlen, ret;
565
566         FILE *namefp;
567         DIR *dp;
568         char thisname[IIO_MAX_NAME_LENGTH];
569         char *filename;
570
571         dp = opendir(iio_dir);
572         if (!dp) {
573                 fprintf(stderr, "No industrialio devices available\n");
574                 return -ENODEV;
575         }
576
577         while (ent = readdir(dp), ent) {
578                 if (strcmp(ent->d_name, ".") != 0 &&
579                     strcmp(ent->d_name, "..") != 0 &&
580                     strlen(ent->d_name) > strlen(type) &&
581                     strncmp(ent->d_name, type, strlen(type)) == 0) {
582                         errno = 0;
583                         ret = sscanf(ent->d_name + strlen(type), "%d", &number);
584                         if (ret < 0) {
585                                 ret = -errno;
586                                 fprintf(stderr,
587                                         "failed to read element number\n");
588                                 goto error_close_dir;
589                         } else if (ret != 1) {
590                                 ret = -EIO;
591                                 fprintf(stderr,
592                                         "failed to match element number\n");
593                                 goto error_close_dir;
594                         }
595
596                         numstrlen = calc_digits(number);
597                         /* verify the next character is not a colon */
598                         if (strncmp(ent->d_name + strlen(type) + numstrlen,
599                             ":", 1) != 0) {
600                                 filename = malloc(strlen(iio_dir) + strlen(type)
601                                                   + numstrlen + 6);
602                                 if (!filename) {
603                                         ret = -ENOMEM;
604                                         goto error_close_dir;
605                                 }
606
607                                 ret = sprintf(filename, "%s%s%d/name", iio_dir,
608                                               type, number);
609                                 if (ret < 0) {
610                                         free(filename);
611                                         goto error_close_dir;
612                                 }
613
614                                 namefp = fopen(filename, "r");
615                                 if (!namefp) {
616                                         free(filename);
617                                         continue;
618                                 }
619
620                                 free(filename);
621                                 errno = 0;
622                                 if (fscanf(namefp, "%s", thisname) != 1) {
623                                         ret = errno ? -errno : -ENODATA;
624                                         goto error_close_dir;
625                                 }
626
627                                 if (fclose(namefp)) {
628                                         ret = -errno;
629                                         goto error_close_dir;
630                                 }
631
632                                 if (strcmp(name, thisname) == 0) {
633                                         if (closedir(dp) == -1)
634                                                 return -errno;
635
636                                         return number;
637                                 }
638                         }
639                 }
640         }
641         if (closedir(dp) == -1)
642                 return -errno;
643
644         return -ENODEV;
645
646 error_close_dir:
647         if (closedir(dp) == -1)
648                 perror("find_type_by_name(): Failed to close directory");
649
650         return ret;
651 }
652
653 static int _write_sysfs_int(const char *filename, const char *basedir, int val,
654                             int verify)
655 {
656         int ret = 0;
657         FILE *sysfsfp;
658         int test;
659         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
660
661         if (!temp)
662                 return -ENOMEM;
663
664         ret = sprintf(temp, "%s/%s", basedir, filename);
665         if (ret < 0)
666                 goto error_free;
667
668         sysfsfp = fopen(temp, "w");
669         if (!sysfsfp) {
670                 ret = -errno;
671                 fprintf(stderr, "failed to open %s\n", temp);
672                 goto error_free;
673         }
674
675         ret = fprintf(sysfsfp, "%d", val);
676         if (ret < 0) {
677                 if (fclose(sysfsfp))
678                         perror("_write_sysfs_int(): Failed to close dir");
679
680                 goto error_free;
681         }
682
683         if (fclose(sysfsfp)) {
684                 ret = -errno;
685                 goto error_free;
686         }
687
688         if (verify) {
689                 sysfsfp = fopen(temp, "r");
690                 if (!sysfsfp) {
691                         ret = -errno;
692                         fprintf(stderr, "failed to open %s\n", temp);
693                         goto error_free;
694                 }
695
696                 if (fscanf(sysfsfp, "%d", &test) != 1) {
697                         ret = errno ? -errno : -ENODATA;
698                         if (fclose(sysfsfp))
699                                 perror("_write_sysfs_int(): Failed to close dir");
700
701                         goto error_free;
702                 }
703
704                 if (fclose(sysfsfp)) {
705                         ret = -errno;
706                         goto error_free;
707                 }
708
709                 if (test != val) {
710                         fprintf(stderr,
711                                 "Possible failure in int write %d to %s/%s\n",
712                                 val, basedir, filename);
713                         ret = -1;
714                 }
715         }
716
717 error_free:
718         free(temp);
719         return ret;
720 }
721
722 /**
723  * write_sysfs_int() - write an integer value to a sysfs file
724  * @filename: name of the file to write to
725  * @basedir: the sysfs directory in which the file is to be found
726  * @val: integer value to write to file
727  *
728  * Returns a value >= 0 on success, otherwise a negative error code.
729  **/
730 int write_sysfs_int(const char *filename, const char *basedir, int val)
731 {
732         return _write_sysfs_int(filename, basedir, val, 0);
733 }
734
735 /**
736  * write_sysfs_int_and_verify() - write an integer value to a sysfs file
737  *                                and verify
738  * @filename: name of the file to write to
739  * @basedir: the sysfs directory in which the file is to be found
740  * @val: integer value to write to file
741  *
742  * Returns a value >= 0 on success, otherwise a negative error code.
743  **/
744 int write_sysfs_int_and_verify(const char *filename, const char *basedir,
745                                int val)
746 {
747         return _write_sysfs_int(filename, basedir, val, 1);
748 }
749
750 static int _write_sysfs_string(const char *filename, const char *basedir,
751                                const char *val, int verify)
752 {
753         int ret = 0;
754         FILE  *sysfsfp;
755         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
756
757         if (!temp) {
758                 fprintf(stderr, "Memory allocation failed\n");
759                 return -ENOMEM;
760         }
761
762         ret = sprintf(temp, "%s/%s", basedir, filename);
763         if (ret < 0)
764                 goto error_free;
765
766         sysfsfp = fopen(temp, "w");
767         if (!sysfsfp) {
768                 ret = -errno;
769                 fprintf(stderr, "Could not open %s\n", temp);
770                 goto error_free;
771         }
772
773         ret = fprintf(sysfsfp, "%s", val);
774         if (ret < 0) {
775                 if (fclose(sysfsfp))
776                         perror("_write_sysfs_string(): Failed to close dir");
777
778                 goto error_free;
779         }
780
781         if (fclose(sysfsfp)) {
782                 ret = -errno;
783                 goto error_free;
784         }
785
786         if (verify) {
787                 sysfsfp = fopen(temp, "r");
788                 if (!sysfsfp) {
789                         ret = -errno;
790                         fprintf(stderr, "Could not open file to verify\n");
791                         goto error_free;
792                 }
793
794                 if (fscanf(sysfsfp, "%s", temp) != 1) {
795                         ret = errno ? -errno : -ENODATA;
796                         if (fclose(sysfsfp))
797                                 perror("_write_sysfs_string(): Failed to close dir");
798
799                         goto error_free;
800                 }
801
802                 if (fclose(sysfsfp)) {
803                         ret = -errno;
804                         goto error_free;
805                 }
806
807                 if (strcmp(temp, val) != 0) {
808                         fprintf(stderr,
809                                 "Possible failure in string write of %s "
810                                 "Should be %s written to %s/%s\n", temp, val,
811                                 basedir, filename);
812                         ret = -1;
813                 }
814         }
815
816 error_free:
817         free(temp);
818
819         return ret;
820 }
821
822 /**
823  * write_sysfs_string_and_verify() - string write, readback and verify
824  * @filename: name of file to write to
825  * @basedir: the sysfs directory in which the file is to be found
826  * @val: the string to write
827  *
828  * Returns a value >= 0 on success, otherwise a negative error code.
829  **/
830 int write_sysfs_string_and_verify(const char *filename, const char *basedir,
831                                   const char *val)
832 {
833         return _write_sysfs_string(filename, basedir, val, 1);
834 }
835
836 /**
837  * write_sysfs_string() - write string to a sysfs file
838  * @filename: name of file to write to
839  * @basedir: the sysfs directory in which the file is to be found
840  * @val: the string to write
841  *
842  * Returns a value >= 0 on success, otherwise a negative error code.
843  **/
844 int write_sysfs_string(const char *filename, const char *basedir,
845                        const char *val)
846 {
847         return _write_sysfs_string(filename, basedir, val, 0);
848 }
849
850 /**
851  * read_sysfs_posint() - read an integer value from file
852  * @filename: name of file to read from
853  * @basedir: the sysfs directory in which the file is to be found
854  *
855  * Returns the read integer value >= 0 on success, otherwise a negative error
856  * code.
857  **/
858 int read_sysfs_posint(const char *filename, const char *basedir)
859 {
860         int ret;
861         FILE  *sysfsfp;
862         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
863
864         if (!temp) {
865                 fprintf(stderr, "Memory allocation failed");
866                 return -ENOMEM;
867         }
868
869         ret = sprintf(temp, "%s/%s", basedir, filename);
870         if (ret < 0)
871                 goto error_free;
872
873         sysfsfp = fopen(temp, "r");
874         if (!sysfsfp) {
875                 ret = -errno;
876                 goto error_free;
877         }
878
879         errno = 0;
880         if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
881                 ret = errno ? -errno : -ENODATA;
882                 if (fclose(sysfsfp))
883                         perror("read_sysfs_posint(): Failed to close dir");
884
885                 goto error_free;
886         }
887
888         if (fclose(sysfsfp))
889                 ret = -errno;
890
891 error_free:
892         free(temp);
893
894         return ret;
895 }
896
897 /**
898  * read_sysfs_float() - read a float value from file
899  * @filename: name of file to read from
900  * @basedir: the sysfs directory in which the file is to be found
901  * @val: output the read float value
902  *
903  * Returns a value >= 0 on success, otherwise a negative error code.
904  **/
905 int read_sysfs_float(const char *filename, const char *basedir, float *val)
906 {
907         int ret = 0;
908         FILE  *sysfsfp;
909         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
910
911         if (!temp) {
912                 fprintf(stderr, "Memory allocation failed");
913                 return -ENOMEM;
914         }
915
916         ret = sprintf(temp, "%s/%s", basedir, filename);
917         if (ret < 0)
918                 goto error_free;
919
920         sysfsfp = fopen(temp, "r");
921         if (!sysfsfp) {
922                 ret = -errno;
923                 goto error_free;
924         }
925
926         errno = 0;
927         if (fscanf(sysfsfp, "%f\n", val) != 1) {
928                 ret = errno ? -errno : -ENODATA;
929                 if (fclose(sysfsfp))
930                         perror("read_sysfs_float(): Failed to close dir");
931
932                 goto error_free;
933         }
934
935         if (fclose(sysfsfp))
936                 ret = -errno;
937
938 error_free:
939         free(temp);
940
941         return ret;
942 }
943
944 /**
945  * read_sysfs_string() - read a string from file
946  * @filename: name of file to read from
947  * @basedir: the sysfs directory in which the file is to be found
948  * @str: output the read string
949  *
950  * Returns a value >= 0 on success, otherwise a negative error code.
951  **/
952 int read_sysfs_string(const char *filename, const char *basedir, char *str)
953 {
954         int ret = 0;
955         FILE  *sysfsfp;
956         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
957
958         if (!temp) {
959                 fprintf(stderr, "Memory allocation failed");
960                 return -ENOMEM;
961         }
962
963         ret = sprintf(temp, "%s/%s", basedir, filename);
964         if (ret < 0)
965                 goto error_free;
966
967         sysfsfp = fopen(temp, "r");
968         if (!sysfsfp) {
969                 ret = -errno;
970                 goto error_free;
971         }
972
973         errno = 0;
974         if (fscanf(sysfsfp, "%s\n", str) != 1) {
975                 ret = errno ? -errno : -ENODATA;
976                 if (fclose(sysfsfp))
977                         perror("read_sysfs_string(): Failed to close dir");
978
979                 goto error_free;
980         }
981
982         if (fclose(sysfsfp))
983                 ret = -errno;
984
985 error_free:
986         free(temp);
987
988         return ret;
989 }