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