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 int iioutils_break_up_name(const char *full_name
,
38 char *working
, *prefix
= "";
41 for (i
= 0; i
< sizeof(iio_direction
) / sizeof(iio_direction
[0]); i
++)
42 if (!strncmp(full_name
, iio_direction
[i
],
43 strlen(iio_direction
[i
]))) {
44 prefix
= iio_direction
[i
];
48 current
= strdup(full_name
+ strlen(prefix
) + 1);
49 working
= strtok(current
, "_\0");
62 asprintf(generic_name
, "%s_%s", prefix
, working
);
69 * iioutils_get_type() - find and process _type attribute data
70 * @is_signed: output whether channel is signed
71 * @bytes: output how many bytes the channel storage occupies
72 * @mask: output a bit mask for the raw data
74 * @device_dir: the iio device directory
75 * @name: the channel name
76 * @generic_name: the channel type name
78 int iioutils_get_type(unsigned *is_signed
,
84 const char *device_dir
,
86 const char *generic_name
)
91 char *scan_el_dir
, *builtname
, *builtname_generic
, *filename
= 0;
92 char signchar
, endianchar
;
94 const struct dirent
*ent
;
96 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
101 ret
= asprintf(&builtname
, FORMAT_TYPE_FILE
, name
);
104 goto error_free_scan_el_dir
;
106 ret
= asprintf(&builtname_generic
, FORMAT_TYPE_FILE
, generic_name
);
109 goto error_free_builtname
;
112 dp
= opendir(scan_el_dir
);
115 goto error_free_builtname_generic
;
117 while (ent
= readdir(dp
), ent
!= NULL
)
119 * Do we allow devices to override a generic name with
122 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
123 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
124 ret
= asprintf(&filename
,
125 "%s/%s", scan_el_dir
, ent
->d_name
);
130 sysfsfp
= fopen(filename
, "r");
131 if (sysfsfp
== NULL
) {
133 printf("failed to open %s\n", filename
);
134 goto error_free_filename
;
137 ret
= fscanf(sysfsfp
,
145 printf("failed to pass scan type description\n");
146 goto error_close_sysfsfp
;
147 } else if (ret
!= 5) {
149 printf("scan type description didn't match\n");
150 goto error_close_sysfsfp
;
152 *be
= (endianchar
== 'b');
154 if (*bits_used
== 64)
157 *mask
= (1 << *bits_used
) - 1;
176 error_free_builtname_generic
:
177 free(builtname_generic
);
178 error_free_builtname
:
180 error_free_scan_el_dir
:
186 int iioutils_get_param_float(float *output
,
187 const char *param_name
,
188 const char *device_dir
,
190 const char *generic_name
)
195 char *builtname
, *builtname_generic
;
196 char *filename
= NULL
;
197 const struct dirent
*ent
;
199 ret
= asprintf(&builtname
, "%s_%s", name
, param_name
);
204 ret
= asprintf(&builtname_generic
,
205 "%s_%s", generic_name
, param_name
);
208 goto error_free_builtname
;
210 dp
= opendir(device_dir
);
213 goto error_free_builtname_generic
;
215 while (ent
= readdir(dp
), ent
!= NULL
)
216 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
217 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
218 ret
= asprintf(&filename
,
219 "%s/%s", device_dir
, ent
->d_name
);
224 sysfsfp
= fopen(filename
, "r");
227 goto error_free_filename
;
229 fscanf(sysfsfp
, "%f", output
);
237 error_free_builtname_generic
:
238 free(builtname_generic
);
239 error_free_builtname
:
246 * bsort_channel_array_by_index() - reorder so that the array is in index order
250 void bsort_channel_array_by_index(struct iio_channel_info
**ci_array
,
254 struct iio_channel_info temp
;
257 for (x
= 0; x
< cnt
; x
++)
258 for (y
= 0; y
< (cnt
- 1); y
++)
259 if ((*ci_array
)[y
].index
> (*ci_array
)[y
+1].index
) {
260 temp
= (*ci_array
)[y
+ 1];
261 (*ci_array
)[y
+ 1] = (*ci_array
)[y
];
262 (*ci_array
)[y
] = temp
;
267 * build_channel_array() - function to figure out what channels are present
268 * @device_dir: the IIO device directory in sysfs
271 int build_channel_array(const char *device_dir
,
272 struct iio_channel_info
**ci_array
,
278 struct iio_channel_info
*current
;
280 const struct dirent
*ent
;
285 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
290 dp
= opendir(scan_el_dir
);
293 goto error_free_name
;
295 while (ent
= readdir(dp
), ent
!= NULL
)
296 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
298 ret
= asprintf(&filename
,
299 "%s/%s", scan_el_dir
, ent
->d_name
);
302 goto error_close_dir
;
304 sysfsfp
= fopen(filename
, "r");
305 if (sysfsfp
== NULL
) {
308 goto error_close_dir
;
310 fscanf(sysfsfp
, "%i", &ret
);
316 *ci_array
= malloc(sizeof(**ci_array
) * (*counter
));
317 if (*ci_array
== NULL
) {
319 goto error_close_dir
;
323 while (ent
= readdir(dp
), ent
!= NULL
) {
324 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
326 int current_enabled
= 0;
328 current
= &(*ci_array
)[count
++];
329 ret
= asprintf(&filename
,
330 "%s/%s", scan_el_dir
, ent
->d_name
);
333 /* decrement count to avoid freeing name */
335 goto error_cleanup_array
;
337 sysfsfp
= fopen(filename
, "r");
338 if (sysfsfp
== NULL
) {
342 goto error_cleanup_array
;
344 fscanf(sysfsfp
, "%i", ¤t_enabled
);
347 if (!current_enabled
) {
353 current
->scale
= 1.0;
355 current
->name
= strndup(ent
->d_name
,
356 strlen(ent
->d_name
) -
358 if (current
->name
== NULL
) {
362 goto error_cleanup_array
;
364 /* Get the generic and specific name elements */
365 ret
= iioutils_break_up_name(current
->name
,
366 ¤t
->generic_name
);
371 goto error_cleanup_array
;
373 ret
= asprintf(&filename
,
380 goto error_cleanup_array
;
382 sysfsfp
= fopen(filename
, "r");
383 fscanf(sysfsfp
, "%u", ¤t
->index
);
387 ret
= iioutils_get_param_float(¤t
->scale
,
391 current
->generic_name
);
393 goto error_cleanup_array
;
394 ret
= iioutils_get_param_float(¤t
->offset
,
398 current
->generic_name
);
400 goto error_cleanup_array
;
401 ret
= iioutils_get_type(¤t
->is_signed
,
409 current
->generic_name
);
415 /* reorder so that the array is in index order */
416 bsort_channel_array_by_index(ci_array
, *counter
);
421 for (i
= count
- 1; i
>= 0; i
--) {
422 free((*ci_array
)[i
].name
);
423 free((*ci_array
)[i
].generic_name
);
435 * find_type_by_name() - function to match top level types by name
436 * @name: top level type instance name
437 * @type: the type of top level instance being sort
439 * Typical types this is used for are device and trigger.
441 int find_type_by_name(const char *name
, const char *type
)
443 const struct dirent
*ent
;
444 int number
, numstrlen
;
448 char thisname
[IIO_MAX_NAME_LENGTH
];
451 dp
= opendir(iio_dir
);
453 printf("No industrialio devices available\n");
457 while (ent
= readdir(dp
), ent
!= NULL
) {
458 if (strcmp(ent
->d_name
, ".") != 0 &&
459 strcmp(ent
->d_name
, "..") != 0 &&
460 strlen(ent
->d_name
) > strlen(type
) &&
461 strncmp(ent
->d_name
, type
, strlen(type
)) == 0) {
462 numstrlen
= sscanf(ent
->d_name
+ strlen(type
),
465 /* verify the next character is not a colon */
466 if (strncmp(ent
->d_name
+ strlen(type
) + numstrlen
,
469 filename
= malloc(strlen(iio_dir
)
473 if (filename
== NULL
) {
477 sprintf(filename
, "%s%s%d/name",
481 nameFile
= fopen(filename
, "r");
487 fscanf(nameFile
, "%s", thisname
);
489 if (strcmp(name
, thisname
) == 0) {
500 int _write_sysfs_int(char *filename
, char *basedir
, int val
, int verify
)
505 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
509 sprintf(temp
, "%s/%s", basedir
, filename
);
510 sysfsfp
= fopen(temp
, "w");
511 if (sysfsfp
== NULL
) {
513 printf("failed to open %s\n", temp
);
516 fprintf(sysfsfp
, "%d", val
);
519 sysfsfp
= fopen(temp
, "r");
520 if (sysfsfp
== NULL
) {
522 printf("failed to open %s\n", temp
);
525 fscanf(sysfsfp
, "%d", &test
);
528 printf("Possible failure in int write %d to %s%s\n",
540 int write_sysfs_int(char *filename
, char *basedir
, int val
)
542 return _write_sysfs_int(filename
, basedir
, val
, 0);
545 int write_sysfs_int_and_verify(char *filename
, char *basedir
, int val
)
547 return _write_sysfs_int(filename
, basedir
, val
, 1);
550 int _write_sysfs_string(char *filename
, char *basedir
, char *val
, int verify
)
554 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
557 printf("Memory allocation failed\n");
560 sprintf(temp
, "%s/%s", basedir
, filename
);
561 sysfsfp
= fopen(temp
, "w");
562 if (sysfsfp
== NULL
) {
564 printf("Could not open %s\n", temp
);
567 fprintf(sysfsfp
, "%s", val
);
570 sysfsfp
= fopen(temp
, "r");
571 if (sysfsfp
== NULL
) {
573 printf("could not open file to verify\n");
576 fscanf(sysfsfp
, "%s", temp
);
578 if (strcmp(temp
, val
) != 0) {
579 printf("Possible failure in string write of %s "
581 "written to %s\%s\n",
596 * write_sysfs_string_and_verify() - string write, readback and verify
597 * @filename: name of file to write to
598 * @basedir: the sysfs directory in which the file is to be found
599 * @val: the string to write
601 int write_sysfs_string_and_verify(char *filename
, char *basedir
, char *val
)
603 return _write_sysfs_string(filename
, basedir
, val
, 1);
606 int write_sysfs_string(char *filename
, char *basedir
, char *val
)
608 return _write_sysfs_string(filename
, basedir
, val
, 0);
611 int read_sysfs_posint(char *filename
, char *basedir
)
615 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
618 printf("Memory allocation failed");
621 sprintf(temp
, "%s/%s", basedir
, filename
);
622 sysfsfp
= fopen(temp
, "r");
623 if (sysfsfp
== NULL
) {
627 fscanf(sysfsfp
, "%d\n", &ret
);
634 int read_sysfs_float(char *filename
, char *basedir
, float *val
)
638 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
641 printf("Memory allocation failed");
644 sprintf(temp
, "%s/%s", basedir
, filename
);
645 sysfsfp
= fopen(temp
, "r");
646 if (sysfsfp
== NULL
) {
650 fscanf(sysfsfp
, "%f\n", val
);
657 int read_sysfs_string(const char *filename
, const char *basedir
, char *str
)
661 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
664 printf("Memory allocation failed");
667 sprintf(temp
, "%s/%s", basedir
, filename
);
668 sysfsfp
= fopen(temp
, "r");
669 if (sysfsfp
== NULL
) {
673 fscanf(sysfsfp
, "%s\n", str
);
680 #endif /* _IIO_UTILS_H */