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.
10 /* Made up value to limit allocation sizes */
17 #define IIO_MAX_NAME_LENGTH 30
19 #define FORMAT_SCAN_ELEMENTS_DIR "%s:buffer0/scan_elements"
20 #define FORMAT_TYPE_FILE "%s_type"
22 const char *iio_dir
= "/sys/bus/iio/devices/";
25 * iioutils_break_up_name() - extract generic name from full channel name
26 * @full_name: the full channel name
27 * @generic_name: the output generic channel name
29 static int iioutils_break_up_name(const char *full_name
,
35 current
= strdup(full_name
);
36 working
= strtok(current
, "_\0");
48 *generic_name
= strdup(working
);
55 * struct iio_channel_info - information about a given channel
57 * @generic_name: general name for channel type
58 * @scale: scale factor to be applied for conversion to si units
59 * @offset: offset to be applied for conversion to si units
60 * @index: the channel index in the buffer output
61 * @bytes: number of bytes occupied in buffer output
62 * @mask: a bit mask for the raw output
63 * @is_signed: is the raw value stored signed
64 * @enabled: is this channel enabled
66 struct iio_channel_info
{
82 * iioutils_get_type() - find and process _type attribute data
83 * @is_signed: output whether channel is signed
84 * @bytes: output how many bytes the channel storage occupies
85 * @mask: output a bit mask for the raw data
86 * @device_dir: the iio device directory
87 * @name: the channel name
88 * @generic_name: the channel type name
90 inline int iioutils_get_type(unsigned *is_signed
,
95 const char *device_dir
,
97 const char *generic_name
)
102 char *scan_el_dir
, *builtname
, *builtname_generic
, *filename
= 0;
105 const struct dirent
*ent
;
107 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
112 ret
= asprintf(&builtname
, FORMAT_TYPE_FILE
, name
);
115 goto error_free_scan_el_dir
;
117 ret
= asprintf(&builtname_generic
, FORMAT_TYPE_FILE
, generic_name
);
120 goto error_free_builtname
;
123 dp
= opendir(scan_el_dir
);
126 goto error_free_builtname_generic
;
128 while (ent
= readdir(dp
), ent
!= NULL
)
130 * Do we allow devices to override a generic name with
133 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
134 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
135 ret
= asprintf(&filename
,
136 "%s/%s", scan_el_dir
, ent
->d_name
);
141 sysfsfp
= fopen(filename
, "r");
142 if (sysfsfp
== NULL
) {
143 printf("failed to open %s\n", filename
);
145 goto error_free_filename
;
148 "%c%u/%u>>%u", &signchar
, bits_used
,
151 if (*bits_used
== 64)
154 *mask
= (1 << *bits_used
) - 1;
165 error_free_builtname_generic
:
166 free(builtname_generic
);
167 error_free_builtname
:
169 error_free_scan_el_dir
:
175 inline int iioutils_get_param_float(float *output
,
176 const char *param_name
,
177 const char *device_dir
,
179 const char *generic_name
)
184 char *builtname
, *builtname_generic
;
185 char *filename
= NULL
;
186 const struct dirent
*ent
;
188 ret
= asprintf(&builtname
, "%s_%s", name
, param_name
);
193 ret
= asprintf(&builtname_generic
,
194 "%s_%s", generic_name
, param_name
);
197 goto error_free_builtname
;
199 dp
= opendir(device_dir
);
202 goto error_free_builtname_generic
;
204 while (ent
= readdir(dp
), ent
!= NULL
)
205 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
206 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
207 ret
= asprintf(&filename
,
208 "%s/%s", device_dir
, ent
->d_name
);
213 sysfsfp
= fopen(filename
, "r");
216 goto error_free_filename
;
218 fscanf(sysfsfp
, "%f", output
);
226 error_free_builtname_generic
:
227 free(builtname_generic
);
228 error_free_builtname
:
235 * bsort_channel_array_by_index() - reorder so that the array is in index order
239 inline void bsort_channel_array_by_index(struct iio_channel_info
**ci_array
,
243 struct iio_channel_info temp
;
246 for (x
= 0; x
< cnt
; x
++)
247 for (y
= 0; y
< (cnt
- 1); y
++)
248 if ((*ci_array
)[y
].index
> (*ci_array
)[y
+1].index
) {
249 temp
= (*ci_array
)[y
+ 1];
250 (*ci_array
)[y
+ 1] = (*ci_array
)[y
];
251 (*ci_array
)[y
] = temp
;
256 * build_channel_array() - function to figure out what channels are present
257 * @device_dir: the IIO device directory in sysfs
260 inline int build_channel_array(const char *device_dir
,
261 struct iio_channel_info
**ci_array
,
267 struct iio_channel_info
*current
;
269 const struct dirent
*ent
;
274 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
279 dp
= opendir(scan_el_dir
);
282 goto error_free_name
;
284 while (ent
= readdir(dp
), ent
!= NULL
)
285 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
287 ret
= asprintf(&filename
,
288 "%s/%s", scan_el_dir
, ent
->d_name
);
291 goto error_close_dir
;
293 sysfsfp
= fopen(filename
, "r");
294 if (sysfsfp
== NULL
) {
297 goto error_close_dir
;
299 fscanf(sysfsfp
, "%u", &ret
);
305 *ci_array
= malloc(sizeof(**ci_array
) * (*counter
));
306 if (*ci_array
== NULL
) {
308 goto error_close_dir
;
312 while (ent
= readdir(dp
), ent
!= NULL
) {
313 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
315 current
= &(*ci_array
)[count
++];
316 ret
= asprintf(&filename
,
317 "%s/%s", scan_el_dir
, ent
->d_name
);
320 /* decrement count to avoid freeing name */
322 goto error_cleanup_array
;
324 sysfsfp
= fopen(filename
, "r");
325 if (sysfsfp
== NULL
) {
328 goto error_cleanup_array
;
330 fscanf(sysfsfp
, "%u", ¤t
->enabled
);
333 if (!current
->enabled
) {
339 current
->scale
= 1.0;
341 current
->name
= strndup(ent
->d_name
,
342 strlen(ent
->d_name
) -
344 if (current
->name
== NULL
) {
347 goto error_cleanup_array
;
349 /* Get the generic and specific name elements */
350 ret
= iioutils_break_up_name(current
->name
,
351 ¤t
->generic_name
);
354 goto error_cleanup_array
;
356 ret
= asprintf(&filename
,
363 goto error_cleanup_array
;
365 sysfsfp
= fopen(filename
, "r");
366 fscanf(sysfsfp
, "%u", ¤t
->index
);
370 ret
= iioutils_get_param_float(¤t
->scale
,
374 current
->generic_name
);
376 goto error_cleanup_array
;
377 ret
= iioutils_get_param_float(¤t
->offset
,
381 current
->generic_name
);
383 goto error_cleanup_array
;
384 ret
= iioutils_get_type(¤t
->is_signed
,
391 current
->generic_name
);
396 /* reorder so that the array is in index order */
397 bsort_channel_array_by_index(ci_array
, *counter
);
402 for (i
= count
- 1; i
>= 0; i
--)
403 free((*ci_array
)[i
].name
);
414 * find_type_by_name() - function to match top level types by name
415 * @name: top level type instance name
416 * @type: the type of top level instance being sort
418 * Typical types this is used for are device and trigger.
420 inline int find_type_by_name(const char *name
, const char *type
)
422 const struct dirent
*ent
;
423 int number
, numstrlen
;
427 char thisname
[IIO_MAX_NAME_LENGTH
];
430 dp
= opendir(iio_dir
);
432 printf("No industrialio devices available");
436 while (ent
= readdir(dp
), ent
!= NULL
) {
437 if (strcmp(ent
->d_name
, ".") != 0 &&
438 strcmp(ent
->d_name
, "..") != 0 &&
439 strlen(ent
->d_name
) > strlen(type
) &&
440 strncmp(ent
->d_name
, type
, strlen(type
)) == 0) {
441 numstrlen
= sscanf(ent
->d_name
+ strlen(type
),
444 /* verify the next character is not a colon */
445 if (strncmp(ent
->d_name
+ strlen(type
) + numstrlen
,
448 filename
= malloc(strlen(iio_dir
)
452 if (filename
== NULL
)
454 sprintf(filename
, "%s%s%d/name",
458 nameFile
= fopen(filename
, "r");
462 fscanf(nameFile
, "%s", thisname
);
463 if (strcmp(name
, thisname
) == 0)
472 inline int _write_sysfs_int(char *filename
, char *basedir
, int val
, int verify
)
477 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
480 sprintf(temp
, "%s/%s", basedir
, filename
);
481 sysfsfp
= fopen(temp
, "w");
482 if (sysfsfp
== NULL
) {
483 printf("failed to open %s\n", temp
);
487 fprintf(sysfsfp
, "%d", val
);
490 sysfsfp
= fopen(temp
, "r");
491 if (sysfsfp
== NULL
) {
492 printf("failed to open %s\n", temp
);
496 fscanf(sysfsfp
, "%d", &test
);
498 printf("Possible failure in int write %d to %s%s\n",
510 int write_sysfs_int(char *filename
, char *basedir
, int val
)
512 return _write_sysfs_int(filename
, basedir
, val
, 0);
515 int write_sysfs_int_and_verify(char *filename
, char *basedir
, int val
)
517 return _write_sysfs_int(filename
, basedir
, val
, 1);
520 int _write_sysfs_string(char *filename
, char *basedir
, char *val
, int verify
)
524 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
526 printf("Memory allocation failed\n");
529 sprintf(temp
, "%s/%s", basedir
, filename
);
530 sysfsfp
= fopen(temp
, "w");
531 if (sysfsfp
== NULL
) {
532 printf("Could not open %s\n", temp
);
536 fprintf(sysfsfp
, "%s", val
);
539 sysfsfp
= fopen(temp
, "r");
540 if (sysfsfp
== NULL
) {
541 printf("could not open file to verify\n");
545 fscanf(sysfsfp
, "%s", temp
);
546 if (strcmp(temp
, val
) != 0) {
547 printf("Possible failure in string write of %s "
549 "written to %s\%s\n",
564 * write_sysfs_string_and_verify() - string write, readback and verify
565 * @filename: name of file to write to
566 * @basedir: the sysfs directory in which the file is to be found
567 * @val: the string to write
569 int write_sysfs_string_and_verify(char *filename
, char *basedir
, char *val
)
571 return _write_sysfs_string(filename
, basedir
, val
, 1);
574 int write_sysfs_string(char *filename
, char *basedir
, char *val
)
576 return _write_sysfs_string(filename
, basedir
, val
, 0);
579 int read_sysfs_posint(char *filename
, char *basedir
)
583 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
585 printf("Memory allocation failed");
588 sprintf(temp
, "%s/%s", basedir
, filename
);
589 sysfsfp
= fopen(temp
, "r");
590 if (sysfsfp
== NULL
) {
594 fscanf(sysfsfp
, "%d\n", &ret
);
601 int read_sysfs_float(char *filename
, char *basedir
, float *val
)
605 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
607 printf("Memory allocation failed");
610 sprintf(temp
, "%s/%s", basedir
, filename
);
611 sysfsfp
= fopen(temp
, "r");
612 if (sysfsfp
== NULL
) {
616 fscanf(sysfsfp
, "%f\n", val
);