Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / tools / iio / iio_utils.c
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 #ifndef _IIO_UTILS_H
10 #define _IIO_UTILS_H
11
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <dirent.h>
17 #include <errno.h>
18 #include <ctype.h>
19 #include "iio_utils.h"
20
21 const char *iio_dir = "/sys/bus/iio/devices/";
22
23 static char * const iio_direction[] = {
24         "in",
25         "out",
26 };
27
28 /**
29  * iioutils_break_up_name() - extract generic name from full channel name
30  * @full_name: the full channel name
31  * @generic_name: the output generic channel name
32  **/
33 int iioutils_break_up_name(const char *full_name,
34                                   char **generic_name)
35 {
36         char *current;
37         char *w, *r;
38         char *working, *prefix = "";
39         int i;
40
41         for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
42                 if (!strncmp(full_name, iio_direction[i],
43                              strlen(iio_direction[i]))) {
44                         prefix = iio_direction[i];
45                         break;
46                 }
47
48         current = strdup(full_name + strlen(prefix) + 1);
49         working = strtok(current, "_\0");
50
51         w = working;
52         r = working;
53
54         while (*r != '\0') {
55                 if (!isdigit(*r)) {
56                         *w = *r;
57                         w++;
58                 }
59                 r++;
60         }
61         *w = '\0';
62         asprintf(generic_name, "%s_%s", prefix, working);
63         free(current);
64
65         return 0;
66 }
67
68 /**
69  * iioutils_get_type() - find and process _type attribute data
70  * @is_signed: output whether channel is signed
71  * @bytes: output how many bytes the channel storage occupies
72  * @mask: output a bit mask for the raw data
73  * @be: big endian
74  * @device_dir: the iio device directory
75  * @name: the channel name
76  * @generic_name: the channel type name
77  **/
78 int iioutils_get_type(unsigned *is_signed,
79                              unsigned *bytes,
80                              unsigned *bits_used,
81                              unsigned *shift,
82                              uint64_t *mask,
83                              unsigned *be,
84                              const char *device_dir,
85                              const char *name,
86                              const char *generic_name)
87 {
88         FILE *sysfsfp;
89         int ret;
90         DIR *dp;
91         char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
92         char signchar, endianchar;
93         unsigned padint;
94         const struct dirent *ent;
95
96         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
97         if (ret < 0) {
98                 ret = -ENOMEM;
99                 goto error_ret;
100         }
101         ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
102         if (ret < 0) {
103                 ret = -ENOMEM;
104                 goto error_free_scan_el_dir;
105         }
106         ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
107         if (ret < 0) {
108                 ret = -ENOMEM;
109                 goto error_free_builtname;
110         }
111
112         dp = opendir(scan_el_dir);
113         if (dp == NULL) {
114                 ret = -errno;
115                 goto error_free_builtname_generic;
116         }
117         while (ent = readdir(dp), ent != NULL)
118                 /*
119                  * Do we allow devices to override a generic name with
120                  * a specific one?
121                  */
122                 if ((strcmp(builtname, ent->d_name) == 0) ||
123                     (strcmp(builtname_generic, ent->d_name) == 0)) {
124                         ret = asprintf(&filename,
125                                        "%s/%s", scan_el_dir, ent->d_name);
126                         if (ret < 0) {
127                                 ret = -ENOMEM;
128                                 goto error_closedir;
129                         }
130                         sysfsfp = fopen(filename, "r");
131                         if (sysfsfp == NULL) {
132                                 printf("failed to open %s\n", filename);
133                                 ret = -errno;
134                                 goto error_free_filename;
135                         }
136
137                         ret = fscanf(sysfsfp,
138                                      "%ce:%c%u/%u>>%u",
139                                      &endianchar,
140                                      &signchar,
141                                      bits_used,
142                                      &padint, shift);
143                         if (ret < 0) {
144                                 printf("failed to pass scan type description\n");
145                                 ret = -errno;
146                                 goto error_close_sysfsfp;
147                         }
148                         *be = (endianchar == 'b');
149                         *bytes = padint / 8;
150                         if (*bits_used == 64)
151                                 *mask = ~0;
152                         else
153                                 *mask = (1 << *bits_used) - 1;
154                         if (signchar == 's')
155                                 *is_signed = 1;
156                         else
157                                 *is_signed = 0;
158                         fclose(sysfsfp);
159                         free(filename);
160
161                         filename = 0;
162                         sysfsfp = 0;
163                 }
164 error_close_sysfsfp:
165         if (sysfsfp)
166                 fclose(sysfsfp);
167 error_free_filename:
168         if (filename)
169                 free(filename);
170 error_closedir:
171         closedir(dp);
172 error_free_builtname_generic:
173         free(builtname_generic);
174 error_free_builtname:
175         free(builtname);
176 error_free_scan_el_dir:
177         free(scan_el_dir);
178 error_ret:
179         return ret;
180 }
181
182 int iioutils_get_param_float(float *output,
183                                     const char *param_name,
184                                     const char *device_dir,
185                                     const char *name,
186                                     const char *generic_name)
187 {
188         FILE *sysfsfp;
189         int ret;
190         DIR *dp;
191         char *builtname, *builtname_generic;
192         char *filename = NULL;
193         const struct dirent *ent;
194
195         ret = asprintf(&builtname, "%s_%s", name, param_name);
196         if (ret < 0) {
197                 ret = -ENOMEM;
198                 goto error_ret;
199         }
200         ret = asprintf(&builtname_generic,
201                        "%s_%s", generic_name, param_name);
202         if (ret < 0) {
203                 ret = -ENOMEM;
204                 goto error_free_builtname;
205         }
206         dp = opendir(device_dir);
207         if (dp == NULL) {
208                 ret = -errno;
209                 goto error_free_builtname_generic;
210         }
211         while (ent = readdir(dp), ent != NULL)
212                 if ((strcmp(builtname, ent->d_name) == 0) ||
213                     (strcmp(builtname_generic, ent->d_name) == 0)) {
214                         ret = asprintf(&filename,
215                                        "%s/%s", device_dir, ent->d_name);
216                         if (ret < 0) {
217                                 ret = -ENOMEM;
218                                 goto error_closedir;
219                         }
220                         sysfsfp = fopen(filename, "r");
221                         if (!sysfsfp) {
222                                 ret = -errno;
223                                 goto error_free_filename;
224                         }
225                         fscanf(sysfsfp, "%f", output);
226                         break;
227                 }
228 error_free_filename:
229         if (filename)
230                 free(filename);
231 error_closedir:
232         closedir(dp);
233 error_free_builtname_generic:
234         free(builtname_generic);
235 error_free_builtname:
236         free(builtname);
237 error_ret:
238         return ret;
239 }
240
241 /**
242  * bsort_channel_array_by_index() - reorder so that the array is in index order
243  *
244  **/
245
246 void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
247                                          int cnt)
248 {
249
250         struct iio_channel_info temp;
251         int x, y;
252
253         for (x = 0; x < cnt; x++)
254                 for (y = 0; y < (cnt - 1); y++)
255                         if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
256                                 temp = (*ci_array)[y + 1];
257                                 (*ci_array)[y + 1] = (*ci_array)[y];
258                                 (*ci_array)[y] = temp;
259                         }
260 }
261
262 /**
263  * build_channel_array() - function to figure out what channels are present
264  * @device_dir: the IIO device directory in sysfs
265  * @
266  **/
267 int build_channel_array(const char *device_dir,
268                               struct iio_channel_info **ci_array,
269                               int *counter)
270 {
271         DIR *dp;
272         FILE *sysfsfp;
273         int count, i;
274         struct iio_channel_info *current;
275         int ret;
276         const struct dirent *ent;
277         char *scan_el_dir;
278         char *filename;
279
280         *counter = 0;
281         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
282         if (ret < 0) {
283                 ret = -ENOMEM;
284                 goto error_ret;
285         }
286         dp = opendir(scan_el_dir);
287         if (dp == NULL) {
288                 ret = -errno;
289                 goto error_free_name;
290         }
291         while (ent = readdir(dp), ent != NULL)
292                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
293                            "_en") == 0) {
294                         ret = asprintf(&filename,
295                                        "%s/%s", scan_el_dir, ent->d_name);
296                         if (ret < 0) {
297                                 ret = -ENOMEM;
298                                 goto error_close_dir;
299                         }
300                         sysfsfp = fopen(filename, "r");
301                         if (sysfsfp == NULL) {
302                                 ret = -errno;
303                                 free(filename);
304                                 goto error_close_dir;
305                         }
306                         fscanf(sysfsfp, "%i", &ret);
307                         if (ret == 1)
308                                 (*counter)++;
309                         fclose(sysfsfp);
310                         free(filename);
311                 }
312         *ci_array = malloc(sizeof(**ci_array) * (*counter));
313         if (*ci_array == NULL) {
314                 ret = -ENOMEM;
315                 goto error_close_dir;
316         }
317         seekdir(dp, 0);
318         count = 0;
319         while (ent = readdir(dp), ent != NULL) {
320                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
321                            "_en") == 0) {
322                         int current_enabled = 0;
323
324                         current = &(*ci_array)[count++];
325                         ret = asprintf(&filename,
326                                        "%s/%s", scan_el_dir, ent->d_name);
327                         if (ret < 0) {
328                                 ret = -ENOMEM;
329                                 /* decrement count to avoid freeing name */
330                                 count--;
331                                 goto error_cleanup_array;
332                         }
333                         sysfsfp = fopen(filename, "r");
334                         if (sysfsfp == NULL) {
335                                 free(filename);
336                                 ret = -errno;
337                                 goto error_cleanup_array;
338                         }
339                         fscanf(sysfsfp, "%i", &current_enabled);
340                         fclose(sysfsfp);
341
342                         if (!current_enabled) {
343                                 free(filename);
344                                 count--;
345                                 continue;
346                         }
347
348                         current->scale = 1.0;
349                         current->offset = 0;
350                         current->name = strndup(ent->d_name,
351                                                 strlen(ent->d_name) -
352                                                 strlen("_en"));
353                         if (current->name == NULL) {
354                                 free(filename);
355                                 ret = -ENOMEM;
356                                 goto error_cleanup_array;
357                         }
358                         /* Get the generic and specific name elements */
359                         ret = iioutils_break_up_name(current->name,
360                                                      &current->generic_name);
361                         if (ret) {
362                                 free(filename);
363                                 goto error_cleanup_array;
364                         }
365                         ret = asprintf(&filename,
366                                        "%s/%s_index",
367                                        scan_el_dir,
368                                        current->name);
369                         if (ret < 0) {
370                                 free(filename);
371                                 ret = -ENOMEM;
372                                 goto error_cleanup_array;
373                         }
374                         sysfsfp = fopen(filename, "r");
375                         fscanf(sysfsfp, "%u", &current->index);
376                         fclose(sysfsfp);
377                         free(filename);
378                         /* Find the scale */
379                         ret = iioutils_get_param_float(&current->scale,
380                                                        "scale",
381                                                        device_dir,
382                                                        current->name,
383                                                        current->generic_name);
384                         if (ret < 0)
385                                 goto error_cleanup_array;
386                         ret = iioutils_get_param_float(&current->offset,
387                                                        "offset",
388                                                        device_dir,
389                                                        current->name,
390                                                        current->generic_name);
391                         if (ret < 0)
392                                 goto error_cleanup_array;
393                         ret = iioutils_get_type(&current->is_signed,
394                                                 &current->bytes,
395                                                 &current->bits_used,
396                                                 &current->shift,
397                                                 &current->mask,
398                                                 &current->be,
399                                                 device_dir,
400                                                 current->name,
401                                                 current->generic_name);
402                 }
403         }
404
405         closedir(dp);
406         /* reorder so that the array is in index order */
407         bsort_channel_array_by_index(ci_array, *counter);
408
409         return 0;
410
411 error_cleanup_array:
412         for (i = count - 1;  i >= 0; i--)
413                 free((*ci_array)[i].name);
414         free(*ci_array);
415 error_close_dir:
416         closedir(dp);
417 error_free_name:
418         free(scan_el_dir);
419 error_ret:
420         return ret;
421 }
422
423 /**
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
427  *
428  * Typical types this is used for are device and trigger.
429  **/
430 int find_type_by_name(const char *name, const char *type)
431 {
432         const struct dirent *ent;
433         int number, numstrlen;
434
435         FILE *nameFile;
436         DIR *dp;
437         char thisname[IIO_MAX_NAME_LENGTH];
438         char *filename;
439
440         dp = opendir(iio_dir);
441         if (dp == NULL) {
442                 printf("No industrialio devices available\n");
443                 return -ENODEV;
444         }
445
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),
452                                            "%d",
453                                            &number);
454                         /* verify the next character is not a colon */
455                         if (strncmp(ent->d_name + strlen(type) + numstrlen,
456                                         ":",
457                                         1) != 0) {
458                                 filename = malloc(strlen(iio_dir)
459                                                 + strlen(type)
460                                                 + numstrlen
461                                                 + 6);
462                                 if (filename == NULL) {
463                                         closedir(dp);
464                                         return -ENOMEM;
465                                 }
466                                 sprintf(filename, "%s%s%d/name",
467                                         iio_dir,
468                                         type,
469                                         number);
470                                 nameFile = fopen(filename, "r");
471                                 if (!nameFile) {
472                                         free(filename);
473                                         continue;
474                                 }
475                                 free(filename);
476                                 fscanf(nameFile, "%s", thisname);
477                                 fclose(nameFile);
478                                 if (strcmp(name, thisname) == 0) {
479                                         closedir(dp);
480                                         return number;
481                                 }
482                         }
483                 }
484         }
485         closedir(dp);
486         return -ENODEV;
487 }
488
489 int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
490 {
491         int ret = 0;
492         FILE *sysfsfp;
493         int test;
494         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
495
496         if (temp == NULL)
497                 return -ENOMEM;
498         sprintf(temp, "%s/%s", basedir, filename);
499         sysfsfp = fopen(temp, "w");
500         if (sysfsfp == NULL) {
501                 printf("failed to open %s\n", temp);
502                 ret = -errno;
503                 goto error_free;
504         }
505         fprintf(sysfsfp, "%d", val);
506         fclose(sysfsfp);
507         if (verify) {
508                 sysfsfp = fopen(temp, "r");
509                 if (sysfsfp == NULL) {
510                         printf("failed to open %s\n", temp);
511                         ret = -errno;
512                         goto error_free;
513                 }
514                 fscanf(sysfsfp, "%d", &test);
515                 fclose(sysfsfp);
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
545         if (temp == NULL) {
546                 printf("Memory allocation failed\n");
547                 return -ENOMEM;
548         }
549         sprintf(temp, "%s/%s", basedir, filename);
550         sysfsfp = fopen(temp, "w");
551         if (sysfsfp == NULL) {
552                 printf("Could not open %s\n", temp);
553                 ret = -errno;
554                 goto error_free;
555         }
556         fprintf(sysfsfp, "%s", val);
557         fclose(sysfsfp);
558         if (verify) {
559                 sysfsfp = fopen(temp, "r");
560                 if (sysfsfp == NULL) {
561                         printf("could not open file to verify\n");
562                         ret = -errno;
563                         goto error_free;
564                 }
565                 fscanf(sysfsfp, "%s", temp);
566                 fclose(sysfsfp);
567                 if (strcmp(temp, val) != 0) {
568                         printf("Possible failure in string write of %s "
569                                 "Should be %s "
570                                 "written to %s\%s\n",
571                                 temp,
572                                 val,
573                                 basedir,
574                                 filename);
575                         ret = -1;
576                 }
577         }
578 error_free:
579         free(temp);
580
581         return ret;
582 }
583
584 /**
585  * write_sysfs_string_and_verify() - string write, readback and verify
586  * @filename: name of file to write to
587  * @basedir: the sysfs directory in which the file is to be found
588  * @val: the string to write
589  **/
590 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
591 {
592         return _write_sysfs_string(filename, basedir, val, 1);
593 }
594
595 int write_sysfs_string(char *filename, char *basedir, char *val)
596 {
597         return _write_sysfs_string(filename, basedir, val, 0);
598 }
599
600 int read_sysfs_posint(char *filename, char *basedir)
601 {
602         int ret;
603         FILE  *sysfsfp;
604         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
605
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, "%d\n", &ret);
617         fclose(sysfsfp);
618 error_free:
619         free(temp);
620         return ret;
621 }
622
623 int read_sysfs_float(char *filename, char *basedir, float *val)
624 {
625         int ret = 0;
626         FILE  *sysfsfp;
627         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
628
629         if (temp == NULL) {
630                 printf("Memory allocation failed");
631                 return -ENOMEM;
632         }
633         sprintf(temp, "%s/%s", basedir, filename);
634         sysfsfp = fopen(temp, "r");
635         if (sysfsfp == NULL) {
636                 ret = -errno;
637                 goto error_free;
638         }
639         fscanf(sysfsfp, "%f\n", val);
640         fclose(sysfsfp);
641 error_free:
642         free(temp);
643         return ret;
644 }
645
646 int read_sysfs_string(const char *filename, const char *basedir, char *str)
647 {
648         int ret = 0;
649         FILE  *sysfsfp;
650         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
651
652         if (temp == NULL) {
653                 printf("Memory allocation failed");
654                 return -ENOMEM;
655         }
656         sprintf(temp, "%s/%s", basedir, filename);
657         sysfsfp = fopen(temp, "r");
658         if (sysfsfp == NULL) {
659                 ret = -errno;
660                 goto error_free;
661         }
662         fscanf(sysfsfp, "%s\n", str);
663         fclose(sysfsfp);
664 error_free:
665         free(temp);
666         return ret;
667 }
668
669 #endif /* _IIO_UTILS_H */