sh: select ARCH_NO_SYSDEV_OPS.
[pandora-kernel.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 IIO_EV_CLASS_BUFFER             0
20 #define IIO_BUFFER_EVENT_CODE(code)             \
21         (IIO_EV_CLASS_BUFFER | (code << 8))
22
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)
26
27
28 #define FORMAT_SCAN_ELEMENTS_DIR "%s:buffer0/scan_elements"
29 #define FORMAT_TYPE_FILE "%s_type"
30
31 const char *iio_dir = "/sys/bus/iio/devices/";
32
33 struct iio_event_data {
34         int id;
35         __s64 timestamp;
36 };
37
38 /**
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
42  **/
43 static int iioutils_break_up_name(const char *full_name,
44                                   char **generic_name)
45 {
46         char *current;
47         char *w, *r;
48         char *working;
49         current = strdup(full_name);
50         working = strtok(current, "_\0");
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         *generic_name = strdup(working);
63         free(current);
64
65         return 0;
66 }
67
68 /**
69  * struct iio_channel_info - information about a given channel
70  * @name: channel name
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
79  **/
80 struct iio_channel_info {
81         char *name;
82         char *generic_name;
83         float scale;
84         float offset;
85         unsigned index;
86         unsigned bytes;
87         unsigned bits_used;
88         uint64_t mask;
89         unsigned is_signed;
90         unsigned enabled;
91         unsigned location;
92 };
93
94 /**
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
102  **/
103 inline int iioutils_get_type(unsigned *is_signed,
104                              unsigned *bytes,
105                              unsigned *bits_used,
106                              uint64_t *mask,
107                              const char *device_dir,
108                              const char *name,
109                              const char *generic_name)
110 {
111         FILE *sysfsfp;
112         int ret;
113         DIR *dp;
114         char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
115         char signchar;
116         unsigned padint;
117         const struct dirent *ent;
118
119         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
120         if (ret < 0) {
121                 ret = -ENOMEM;
122                 goto error_ret;
123         }
124         ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
125         if (ret < 0) {
126                 ret = -ENOMEM;
127                 goto error_free_scan_el_dir;
128         }
129         ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
130         if (ret < 0) {
131                 ret = -ENOMEM;
132                 goto error_free_builtname;
133         }
134
135         dp = opendir(scan_el_dir);
136         if (dp == NULL) {
137                 ret = -errno;
138                 goto error_free_builtname_generic;
139         }
140         while (ent = readdir(dp), ent != NULL)
141                 /*
142                  * Do we allow devices to override a generic name with
143                  * a specific one?
144                  */
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);
149                         if (ret < 0) {
150                                 ret = -ENOMEM;
151                                 goto error_closedir;
152                         }
153                         sysfsfp = fopen(filename, "r");
154                         if (sysfsfp == NULL) {
155                                 printf("failed to open %s\n", filename);
156                                 ret = -errno;
157                                 goto error_free_filename;
158                         }
159                         fscanf(sysfsfp,
160                                "%c%u/%u", &signchar, bits_used, &padint);
161                         *bytes = padint / 8;
162                         if (*bits_used == 64)
163                                 *mask = ~0;
164                         else
165                                 *mask = (1 << *bits_used) - 1;
166                         if (signchar == 's')
167                                 *is_signed = 1;
168                         else
169                                 *is_signed = 0;
170                 }
171 error_free_filename:
172         if (filename)
173                 free(filename);
174 error_closedir:
175         closedir(dp);
176 error_free_builtname_generic:
177         free(builtname_generic);
178 error_free_builtname:
179         free(builtname);
180 error_free_scan_el_dir:
181         free(scan_el_dir);
182 error_ret:
183         return ret;
184 }
185
186 inline int iioutils_get_param_float(float *output,
187                                     const char *param_name,
188                                     const char *device_dir,
189                                     const char *name,
190                                     const char *generic_name)
191 {
192         FILE *sysfsfp;
193         int ret;
194         DIR *dp;
195         char *builtname, *builtname_generic;
196         char *filename = NULL;
197         const struct dirent *ent;
198
199         ret = asprintf(&builtname, "%s_%s", name, param_name);
200         if (ret < 0) {
201                 ret = -ENOMEM;
202                 goto error_ret;
203         }
204         ret = asprintf(&builtname_generic,
205                        "%s_%s", generic_name, param_name);
206         if (ret < 0) {
207                 ret = -ENOMEM;
208                 goto error_free_builtname;
209         }
210         dp = opendir(device_dir);
211         if (dp == NULL) {
212                 ret = -errno;
213                 goto error_free_builtname_generic;
214         }
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);
220                         if (ret < 0) {
221                                 ret = -ENOMEM;
222                                 goto error_closedir;
223                         }
224                         sysfsfp = fopen(filename, "r");
225                         if (!sysfsfp) {
226                                 ret = -errno;
227                                 goto error_free_filename;
228                         }
229                         fscanf(sysfsfp, "%f", output);
230                         break;
231                 }
232 error_free_filename:
233         if (filename)
234                 free(filename);
235 error_closedir:
236         closedir(dp);
237 error_free_builtname_generic:
238         free(builtname_generic);
239 error_free_builtname:
240         free(builtname);
241 error_ret:
242         return ret;
243 }
244
245 /**
246  * bsort_channel_array_by_index() - reorder so that the array is in index order
247  *
248  **/
249
250 inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
251                                          int cnt)
252 {
253
254         struct iio_channel_info temp;
255         int x, y;
256
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;
263                         }
264 }
265
266 /**
267  * build_channel_array() - function to figure out what channels are present
268  * @device_dir: the IIO device directory in sysfs
269  * @
270  **/
271 inline int build_channel_array(const char *device_dir,
272                               struct iio_channel_info **ci_array,
273                               int *counter)
274 {
275         DIR *dp;
276         FILE *sysfsfp;
277         int count, temp, i;
278         struct iio_channel_info *current;
279         int ret;
280         const struct dirent *ent;
281         char *scan_el_dir;
282         char *filename;
283
284         *counter = 0;
285         ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
286         if (ret < 0) {
287                 ret = -ENOMEM;
288                 goto error_ret;
289         }
290         dp = opendir(scan_el_dir);
291         if (dp == NULL) {
292                 ret = -errno;
293                 goto error_free_name;
294         }
295         while (ent = readdir(dp), ent != NULL)
296                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
297                            "_en") == 0) {
298                         ret = asprintf(&filename,
299                                        "%s/%s", scan_el_dir, ent->d_name);
300                         if (ret < 0) {
301                                 ret = -ENOMEM;
302                                 goto error_close_dir;
303                         }
304                         sysfsfp = fopen(filename, "r");
305                         if (sysfsfp == NULL) {
306                                 ret = -errno;
307                                 free(filename);
308                                 goto error_close_dir;
309                         }
310                         fscanf(sysfsfp, "%u", &ret);
311                         if (ret == 1)
312                                 (*counter)++;
313                         fclose(sysfsfp);
314                         free(filename);
315                 }
316         *ci_array = malloc(sizeof(**ci_array) * (*counter));
317         if (*ci_array == NULL) {
318                 ret = -ENOMEM;
319                 goto error_close_dir;
320         }
321         seekdir(dp, 0);
322         count = 0;
323         while (ent = readdir(dp), ent != NULL) {
324                 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
325                            "_en") == 0) {
326                         current = &(*ci_array)[count++];
327                         ret = asprintf(&filename,
328                                        "%s/%s", scan_el_dir, ent->d_name);
329                         if (ret < 0) {
330                                 ret = -ENOMEM;
331                                 /* decrement count to avoid freeing name */
332                                 count--;
333                                 goto error_cleanup_array;
334                         }
335                         sysfsfp = fopen(filename, "r");
336                         if (sysfsfp == NULL) {
337                                 free(filename);
338                                 ret = -errno;
339                                 goto error_cleanup_array;
340                         }
341                         fscanf(sysfsfp, "%u", &current->enabled);
342                         fclose(sysfsfp);
343
344                         if (!current->enabled) {
345                                 free(filename);
346                                 count--;
347                                 continue;
348                         }
349
350                         current->scale = 1.0;
351                         current->offset = 0;
352                         current->name = strndup(ent->d_name,
353                                                 strlen(ent->d_name) -
354                                                 strlen("_en"));
355                         if (current->name == NULL) {
356                                 free(filename);
357                                 ret = -ENOMEM;
358                                 goto error_cleanup_array;
359                         }
360                         /* Get the generic and specific name elements */
361                         ret = iioutils_break_up_name(current->name,
362                                                      &current->generic_name);
363                         if (ret) {
364                                 free(filename);
365                                 goto error_cleanup_array;
366                         }
367                         ret = asprintf(&filename,
368                                        "%s/%s_index",
369                                        scan_el_dir,
370                                        current->name);
371                         if (ret < 0) {
372                                 free(filename);
373                                 ret = -ENOMEM;
374                                 goto error_cleanup_array;
375                         }
376                         sysfsfp = fopen(filename, "r");
377                         fscanf(sysfsfp, "%u", &current->index);
378                         fclose(sysfsfp);
379                         free(filename);
380                         /* Find the scale */
381                         ret = iioutils_get_param_float(&current->scale,
382                                                        "scale",
383                                                        device_dir,
384                                                        current->name,
385                                                        current->generic_name);
386                         if (ret < 0)
387                                 goto error_cleanup_array;
388                         ret = iioutils_get_param_float(&current->offset,
389                                                        "offset",
390                                                        device_dir,
391                                                        current->name,
392                                                        current->generic_name);
393                         if (ret < 0)
394                                 goto error_cleanup_array;
395                         ret = iioutils_get_type(&current->is_signed,
396                                                 &current->bytes,
397                                                 &current->bits_used,
398                                                 &current->mask,
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 inline 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");
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                                         return -ENOMEM;
464                                 sprintf(filename, "%s%s%d/name",
465                                         iio_dir,
466                                         type,
467                                         number);
468                                 nameFile = fopen(filename, "r");
469                                 if (!nameFile)
470                                         continue;
471                                 free(filename);
472                                 fscanf(nameFile, "%s", thisname);
473                                 if (strcmp(name, thisname) == 0)
474                                         return number;
475                                 fclose(nameFile);
476                         }
477                 }
478         }
479         return -ENODEV;
480 }
481
482 inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
483 {
484         int ret;
485         FILE *sysfsfp;
486         int test;
487         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
488         if (temp == NULL)
489                 return -ENOMEM;
490         sprintf(temp, "%s/%s", basedir, filename);
491         sysfsfp = fopen(temp, "w");
492         if (sysfsfp == NULL) {
493                 printf("failed to open %s\n", temp);
494                 ret = -errno;
495                 goto error_free;
496         }
497         fprintf(sysfsfp, "%d", val);
498         fclose(sysfsfp);
499         if (verify) {
500                 sysfsfp = fopen(temp, "r");
501                 if (sysfsfp == NULL) {
502                         printf("failed to open %s\n", temp);
503                         ret = -errno;
504                         goto error_free;
505                 }
506                 fscanf(sysfsfp, "%d", &test);
507                 if (test != val) {
508                         printf("Possible failure in int write %d to %s%s\n",
509                                 val,
510                                 basedir,
511                                 filename);
512                         ret = -1;
513                 }
514         }
515 error_free:
516         free(temp);
517         return ret;
518 }
519
520 int write_sysfs_int(char *filename, char *basedir, int val)
521 {
522         return _write_sysfs_int(filename, basedir, val, 0);
523 }
524
525 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
526 {
527         return _write_sysfs_int(filename, basedir, val, 1);
528 }
529
530 int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
531 {
532         int ret = 0;
533         FILE  *sysfsfp;
534         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
535         if (temp == NULL) {
536                 printf("Memory allocation failed\n");
537                 return -ENOMEM;
538         }
539         sprintf(temp, "%s/%s", basedir, filename);
540         sysfsfp = fopen(temp, "w");
541         if (sysfsfp == NULL) {
542                 printf("Could not open %s\n", temp);
543                 ret = -errno;
544                 goto error_free;
545         }
546         fprintf(sysfsfp, "%s", val);
547         fclose(sysfsfp);
548         if (verify) {
549                 sysfsfp = fopen(temp, "r");
550                 if (sysfsfp == NULL) {
551                         printf("could not open file to verify\n");
552                         ret = -errno;
553                         goto error_free;
554                 }
555                 fscanf(sysfsfp, "%s", temp);
556                 if (strcmp(temp, val) != 0) {
557                         printf("Possible failure in string write of %s "
558                                 "Should be %s "
559                                 "writen to %s\%s\n",
560                                 temp,
561                                 val,
562                                 basedir,
563                                 filename);
564                         ret = -1;
565                 }
566         }
567 error_free:
568         free(temp);
569
570         return ret;
571 }
572
573 /**
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
578  **/
579 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
580 {
581         return _write_sysfs_string(filename, basedir, val, 1);
582 }
583
584 int write_sysfs_string(char *filename, char *basedir, char *val)
585 {
586         return _write_sysfs_string(filename, basedir, val, 0);
587 }
588
589 int read_sysfs_posint(char *filename, char *basedir)
590 {
591         int ret;
592         FILE  *sysfsfp;
593         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
594         if (temp == NULL) {
595                 printf("Memory allocation failed");
596                 return -ENOMEM;
597         }
598         sprintf(temp, "%s/%s", basedir, filename);
599         sysfsfp = fopen(temp, "r");
600         if (sysfsfp == NULL) {
601                 ret = -errno;
602                 goto error_free;
603         }
604         fscanf(sysfsfp, "%d\n", &ret);
605         fclose(sysfsfp);
606 error_free:
607         free(temp);
608         return ret;
609 }
610
611 int read_sysfs_float(char *filename, char *basedir, float *val)
612 {
613         float ret = 0;
614         FILE  *sysfsfp;
615         char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
616         if (temp == NULL) {
617                 printf("Memory allocation failed");
618                 return -ENOMEM;
619         }
620         sprintf(temp, "%s/%s", basedir, filename);
621         sysfsfp = fopen(temp, "r");
622         if (sysfsfp == NULL) {
623                 ret = -errno;
624                 goto error_free;
625         }
626         fscanf(sysfsfp, "%f\n", val);
627         fclose(sysfsfp);
628 error_free:
629         free(temp);
630         return ret;
631 }