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