Linux Audio

Check our new training course

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