1 /* IIO - useful set of util functionality
3 * Copyright (c) 2008 Jonathan Cameron
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.
19 #include "iio_utils.h"
21 const char *iio_dir = "/sys/bus/iio/devices/";
23 static char * const iio_direction[] = {
29 * iioutils_break_up_name() - extract generic name from full channel name
30 * @full_name: the full channel name
31 * @generic_name: the output generic channel name
33 * Returns 0 on success, or a negative error code if string extraction failed.
35 int iioutils_break_up_name(const char *full_name,
40 char *working, *prefix = "";
43 for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
44 if (!strncmp(full_name, iio_direction[i],
45 strlen(iio_direction[i]))) {
46 prefix = iio_direction[i];
50 current = strdup(full_name + strlen(prefix) + 1);
54 working = strtok(current, "_\0");
71 ret = asprintf(generic_name, "%s_%s", prefix, working);
74 return (ret == -1) ? -ENOMEM : 0;
78 * iioutils_get_type() - find and process _type attribute data
79 * @is_signed: output whether channel is signed
80 * @bytes: output how many bytes the channel storage occupies
81 * @bits_used: output number of valid bits of data
82 * @shift: output amount of bits to shift right data before applying bit mask
83 * @mask: output a bit mask for the raw data
84 * @be: output if data in big endian
85 * @device_dir: the IIO device directory
86 * @name: the channel name
87 * @generic_name: the channel type name
89 * Returns a value >= 0 on success, otherwise a negative error code.
91 int iioutils_get_type(unsigned *is_signed,
97 const char *device_dir,
99 const char *generic_name)
104 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
105 char signchar, endianchar;
107 const struct dirent *ent;
109 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
114 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
117 goto error_free_scan_el_dir;
119 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
122 goto error_free_builtname;
125 dp = opendir(scan_el_dir);
128 goto error_free_builtname_generic;
131 while (ent = readdir(dp), ent != NULL)
133 * Do we allow devices to override a generic name with
136 if ((strcmp(builtname, ent->d_name) == 0) ||
137 (strcmp(builtname_generic, ent->d_name) == 0)) {
138 ret = asprintf(&filename,
139 "%s/%s", scan_el_dir, ent->d_name);
144 sysfsfp = fopen(filename, "r");
145 if (sysfsfp == NULL) {
147 printf("failed to open %s\n", filename);
148 goto error_free_filename;
151 ret = fscanf(sysfsfp,
159 printf("failed to pass scan type description\n");
160 goto error_close_sysfsfp;
161 } else if (ret != 5) {
163 printf("scan type description didn't match\n");
164 goto error_close_sysfsfp;
166 *be = (endianchar == 'b');
168 if (*bits_used == 64)
171 *mask = (1 << *bits_used) - 1;
176 if (fclose(sysfsfp)) {
178 printf("Failed to close %s\n", filename);
179 goto error_free_filename;
190 perror("iioutils_get_type(): Failed to close file");
196 if (closedir(dp) == -1)
197 perror("iioutils_get_type(): Failed to close directory");
199 error_free_builtname_generic:
200 free(builtname_generic);
201 error_free_builtname:
203 error_free_scan_el_dir:
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
217 * Returns a value >= 0 on success, otherwise a negative error code.
219 int iioutils_get_param_float(float *output,
220 const char *param_name,
221 const char *device_dir,
223 const char *generic_name)
228 char *builtname, *builtname_generic;
229 char *filename = NULL;
230 const struct dirent *ent;
232 ret = asprintf(&builtname, "%s_%s", name, param_name);
237 ret = asprintf(&builtname_generic,
238 "%s_%s", generic_name, param_name);
241 goto error_free_builtname;
243 dp = opendir(device_dir);
246 goto error_free_builtname_generic;
249 while (ent = readdir(dp), ent != NULL)
250 if ((strcmp(builtname, ent->d_name) == 0) ||
251 (strcmp(builtname_generic, ent->d_name) == 0)) {
252 ret = asprintf(&filename,
253 "%s/%s", device_dir, ent->d_name);
258 sysfsfp = fopen(filename, "r");
261 goto error_free_filename;
264 if (fscanf(sysfsfp, "%f", output) != 1)
265 ret = errno ? -errno : -ENODATA;
273 if (closedir(dp) == -1)
274 perror("iioutils_get_param_float(): Failed to close directory");
276 error_free_builtname_generic:
277 free(builtname_generic);
278 error_free_builtname:
285 * bsort_channel_array_by_index() - sort the array in index order
286 * @ci_array: the iio_channel_info array to be sorted
287 * @cnt: the amount of array elements
290 void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
294 struct iio_channel_info temp;
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;
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
312 * Returns 0 on success, otherwise a negative error code.
314 int build_channel_array(const char *device_dir,
315 struct iio_channel_info **ci_array,
321 struct iio_channel_info *current;
323 const struct dirent *ent;
328 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
333 dp = opendir(scan_el_dir);
336 goto error_free_name;
338 while (ent = readdir(dp), ent != NULL)
339 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
341 ret = asprintf(&filename,
342 "%s/%s", scan_el_dir, ent->d_name);
345 goto error_close_dir;
347 sysfsfp = fopen(filename, "r");
348 if (sysfsfp == NULL) {
351 goto error_close_dir;
354 if (fscanf(sysfsfp, "%i", &ret) != 1) {
355 ret = errno ? -errno : -ENODATA;
357 perror("build_channel_array(): Failed to close file");
360 goto error_close_dir;
365 if (fclose(sysfsfp)) {
368 goto error_close_dir;
373 *ci_array = malloc(sizeof(**ci_array) * (*counter));
374 if (*ci_array == NULL) {
376 goto error_close_dir;
380 while (ent = readdir(dp), ent != NULL) {
381 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
383 int current_enabled = 0;
385 current = &(*ci_array)[count++];
386 ret = asprintf(&filename,
387 "%s/%s", scan_el_dir, ent->d_name);
390 /* decrement count to avoid freeing name */
392 goto error_cleanup_array;
394 sysfsfp = fopen(filename, "r");
395 if (sysfsfp == NULL) {
399 goto error_cleanup_array;
402 if (fscanf(sysfsfp, "%i", ¤t_enabled) != 1) {
403 ret = errno ? -errno : -ENODATA;
406 goto error_cleanup_array;
409 if (fclose(sysfsfp)) {
413 goto error_cleanup_array;
416 if (!current_enabled) {
422 current->scale = 1.0;
424 current->name = strndup(ent->d_name,
425 strlen(ent->d_name) -
427 if (current->name == NULL) {
431 goto error_cleanup_array;
433 /* Get the generic and specific name elements */
434 ret = iioutils_break_up_name(current->name,
435 ¤t->generic_name);
440 goto error_cleanup_array;
442 ret = asprintf(&filename,
449 goto error_cleanup_array;
451 sysfsfp = fopen(filename, "r");
452 if (sysfsfp == NULL) {
454 printf("failed to open %s\n", filename);
456 goto error_cleanup_array;
460 if (fscanf(sysfsfp, "%u", ¤t->index) != 1) {
461 ret = errno ? -errno : -ENODATA;
463 perror("build_channel_array(): Failed to close file");
466 goto error_cleanup_array;
469 if (fclose(sysfsfp)) {
472 goto error_cleanup_array;
477 ret = iioutils_get_param_float(¤t->scale,
481 current->generic_name);
483 goto error_cleanup_array;
484 ret = iioutils_get_param_float(¤t->offset,
488 current->generic_name);
490 goto error_cleanup_array;
491 ret = iioutils_get_type(¤t->is_signed,
499 current->generic_name);
501 goto error_cleanup_array;
505 if (closedir(dp) == -1) {
507 goto error_cleanup_array;
511 /* reorder so that the array is in index order */
512 bsort_channel_array_by_index(ci_array, *counter);
517 for (i = count - 1; i >= 0; i--) {
518 free((*ci_array)[i].name);
519 free((*ci_array)[i].generic_name);
524 if (closedir(dp) == -1)
525 perror("build_channel_array(): Failed to close dir");
533 int calc_digits(int num)
546 * find_type_by_name() - function to match top level types by name
547 * @name: top level type instance name
548 * @type: the type of top level instance being searched
550 * Returns the device number of a matched IIO device on success, otherwise a
551 * negative error code.
552 * Typical types this is used for are device and trigger.
554 int find_type_by_name(const char *name, const char *type)
556 const struct dirent *ent;
557 int number, numstrlen, ret;
561 char thisname[IIO_MAX_NAME_LENGTH];
564 dp = opendir(iio_dir);
566 printf("No industrialio devices available\n");
570 while (ent = readdir(dp), ent != NULL) {
571 if (strcmp(ent->d_name, ".") != 0 &&
572 strcmp(ent->d_name, "..") != 0 &&
573 strlen(ent->d_name) > strlen(type) &&
574 strncmp(ent->d_name, type, strlen(type)) == 0) {
576 ret = sscanf(ent->d_name + strlen(type), "%d", &number);
579 printf("failed to read element number\n");
580 goto error_close_dir;
581 } else if (ret != 1) {
583 printf("failed to match element number\n");
584 goto error_close_dir;
587 numstrlen = calc_digits(number);
588 /* verify the next character is not a colon */
589 if (strncmp(ent->d_name + strlen(type) + numstrlen,
592 filename = malloc(strlen(iio_dir)
596 if (filename == NULL) {
598 goto error_close_dir;
601 ret = sprintf(filename, "%s%s%d/name", iio_dir,
605 goto error_close_dir;
608 nameFile = fopen(filename, "r");
615 if (fscanf(nameFile, "%s", thisname) != 1) {
616 ret = errno ? -errno : -ENODATA;
617 goto error_close_dir;
620 if (fclose(nameFile)) {
622 goto error_close_dir;
625 if (strcmp(name, thisname) == 0) {
626 if (closedir(dp) == -1)
633 if (closedir(dp) == -1)
639 if (closedir(dp) == -1)
640 perror("find_type_by_name(): Failed to close directory");
644 static int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
649 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
653 ret = sprintf(temp, "%s/%s", basedir, filename);
657 sysfsfp = fopen(temp, "w");
658 if (sysfsfp == NULL) {
660 printf("failed to open %s\n", temp);
663 ret = fprintf(sysfsfp, "%d", val);
666 perror("_write_sysfs_int(): Failed to close dir");
671 if (fclose(sysfsfp)) {
677 sysfsfp = fopen(temp, "r");
678 if (sysfsfp == NULL) {
680 printf("failed to open %s\n", temp);
683 if (fscanf(sysfsfp, "%d", &test) != 1) {
684 ret = errno ? -errno : -ENODATA;
686 perror("_write_sysfs_int(): Failed to close dir");
691 if (fclose(sysfsfp)) {
697 printf("Possible failure in int write %d to %s%s\n",
710 * write_sysfs_int() - write an integer value to a sysfs file
711 * @filename: name of the file to write to
712 * @basedir: the sysfs directory in which the file is to be found
713 * @val: integer value to write to file
715 * Returns a value >= 0 on success, otherwise a negative error code.
717 int write_sysfs_int(char *filename, char *basedir, int val)
719 return _write_sysfs_int(filename, basedir, val, 0);
723 * write_sysfs_int_and_verify() - write an integer value to a sysfs file
725 * @filename: name of the file to write to
726 * @basedir: the sysfs directory in which the file is to be found
727 * @val: integer value to write to file
729 * Returns a value >= 0 on success, otherwise a negative error code.
731 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
733 return _write_sysfs_int(filename, basedir, val, 1);
736 static int _write_sysfs_string(char *filename, char *basedir, char *val,
741 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
744 printf("Memory allocation failed\n");
747 ret = sprintf(temp, "%s/%s", basedir, filename);
751 sysfsfp = fopen(temp, "w");
752 if (sysfsfp == NULL) {
754 printf("Could not open %s\n", temp);
757 ret = fprintf(sysfsfp, "%s", val);
760 perror("_write_sysfs_string(): Failed to close dir");
765 if (fclose(sysfsfp)) {
771 sysfsfp = fopen(temp, "r");
772 if (sysfsfp == NULL) {
774 printf("could not open file to verify\n");
777 if (fscanf(sysfsfp, "%s", temp) != 1) {
778 ret = errno ? -errno : -ENODATA;
780 perror("_write_sysfs_string(): Failed to close dir");
785 if (fclose(sysfsfp)) {
790 if (strcmp(temp, val) != 0) {
791 printf("Possible failure in string write of %s "
793 "written to %s\%s\n",
808 * write_sysfs_string_and_verify() - string write, readback and verify
809 * @filename: name of file to write to
810 * @basedir: the sysfs directory in which the file is to be found
811 * @val: the string to write
813 * Returns a value >= 0 on success, otherwise a negative error code.
815 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
817 return _write_sysfs_string(filename, basedir, val, 1);
821 * write_sysfs_string() - write string to a sysfs file
822 * @filename: name of file to write to
823 * @basedir: the sysfs directory in which the file is to be found
824 * @val: the string to write
826 * Returns a value >= 0 on success, otherwise a negative error code.
828 int write_sysfs_string(char *filename, char *basedir, char *val)
830 return _write_sysfs_string(filename, basedir, val, 0);
834 * read_sysfs_posint() - read an integer value from file
835 * @filename: name of file to read from
836 * @basedir: the sysfs directory in which the file is to be found
838 * Returns the read integer value >= 0 on success, otherwise a negative error
841 int read_sysfs_posint(char *filename, char *basedir)
845 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
848 printf("Memory allocation failed");
851 ret = sprintf(temp, "%s/%s", basedir, filename);
855 sysfsfp = fopen(temp, "r");
856 if (sysfsfp == NULL) {
861 if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
862 ret = errno ? -errno : -ENODATA;
864 perror("read_sysfs_posint(): Failed to close dir");
878 * read_sysfs_float() - read a float value from file
879 * @filename: name of file to read from
880 * @basedir: the sysfs directory in which the file is to be found
881 * @val: output the read float value
883 * Returns a value >= 0 on success, otherwise a negative error code.
885 int read_sysfs_float(char *filename, char *basedir, float *val)
889 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
892 printf("Memory allocation failed");
895 ret = sprintf(temp, "%s/%s", basedir, filename);
899 sysfsfp = fopen(temp, "r");
900 if (sysfsfp == NULL) {
905 if (fscanf(sysfsfp, "%f\n", val) != 1) {
906 ret = errno ? -errno : -ENODATA;
908 perror("read_sysfs_float(): Failed to close dir");
922 * read_sysfs_string() - read a string from file
923 * @filename: name of file to read from
924 * @basedir: the sysfs directory in which the file is to be found
925 * @str: output the read string
927 * Returns a value >= 0 on success, otherwise a negative error code.
929 int read_sysfs_string(const char *filename, const char *basedir, char *str)
933 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
936 printf("Memory allocation failed");
939 ret = sprintf(temp, "%s/%s", basedir, filename);
943 sysfsfp = fopen(temp, "r");
944 if (sysfsfp == NULL) {
949 if (fscanf(sysfsfp, "%s\n", str) != 1) {
950 ret = errno ? -errno : -ENODATA;
952 perror("read_sysfs_string(): Failed to close dir");
965 #endif /* _IIO_UTILS_H */