staging: iio: quell asprintf() warning, missing #includes
[deliverable/linux.git] / drivers / staging / iio / Documentation / iio_utils.h
1 /* IIO - useful set of util functionality
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
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.
8 */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <dirent.h>
16 #include <errno.h>
17
18 /* Made up value to limit allocation sizes */
19 #define IIO_MAX_NAME_LENGTH 30
20
21 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
22 #define FORMAT_TYPE_FILE "%s_type"
23
24 const char *iio_dir = "/sys/bus/iio/devices/";
25
26 /**
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
30 **/
31 inline int iioutils_break_up_name(const char *full_name,
32 char **generic_name)
33 {
34 char *current;
35 char *w, *r;
36 char *working;
37 current = strdup(full_name);
38 working = strtok(current, "_\0");
39 w = working;
40 r = working;
41
42 while (*r != '\0') {
43 if (!isdigit(*r)) {
44 *w = *r;
45 w++;
46 }
47 r++;
48 }
49 *w = '\0';
50 *generic_name = strdup(working);
51 free(current);
52
53 return 0;
54 }
55
56 /**
57 * struct iio_channel_info - information about a given channel
58 * @name: channel name
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
67 **/
68 struct iio_channel_info {
69 char *name;
70 char *generic_name;
71 float scale;
72 float offset;
73 unsigned index;
74 unsigned bytes;
75 unsigned bits_used;
76 unsigned shift;
77 uint64_t mask;
78 unsigned be;
79 unsigned is_signed;
80 unsigned enabled;
81 unsigned location;
82 };
83
84 /**
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
89 * @be: big endian
90 * @device_dir: the iio device directory
91 * @name: the channel name
92 * @generic_name: the channel type name
93 **/
94 inline int iioutils_get_type(unsigned *is_signed,
95 unsigned *bytes,
96 unsigned *bits_used,
97 unsigned *shift,
98 uint64_t *mask,
99 unsigned *be,
100 const char *device_dir,
101 const char *name,
102 const char *generic_name)
103 {
104 FILE *sysfsfp;
105 int ret;
106 DIR *dp;
107 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
108 char signchar, endianchar;
109 unsigned padint;
110 const struct dirent *ent;
111
112 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
113 if (ret < 0) {
114 ret = -ENOMEM;
115 goto error_ret;
116 }
117 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
118 if (ret < 0) {
119 ret = -ENOMEM;
120 goto error_free_scan_el_dir;
121 }
122 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
123 if (ret < 0) {
124 ret = -ENOMEM;
125 goto error_free_builtname;
126 }
127
128 dp = opendir(scan_el_dir);
129 if (dp == NULL) {
130 ret = -errno;
131 goto error_free_builtname_generic;
132 }
133 while (ent = readdir(dp), ent != NULL)
134 /*
135 * Do we allow devices to override a generic name with
136 * a specific one?
137 */
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);
142 if (ret < 0) {
143 ret = -ENOMEM;
144 goto error_closedir;
145 }
146 sysfsfp = fopen(filename, "r");
147 if (sysfsfp == NULL) {
148 printf("failed to open %s\n", filename);
149 ret = -errno;
150 goto error_free_filename;
151 }
152
153 ret = fscanf(sysfsfp,
154 "%ce:%c%u/%u>>%u",
155 &endianchar,
156 &signchar,
157 bits_used,
158 &padint, shift);
159 if (ret < 0) {
160 printf("failed to pass scan type description\n");
161 return ret;
162 }
163 *be = (endianchar == 'b');
164 *bytes = padint / 8;
165 if (*bits_used == 64)
166 *mask = ~0;
167 else
168 *mask = (1 << *bits_used) - 1;
169 if (signchar == 's')
170 *is_signed = 1;
171 else
172 *is_signed = 0;
173 fclose(sysfsfp);
174 free(filename);
175
176 filename = 0;
177 }
178 error_free_filename:
179 if (filename)
180 free(filename);
181 error_closedir:
182 closedir(dp);
183 error_free_builtname_generic:
184 free(builtname_generic);
185 error_free_builtname:
186 free(builtname);
187 error_free_scan_el_dir:
188 free(scan_el_dir);
189 error_ret:
190 return ret;
191 }
192
193 inline int iioutils_get_param_float(float *output,
194 const char *param_name,
195 const char *device_dir,
196 const char *name,
197 const char *generic_name)
198 {
199 FILE *sysfsfp;
200 int ret;
201 DIR *dp;
202 char *builtname, *builtname_generic;
203 char *filename = NULL;
204 const struct dirent *ent;
205
206 ret = asprintf(&builtname, "%s_%s", name, param_name);
207 if (ret < 0) {
208 ret = -ENOMEM;
209 goto error_ret;
210 }
211 ret = asprintf(&builtname_generic,
212 "%s_%s", generic_name, param_name);
213 if (ret < 0) {
214 ret = -ENOMEM;
215 goto error_free_builtname;
216 }
217 dp = opendir(device_dir);
218 if (dp == NULL) {
219 ret = -errno;
220 goto error_free_builtname_generic;
221 }
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);
227 if (ret < 0) {
228 ret = -ENOMEM;
229 goto error_closedir;
230 }
231 sysfsfp = fopen(filename, "r");
232 if (!sysfsfp) {
233 ret = -errno;
234 goto error_free_filename;
235 }
236 fscanf(sysfsfp, "%f", output);
237 break;
238 }
239 error_free_filename:
240 if (filename)
241 free(filename);
242 error_closedir:
243 closedir(dp);
244 error_free_builtname_generic:
245 free(builtname_generic);
246 error_free_builtname:
247 free(builtname);
248 error_ret:
249 return ret;
250 }
251
252 /**
253 * bsort_channel_array_by_index() - reorder so that the array is in index order
254 *
255 **/
256
257 inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
258 int cnt)
259 {
260
261 struct iio_channel_info temp;
262 int x, y;
263
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;
270 }
271 }
272
273 /**
274 * build_channel_array() - function to figure out what channels are present
275 * @device_dir: the IIO device directory in sysfs
276 * @
277 **/
278 inline int build_channel_array(const char *device_dir,
279 struct iio_channel_info **ci_array,
280 int *counter)
281 {
282 DIR *dp;
283 FILE *sysfsfp;
284 int count, i;
285 struct iio_channel_info *current;
286 int ret;
287 const struct dirent *ent;
288 char *scan_el_dir;
289 char *filename;
290
291 *counter = 0;
292 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
293 if (ret < 0) {
294 ret = -ENOMEM;
295 goto error_ret;
296 }
297 dp = opendir(scan_el_dir);
298 if (dp == NULL) {
299 ret = -errno;
300 goto error_free_name;
301 }
302 while (ent = readdir(dp), ent != NULL)
303 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
304 "_en") == 0) {
305 ret = asprintf(&filename,
306 "%s/%s", scan_el_dir, ent->d_name);
307 if (ret < 0) {
308 ret = -ENOMEM;
309 goto error_close_dir;
310 }
311 sysfsfp = fopen(filename, "r");
312 if (sysfsfp == NULL) {
313 ret = -errno;
314 free(filename);
315 goto error_close_dir;
316 }
317 fscanf(sysfsfp, "%u", &ret);
318 if (ret == 1)
319 (*counter)++;
320 fclose(sysfsfp);
321 free(filename);
322 }
323 *ci_array = malloc(sizeof(**ci_array) * (*counter));
324 if (*ci_array == NULL) {
325 ret = -ENOMEM;
326 goto error_close_dir;
327 }
328 seekdir(dp, 0);
329 count = 0;
330 while (ent = readdir(dp), ent != NULL) {
331 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
332 "_en") == 0) {
333 current = &(*ci_array)[count++];
334 ret = asprintf(&filename,
335 "%s/%s", scan_el_dir, ent->d_name);
336 if (ret < 0) {
337 ret = -ENOMEM;
338 /* decrement count to avoid freeing name */
339 count--;
340 goto error_cleanup_array;
341 }
342 sysfsfp = fopen(filename, "r");
343 if (sysfsfp == NULL) {
344 free(filename);
345 ret = -errno;
346 goto error_cleanup_array;
347 }
348 fscanf(sysfsfp, "%u", &current->enabled);
349 fclose(sysfsfp);
350
351 if (!current->enabled) {
352 free(filename);
353 count--;
354 continue;
355 }
356
357 current->scale = 1.0;
358 current->offset = 0;
359 current->name = strndup(ent->d_name,
360 strlen(ent->d_name) -
361 strlen("_en"));
362 if (current->name == NULL) {
363 free(filename);
364 ret = -ENOMEM;
365 goto error_cleanup_array;
366 }
367 /* Get the generic and specific name elements */
368 ret = iioutils_break_up_name(current->name,
369 &current->generic_name);
370 if (ret) {
371 free(filename);
372 goto error_cleanup_array;
373 }
374 ret = asprintf(&filename,
375 "%s/%s_index",
376 scan_el_dir,
377 current->name);
378 if (ret < 0) {
379 free(filename);
380 ret = -ENOMEM;
381 goto error_cleanup_array;
382 }
383 sysfsfp = fopen(filename, "r");
384 fscanf(sysfsfp, "%u", &current->index);
385 fclose(sysfsfp);
386 free(filename);
387 /* Find the scale */
388 ret = iioutils_get_param_float(&current->scale,
389 "scale",
390 device_dir,
391 current->name,
392 current->generic_name);
393 if (ret < 0)
394 goto error_cleanup_array;
395 ret = iioutils_get_param_float(&current->offset,
396 "offset",
397 device_dir,
398 current->name,
399 current->generic_name);
400 if (ret < 0)
401 goto error_cleanup_array;
402 ret = iioutils_get_type(&current->is_signed,
403 &current->bytes,
404 &current->bits_used,
405 &current->shift,
406 &current->mask,
407 &current->be,
408 device_dir,
409 current->name,
410 current->generic_name);
411 }
412 }
413
414 closedir(dp);
415 /* reorder so that the array is in index order */
416 bsort_channel_array_by_index(ci_array, *counter);
417
418 return 0;
419
420 error_cleanup_array:
421 for (i = count - 1; i >= 0; i--)
422 free((*ci_array)[i].name);
423 free(*ci_array);
424 error_close_dir:
425 closedir(dp);
426 error_free_name:
427 free(scan_el_dir);
428 error_ret:
429 return ret;
430 }
431
432 /**
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
436 *
437 * Typical types this is used for are device and trigger.
438 **/
439 inline int find_type_by_name(const char *name, const char *type)
440 {
441 const struct dirent *ent;
442 int number, numstrlen;
443
444 FILE *nameFile;
445 DIR *dp;
446 char thisname[IIO_MAX_NAME_LENGTH];
447 char *filename;
448
449 dp = opendir(iio_dir);
450 if (dp == NULL) {
451 printf("No industrialio devices available");
452 return -ENODEV;
453 }
454
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),
461 "%d",
462 &number);
463 /* verify the next character is not a colon */
464 if (strncmp(ent->d_name + strlen(type) + numstrlen,
465 ":",
466 1) != 0) {
467 filename = malloc(strlen(iio_dir)
468 + strlen(type)
469 + numstrlen
470 + 6);
471 if (filename == NULL)
472 return -ENOMEM;
473 sprintf(filename, "%s%s%d/name",
474 iio_dir,
475 type,
476 number);
477 nameFile = fopen(filename, "r");
478 if (!nameFile)
479 continue;
480 free(filename);
481 fscanf(nameFile, "%s", thisname);
482 if (strcmp(name, thisname) == 0)
483 return number;
484 fclose(nameFile);
485 }
486 }
487 }
488 return -ENODEV;
489 }
490
491 inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
492 {
493 int ret;
494 FILE *sysfsfp;
495 int test;
496 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
497 if (temp == NULL)
498 return -ENOMEM;
499 sprintf(temp, "%s/%s", basedir, filename);
500 sysfsfp = fopen(temp, "w");
501 if (sysfsfp == NULL) {
502 printf("failed to open %s\n", temp);
503 ret = -errno;
504 goto error_free;
505 }
506 fprintf(sysfsfp, "%d", val);
507 fclose(sysfsfp);
508 if (verify) {
509 sysfsfp = fopen(temp, "r");
510 if (sysfsfp == NULL) {
511 printf("failed to open %s\n", temp);
512 ret = -errno;
513 goto error_free;
514 }
515 fscanf(sysfsfp, "%d", &test);
516 if (test != val) {
517 printf("Possible failure in int write %d to %s%s\n",
518 val,
519 basedir,
520 filename);
521 ret = -1;
522 }
523 }
524 error_free:
525 free(temp);
526 return ret;
527 }
528
529 int write_sysfs_int(char *filename, char *basedir, int val)
530 {
531 return _write_sysfs_int(filename, basedir, val, 0);
532 }
533
534 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
535 {
536 return _write_sysfs_int(filename, basedir, val, 1);
537 }
538
539 int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
540 {
541 int ret = 0;
542 FILE *sysfsfp;
543 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
544 if (temp == NULL) {
545 printf("Memory allocation failed\n");
546 return -ENOMEM;
547 }
548 sprintf(temp, "%s/%s", basedir, filename);
549 sysfsfp = fopen(temp, "w");
550 if (sysfsfp == NULL) {
551 printf("Could not open %s\n", temp);
552 ret = -errno;
553 goto error_free;
554 }
555 fprintf(sysfsfp, "%s", val);
556 fclose(sysfsfp);
557 if (verify) {
558 sysfsfp = fopen(temp, "r");
559 if (sysfsfp == NULL) {
560 printf("could not open file to verify\n");
561 ret = -errno;
562 goto error_free;
563 }
564 fscanf(sysfsfp, "%s", temp);
565 if (strcmp(temp, val) != 0) {
566 printf("Possible failure in string write of %s "
567 "Should be %s "
568 "written to %s\%s\n",
569 temp,
570 val,
571 basedir,
572 filename);
573 ret = -1;
574 }
575 }
576 error_free:
577 free(temp);
578
579 return ret;
580 }
581
582 /**
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
587 **/
588 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
589 {
590 return _write_sysfs_string(filename, basedir, val, 1);
591 }
592
593 int write_sysfs_string(char *filename, char *basedir, char *val)
594 {
595 return _write_sysfs_string(filename, basedir, val, 0);
596 }
597
598 int read_sysfs_posint(char *filename, char *basedir)
599 {
600 int ret;
601 FILE *sysfsfp;
602 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
603 if (temp == NULL) {
604 printf("Memory allocation failed");
605 return -ENOMEM;
606 }
607 sprintf(temp, "%s/%s", basedir, filename);
608 sysfsfp = fopen(temp, "r");
609 if (sysfsfp == NULL) {
610 ret = -errno;
611 goto error_free;
612 }
613 fscanf(sysfsfp, "%d\n", &ret);
614 fclose(sysfsfp);
615 error_free:
616 free(temp);
617 return ret;
618 }
619
620 int read_sysfs_float(char *filename, char *basedir, float *val)
621 {
622 float ret = 0;
623 FILE *sysfsfp;
624 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
625 if (temp == NULL) {
626 printf("Memory allocation failed");
627 return -ENOMEM;
628 }
629 sprintf(temp, "%s/%s", basedir, filename);
630 sysfsfp = fopen(temp, "r");
631 if (sysfsfp == NULL) {
632 ret = -errno;
633 goto error_free;
634 }
635 fscanf(sysfsfp, "%f\n", val);
636 fclose(sysfsfp);
637 error_free:
638 free(temp);
639 return ret;
640 }
This page took 0.14045 seconds and 5 git commands to generate.