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.
18 /* Made up value to limit allocation sizes */
19 #define IIO_MAX_NAME_LENGTH 30
21 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
22 #define FORMAT_TYPE_FILE "%s_type"
24 const char *iio_dir
= "/sys/bus/iio/devices/";
27 * iioutils_break_up_name() - extract generic name from full channel name
28 * @full_name: the full channel name
29 * @generic_name: the output generic channel name
31 inline int iioutils_break_up_name(const char *full_name
,
37 current
= strdup(full_name
);
38 working
= strtok(current
, "_\0");
50 *generic_name
= strdup(working
);
57 * struct iio_channel_info - information about a given channel
59 * @generic_name: general name for channel type
60 * @scale: scale factor to be applied for conversion to si units
61 * @offset: offset to be applied for conversion to si units
62 * @index: the channel index in the buffer output
63 * @bytes: number of bytes occupied in buffer output
64 * @mask: a bit mask for the raw output
65 * @is_signed: is the raw value stored signed
66 * @enabled: is this channel enabled
68 struct iio_channel_info
{
85 * iioutils_get_type() - find and process _type attribute data
86 * @is_signed: output whether channel is signed
87 * @bytes: output how many bytes the channel storage occupies
88 * @mask: output a bit mask for the raw data
90 * @device_dir: the iio device directory
91 * @name: the channel name
92 * @generic_name: the channel type name
94 inline int iioutils_get_type(unsigned *is_signed
,
100 const char *device_dir
,
102 const char *generic_name
)
107 char *scan_el_dir
, *builtname
, *builtname_generic
, *filename
= 0;
108 char signchar
, endianchar
;
110 const struct dirent
*ent
;
112 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
117 ret
= asprintf(&builtname
, FORMAT_TYPE_FILE
, name
);
120 goto error_free_scan_el_dir
;
122 ret
= asprintf(&builtname_generic
, FORMAT_TYPE_FILE
, generic_name
);
125 goto error_free_builtname
;
128 dp
= opendir(scan_el_dir
);
131 goto error_free_builtname_generic
;
133 while (ent
= readdir(dp
), ent
!= NULL
)
135 * Do we allow devices to override a generic name with
138 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
139 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
140 ret
= asprintf(&filename
,
141 "%s/%s", scan_el_dir
, ent
->d_name
);
146 sysfsfp
= fopen(filename
, "r");
147 if (sysfsfp
== NULL
) {
148 printf("failed to open %s\n", filename
);
150 goto error_free_filename
;
153 ret
= fscanf(sysfsfp
,
160 printf("failed to pass scan type description\n");
163 *be
= (endianchar
== 'b');
165 if (*bits_used
== 64)
168 *mask
= (1 << *bits_used
) - 1;
183 error_free_builtname_generic
:
184 free(builtname_generic
);
185 error_free_builtname
:
187 error_free_scan_el_dir
:
193 inline int iioutils_get_param_float(float *output
,
194 const char *param_name
,
195 const char *device_dir
,
197 const char *generic_name
)
202 char *builtname
, *builtname_generic
;
203 char *filename
= NULL
;
204 const struct dirent
*ent
;
206 ret
= asprintf(&builtname
, "%s_%s", name
, param_name
);
211 ret
= asprintf(&builtname_generic
,
212 "%s_%s", generic_name
, param_name
);
215 goto error_free_builtname
;
217 dp
= opendir(device_dir
);
220 goto error_free_builtname_generic
;
222 while (ent
= readdir(dp
), ent
!= NULL
)
223 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
224 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
225 ret
= asprintf(&filename
,
226 "%s/%s", device_dir
, ent
->d_name
);
231 sysfsfp
= fopen(filename
, "r");
234 goto error_free_filename
;
236 fscanf(sysfsfp
, "%f", output
);
244 error_free_builtname_generic
:
245 free(builtname_generic
);
246 error_free_builtname
:
253 * bsort_channel_array_by_index() - reorder so that the array is in index order
257 inline void bsort_channel_array_by_index(struct iio_channel_info
**ci_array
,
261 struct iio_channel_info temp
;
264 for (x
= 0; x
< cnt
; x
++)
265 for (y
= 0; y
< (cnt
- 1); y
++)
266 if ((*ci_array
)[y
].index
> (*ci_array
)[y
+1].index
) {
267 temp
= (*ci_array
)[y
+ 1];
268 (*ci_array
)[y
+ 1] = (*ci_array
)[y
];
269 (*ci_array
)[y
] = temp
;
274 * build_channel_array() - function to figure out what channels are present
275 * @device_dir: the IIO device directory in sysfs
278 inline int build_channel_array(const char *device_dir
,
279 struct iio_channel_info
**ci_array
,
285 struct iio_channel_info
*current
;
287 const struct dirent
*ent
;
292 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
297 dp
= opendir(scan_el_dir
);
300 goto error_free_name
;
302 while (ent
= readdir(dp
), ent
!= NULL
)
303 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
305 ret
= asprintf(&filename
,
306 "%s/%s", scan_el_dir
, ent
->d_name
);
309 goto error_close_dir
;
311 sysfsfp
= fopen(filename
, "r");
312 if (sysfsfp
== NULL
) {
315 goto error_close_dir
;
317 fscanf(sysfsfp
, "%u", &ret
);
323 *ci_array
= malloc(sizeof(**ci_array
) * (*counter
));
324 if (*ci_array
== NULL
) {
326 goto error_close_dir
;
330 while (ent
= readdir(dp
), ent
!= NULL
) {
331 if (strcmp(ent
->d_name
+ strlen(ent
->d_name
) - strlen("_en"),
333 current
= &(*ci_array
)[count
++];
334 ret
= asprintf(&filename
,
335 "%s/%s", scan_el_dir
, ent
->d_name
);
338 /* decrement count to avoid freeing name */
340 goto error_cleanup_array
;
342 sysfsfp
= fopen(filename
, "r");
343 if (sysfsfp
== NULL
) {
346 goto error_cleanup_array
;
348 fscanf(sysfsfp
, "%u", ¤t
->enabled
);
351 if (!current
->enabled
) {
357 current
->scale
= 1.0;
359 current
->name
= strndup(ent
->d_name
,
360 strlen(ent
->d_name
) -
362 if (current
->name
== NULL
) {
365 goto error_cleanup_array
;
367 /* Get the generic and specific name elements */
368 ret
= iioutils_break_up_name(current
->name
,
369 ¤t
->generic_name
);
372 goto error_cleanup_array
;
374 ret
= asprintf(&filename
,
381 goto error_cleanup_array
;
383 sysfsfp
= fopen(filename
, "r");
384 fscanf(sysfsfp
, "%u", ¤t
->index
);
388 ret
= iioutils_get_param_float(¤t
->scale
,
392 current
->generic_name
);
394 goto error_cleanup_array
;
395 ret
= iioutils_get_param_float(¤t
->offset
,
399 current
->generic_name
);
401 goto error_cleanup_array
;
402 ret
= iioutils_get_type(¤t
->is_signed
,
410 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
);
433 * find_type_by_name() - function to match top level types by name
434 * @name: top level type instance name
435 * @type: the type of top level instance being sort
437 * Typical types this is used for are device and trigger.
439 inline int find_type_by_name(const char *name
, const char *type
)
441 const struct dirent
*ent
;
442 int number
, numstrlen
;
446 char thisname
[IIO_MAX_NAME_LENGTH
];
449 dp
= opendir(iio_dir
);
451 printf("No industrialio devices available");
455 while (ent
= readdir(dp
), ent
!= NULL
) {
456 if (strcmp(ent
->d_name
, ".") != 0 &&
457 strcmp(ent
->d_name
, "..") != 0 &&
458 strlen(ent
->d_name
) > strlen(type
) &&
459 strncmp(ent
->d_name
, type
, strlen(type
)) == 0) {
460 numstrlen
= sscanf(ent
->d_name
+ strlen(type
),
463 /* verify the next character is not a colon */
464 if (strncmp(ent
->d_name
+ strlen(type
) + numstrlen
,
467 filename
= malloc(strlen(iio_dir
)
471 if (filename
== NULL
)
473 sprintf(filename
, "%s%s%d/name",
477 nameFile
= fopen(filename
, "r");
481 fscanf(nameFile
, "%s", thisname
);
482 if (strcmp(name
, thisname
) == 0)
491 inline int _write_sysfs_int(char *filename
, char *basedir
, int val
, int verify
)
496 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
499 sprintf(temp
, "%s/%s", basedir
, filename
);
500 sysfsfp
= fopen(temp
, "w");
501 if (sysfsfp
== NULL
) {
502 printf("failed to open %s\n", temp
);
506 fprintf(sysfsfp
, "%d", val
);
509 sysfsfp
= fopen(temp
, "r");
510 if (sysfsfp
== NULL
) {
511 printf("failed to open %s\n", temp
);
515 fscanf(sysfsfp
, "%d", &test
);
517 printf("Possible failure in int write %d to %s%s\n",
529 int write_sysfs_int(char *filename
, char *basedir
, int val
)
531 return _write_sysfs_int(filename
, basedir
, val
, 0);
534 int write_sysfs_int_and_verify(char *filename
, char *basedir
, int val
)
536 return _write_sysfs_int(filename
, basedir
, val
, 1);
539 int _write_sysfs_string(char *filename
, char *basedir
, char *val
, int verify
)
543 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
545 printf("Memory allocation failed\n");
548 sprintf(temp
, "%s/%s", basedir
, filename
);
549 sysfsfp
= fopen(temp
, "w");
550 if (sysfsfp
== NULL
) {
551 printf("Could not open %s\n", temp
);
555 fprintf(sysfsfp
, "%s", val
);
558 sysfsfp
= fopen(temp
, "r");
559 if (sysfsfp
== NULL
) {
560 printf("could not open file to verify\n");
564 fscanf(sysfsfp
, "%s", temp
);
565 if (strcmp(temp
, val
) != 0) {
566 printf("Possible failure in string write of %s "
568 "written to %s\%s\n",
583 * write_sysfs_string_and_verify() - string write, readback and verify
584 * @filename: name of file to write to
585 * @basedir: the sysfs directory in which the file is to be found
586 * @val: the string to write
588 int write_sysfs_string_and_verify(char *filename
, char *basedir
, char *val
)
590 return _write_sysfs_string(filename
, basedir
, val
, 1);
593 int write_sysfs_string(char *filename
, char *basedir
, char *val
)
595 return _write_sysfs_string(filename
, basedir
, val
, 0);
598 int read_sysfs_posint(char *filename
, char *basedir
)
602 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
604 printf("Memory allocation failed");
607 sprintf(temp
, "%s/%s", basedir
, filename
);
608 sysfsfp
= fopen(temp
, "r");
609 if (sysfsfp
== NULL
) {
613 fscanf(sysfsfp
, "%d\n", &ret
);
620 int read_sysfs_float(char *filename
, char *basedir
, float *val
)
624 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
626 printf("Memory allocation failed");
629 sprintf(temp
, "%s/%s", basedir
, filename
);
630 sysfsfp
= fopen(temp
, "r");
631 if (sysfsfp
== NULL
) {
635 fscanf(sysfsfp
, "%f\n", val
);