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 IIO_EV_CLASS_BUFFER 0
20 #define IIO_BUFFER_EVENT_CODE(code) \
21 (IIO_EV_CLASS_BUFFER | (code << 8))
23 #define IIO_EVENT_CODE_RING_50_FULL IIO_BUFFER_EVENT_CODE(0)
24 #define IIO_EVENT_CODE_RING_75_FULL IIO_BUFFER_EVENT_CODE(1)
25 #define IIO_EVENT_CODE_RING_100_FULL IIO_BUFFER_EVENT_CODE(2)
28 #define FORMAT_SCAN_ELEMENTS_DIR "%s:buffer0/scan_elements"
29 #define FORMAT_TYPE_FILE "%s_type"
31 const char *iio_dir
= "/sys/bus/iio/devices/";
33 struct iio_event_data
{
39 * iioutils_break_up_name() - extract generic name from full channel name
40 * @full_name: the full channel name
41 * @generic_name: the output generic channel name
43 static int iioutils_break_up_name(const char *full_name
,
49 current
= strdup(full_name
);
50 working
= strtok(current
, "_\0");
62 *generic_name
= strdup(working
);
69 * struct iio_channel_info - information about a given channel
71 * @generic_name: general name for channel type
72 * @scale: scale factor to be applied for conversion to si units
73 * @offset: offset to be applied for conversion to si units
74 * @index: the channel index in the buffer output
75 * @bytes: number of bytes occupied in buffer output
76 * @mask: a bit mask for the raw output
77 * @is_signed: is the raw value stored signed
78 * @enabled: is this channel enabled
80 struct iio_channel_info
{
95 * iioutils_get_type() - find and process _type attribute data
96 * @is_signed: output whether channel is signed
97 * @bytes: output how many bytes the channel storage occupies
98 * @mask: output a bit mask for the raw data
99 * @device_dir: the iio device directory
100 * @name: the channel name
101 * @generic_name: the channel type name
103 inline int iioutils_get_type(unsigned *is_signed
,
107 const char *device_dir
,
109 const char *generic_name
)
114 char *scan_el_dir
, *builtname
, *builtname_generic
, *filename
= 0;
117 const struct dirent
*ent
;
119 ret
= asprintf(&scan_el_dir
, FORMAT_SCAN_ELEMENTS_DIR
, device_dir
);
124 ret
= asprintf(&builtname
, FORMAT_TYPE_FILE
, name
);
127 goto error_free_scan_el_dir
;
129 ret
= asprintf(&builtname_generic
, FORMAT_TYPE_FILE
, generic_name
);
132 goto error_free_builtname
;
135 dp
= opendir(scan_el_dir
);
138 goto error_free_builtname_generic
;
140 while (ent
= readdir(dp
), ent
!= NULL
)
142 * Do we allow devices to override a generic name with
145 if ((strcmp(builtname
, ent
->d_name
) == 0) ||
146 (strcmp(builtname_generic
, ent
->d_name
) == 0)) {
147 ret
= asprintf(&filename
,
148 "%s/%s", scan_el_dir
, ent
->d_name
);
153 sysfsfp
= fopen(filename
, "r");
154 if (sysfsfp
== NULL
) {
155 printf("failed to open %s\n", filename
);
157 goto error_free_filename
;
160 "%c%u/%u", &signchar
, bits_used
, &padint
);
162 if (*bits_used
== 64)
165 *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 inline 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 inline 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 inline 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
, "%u", &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 current
= &(*ci_array
)[count
++];
327 ret
= asprintf(&filename
,
328 "%s/%s", scan_el_dir
, ent
->d_name
);
331 /* decrement count to avoid freeing name */
333 goto error_cleanup_array
;
335 sysfsfp
= fopen(filename
, "r");
336 if (sysfsfp
== NULL
) {
339 goto error_cleanup_array
;
341 fscanf(sysfsfp
, "%u", ¤t
->enabled
);
344 if (!current
->enabled
) {
350 current
->scale
= 1.0;
352 current
->name
= strndup(ent
->d_name
,
353 strlen(ent
->d_name
) -
355 if (current
->name
== NULL
) {
358 goto error_cleanup_array
;
360 /* Get the generic and specific name elements */
361 ret
= iioutils_break_up_name(current
->name
,
362 ¤t
->generic_name
);
365 goto error_cleanup_array
;
367 ret
= asprintf(&filename
,
374 goto error_cleanup_array
;
376 sysfsfp
= fopen(filename
, "r");
377 fscanf(sysfsfp
, "%u", ¤t
->index
);
381 ret
= iioutils_get_param_float(¤t
->scale
,
385 current
->generic_name
);
387 goto error_cleanup_array
;
388 ret
= iioutils_get_param_float(¤t
->offset
,
392 current
->generic_name
);
394 goto error_cleanup_array
;
395 ret
= iioutils_get_type(¤t
->is_signed
,
401 current
->generic_name
);
406 /* reorder so that the array is in index order */
407 bsort_channel_array_by_index(ci_array
, *counter
);
412 for (i
= count
- 1; i
>= 0; i
--)
413 free((*ci_array
)[i
].name
);
424 * find_type_by_name() - function to match top level types by name
425 * @name: top level type instance name
426 * @type: the type of top level instance being sort
428 * Typical types this is used for are device and trigger.
430 inline int find_type_by_name(const char *name
, const char *type
)
432 const struct dirent
*ent
;
433 int number
, numstrlen
;
437 char thisname
[IIO_MAX_NAME_LENGTH
];
440 dp
= opendir(iio_dir
);
442 printf("No industrialio devices available");
446 while (ent
= readdir(dp
), ent
!= NULL
) {
447 if (strcmp(ent
->d_name
, ".") != 0 &&
448 strcmp(ent
->d_name
, "..") != 0 &&
449 strlen(ent
->d_name
) > strlen(type
) &&
450 strncmp(ent
->d_name
, type
, strlen(type
)) == 0) {
451 numstrlen
= sscanf(ent
->d_name
+ strlen(type
),
454 /* verify the next character is not a colon */
455 if (strncmp(ent
->d_name
+ strlen(type
) + numstrlen
,
458 filename
= malloc(strlen(iio_dir
)
462 if (filename
== NULL
)
464 sprintf(filename
, "%s%s%d/name",
468 nameFile
= fopen(filename
, "r");
472 fscanf(nameFile
, "%s", thisname
);
473 if (strcmp(name
, thisname
) == 0)
482 inline int _write_sysfs_int(char *filename
, char *basedir
, int val
, int verify
)
487 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
490 sprintf(temp
, "%s/%s", basedir
, filename
);
491 sysfsfp
= fopen(temp
, "w");
492 if (sysfsfp
== NULL
) {
493 printf("failed to open %s\n", temp
);
497 fprintf(sysfsfp
, "%d", val
);
500 sysfsfp
= fopen(temp
, "r");
501 if (sysfsfp
== NULL
) {
502 printf("failed to open %s\n", temp
);
506 fscanf(sysfsfp
, "%d", &test
);
508 printf("Possible failure in int write %d to %s%s\n",
520 int write_sysfs_int(char *filename
, char *basedir
, int val
)
522 return _write_sysfs_int(filename
, basedir
, val
, 0);
525 int write_sysfs_int_and_verify(char *filename
, char *basedir
, int val
)
527 return _write_sysfs_int(filename
, basedir
, val
, 1);
530 int _write_sysfs_string(char *filename
, char *basedir
, char *val
, int verify
)
534 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
536 printf("Memory allocation failed\n");
539 sprintf(temp
, "%s/%s", basedir
, filename
);
540 sysfsfp
= fopen(temp
, "w");
541 if (sysfsfp
== NULL
) {
542 printf("Could not open %s\n", temp
);
546 fprintf(sysfsfp
, "%s", val
);
549 sysfsfp
= fopen(temp
, "r");
550 if (sysfsfp
== NULL
) {
551 printf("could not open file to verify\n");
555 fscanf(sysfsfp
, "%s", temp
);
556 if (strcmp(temp
, val
) != 0) {
557 printf("Possible failure in string write of %s "
559 "written to %s\%s\n",
574 * write_sysfs_string_and_verify() - string write, readback and verify
575 * @filename: name of file to write to
576 * @basedir: the sysfs directory in which the file is to be found
577 * @val: the string to write
579 int write_sysfs_string_and_verify(char *filename
, char *basedir
, char *val
)
581 return _write_sysfs_string(filename
, basedir
, val
, 1);
584 int write_sysfs_string(char *filename
, char *basedir
, char *val
)
586 return _write_sysfs_string(filename
, basedir
, val
, 0);
589 int read_sysfs_posint(char *filename
, char *basedir
)
593 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
595 printf("Memory allocation failed");
598 sprintf(temp
, "%s/%s", basedir
, filename
);
599 sysfsfp
= fopen(temp
, "r");
600 if (sysfsfp
== NULL
) {
604 fscanf(sysfsfp
, "%d\n", &ret
);
611 int read_sysfs_float(char *filename
, char *basedir
, float *val
)
615 char *temp
= malloc(strlen(basedir
) + strlen(filename
) + 2);
617 printf("Memory allocation failed");
620 sprintf(temp
, "%s/%s", basedir
, filename
);
621 sysfsfp
= fopen(temp
, "r");
622 if (sysfsfp
== NULL
) {
626 fscanf(sysfsfp
, "%f\n", val
);