Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iio_utils.h
Go to the documentation of this file.
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 
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 
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;
78  unsigned be;
79  unsigned is_signed;
80  unsigned enabled;
81  unsigned location;
82 };
83 
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  ret = -errno;
162  goto error_close_sysfsfp;
163  }
164  *be = (endianchar == 'b');
165  *bytes = padint / 8;
166  if (*bits_used == 64)
167  *mask = ~0;
168  else
169  *mask = (1 << *bits_used) - 1;
170  if (signchar == 's')
171  *is_signed = 1;
172  else
173  *is_signed = 0;
174  fclose(sysfsfp);
175  free(filename);
176 
177  filename = 0;
178  sysfsfp = 0;
179  }
180 error_close_sysfsfp:
181  if (sysfsfp)
182  fclose(sysfsfp);
183 error_free_filename:
184  if (filename)
185  free(filename);
186 error_closedir:
187  closedir(dp);
188 error_free_builtname_generic:
189  free(builtname_generic);
190 error_free_builtname:
191  free(builtname);
192 error_free_scan_el_dir:
193  free(scan_el_dir);
194 error_ret:
195  return ret;
196 }
197 
198 inline int iioutils_get_param_float(float *output,
199  const char *param_name,
200  const char *device_dir,
201  const char *name,
202  const char *generic_name)
203 {
204  FILE *sysfsfp;
205  int ret;
206  DIR *dp;
207  char *builtname, *builtname_generic;
208  char *filename = NULL;
209  const struct dirent *ent;
210 
211  ret = asprintf(&builtname, "%s_%s", name, param_name);
212  if (ret < 0) {
213  ret = -ENOMEM;
214  goto error_ret;
215  }
216  ret = asprintf(&builtname_generic,
217  "%s_%s", generic_name, param_name);
218  if (ret < 0) {
219  ret = -ENOMEM;
220  goto error_free_builtname;
221  }
222  dp = opendir(device_dir);
223  if (dp == NULL) {
224  ret = -errno;
225  goto error_free_builtname_generic;
226  }
227  while (ent = readdir(dp), ent != NULL)
228  if ((strcmp(builtname, ent->d_name) == 0) ||
229  (strcmp(builtname_generic, ent->d_name) == 0)) {
230  ret = asprintf(&filename,
231  "%s/%s", device_dir, ent->d_name);
232  if (ret < 0) {
233  ret = -ENOMEM;
234  goto error_closedir;
235  }
236  sysfsfp = fopen(filename, "r");
237  if (!sysfsfp) {
238  ret = -errno;
239  goto error_free_filename;
240  }
241  fscanf(sysfsfp, "%f", output);
242  break;
243  }
244 error_free_filename:
245  if (filename)
246  free(filename);
247 error_closedir:
248  closedir(dp);
249 error_free_builtname_generic:
250  free(builtname_generic);
251 error_free_builtname:
252  free(builtname);
253 error_ret:
254  return ret;
255 }
256 
262 inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
263  int cnt)
264 {
265 
266  struct iio_channel_info temp;
267  int x, y;
268 
269  for (x = 0; x < cnt; x++)
270  for (y = 0; y < (cnt - 1); y++)
271  if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
272  temp = (*ci_array)[y + 1];
273  (*ci_array)[y + 1] = (*ci_array)[y];
274  (*ci_array)[y] = temp;
275  }
276 }
277 
283 inline int build_channel_array(const char *device_dir,
284  struct iio_channel_info **ci_array,
285  int *counter)
286 {
287  DIR *dp;
288  FILE *sysfsfp;
289  int count, i;
290  struct iio_channel_info *current;
291  int ret;
292  const struct dirent *ent;
293  char *scan_el_dir;
294  char *filename;
295 
296  *counter = 0;
297  ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
298  if (ret < 0) {
299  ret = -ENOMEM;
300  goto error_ret;
301  }
302  dp = opendir(scan_el_dir);
303  if (dp == NULL) {
304  ret = -errno;
305  goto error_free_name;
306  }
307  while (ent = readdir(dp), ent != NULL)
308  if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
309  "_en") == 0) {
310  ret = asprintf(&filename,
311  "%s/%s", scan_el_dir, ent->d_name);
312  if (ret < 0) {
313  ret = -ENOMEM;
314  goto error_close_dir;
315  }
316  sysfsfp = fopen(filename, "r");
317  if (sysfsfp == NULL) {
318  ret = -errno;
319  free(filename);
320  goto error_close_dir;
321  }
322  fscanf(sysfsfp, "%u", &ret);
323  if (ret == 1)
324  (*counter)++;
325  fclose(sysfsfp);
326  free(filename);
327  }
328  *ci_array = malloc(sizeof(**ci_array) * (*counter));
329  if (*ci_array == NULL) {
330  ret = -ENOMEM;
331  goto error_close_dir;
332  }
333  seekdir(dp, 0);
334  count = 0;
335  while (ent = readdir(dp), ent != NULL) {
336  if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
337  "_en") == 0) {
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  }
353  fscanf(sysfsfp, "%u", &current->enabled);
354  fclose(sysfsfp);
355 
356  if (!current->enabled) {
357  free(filename);
358  count--;
359  continue;
360  }
361 
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,
410  &current->shift,
411  &current->mask,
412  &current->be,
413  device_dir,
414  current->name,
415  current->generic_name);
416  }
417  }
418 
419  closedir(dp);
420  /* reorder so that the array is in index order */
421  bsort_channel_array_by_index(ci_array, *counter);
422 
423  return 0;
424 
425 error_cleanup_array:
426  for (i = count - 1; i >= 0; i--)
427  free((*ci_array)[i].name);
428  free(*ci_array);
429 error_close_dir:
430  closedir(dp);
431 error_free_name:
432  free(scan_el_dir);
433 error_ret:
434  return ret;
435 }
436 
444 inline int find_type_by_name(const char *name, const char *type)
445 {
446  const struct dirent *ent;
447  int number, numstrlen;
448 
449  FILE *nameFile;
450  DIR *dp;
451  char thisname[IIO_MAX_NAME_LENGTH];
452  char *filename;
453 
454  dp = opendir(iio_dir);
455  if (dp == NULL) {
456  printf("No industrialio devices available\n");
457  return -ENODEV;
458  }
459 
460  while (ent = readdir(dp), ent != NULL) {
461  if (strcmp(ent->d_name, ".") != 0 &&
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)
474  + numstrlen
475  + 6);
476  if (filename == NULL) {
477  closedir(dp);
478  return -ENOMEM;
479  }
480  sprintf(filename, "%s%s%d/name",
481  iio_dir,
482  type,
483  number);
484  nameFile = fopen(filename, "r");
485  if (!nameFile) {
486  free(filename);
487  continue;
488  }
489  free(filename);
490  fscanf(nameFile, "%s", thisname);
491  fclose(nameFile);
492  if (strcmp(name, thisname) == 0) {
493  closedir(dp);
494  return number;
495  }
496  }
497  }
498  }
499  closedir(dp);
500  return -ENODEV;
501 }
502 
503 inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
504 {
505  int ret;
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);
512  sysfsfp = fopen(temp, "w");
513  if (sysfsfp == NULL) {
514  printf("failed to open %s\n", temp);
515  ret = -errno;
516  goto error_free;
517  }
518  fprintf(sysfsfp, "%d", val);
519  fclose(sysfsfp);
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);
528  fclose(sysfsfp);
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  }
537 error_free:
538  free(temp);
539  return ret;
540 }
541 
542 int write_sysfs_int(char *filename, char *basedir, int val)
543 {
544  return _write_sysfs_int(filename, basedir, val, 0);
545 }
546 
547 int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
548 {
549  return _write_sysfs_int(filename, basedir, val, 1);
550 }
551 
552 int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
553 {
554  int ret = 0;
555  FILE *sysfsfp;
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);
562  sysfsfp = fopen(temp, "w");
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);
569  fclose(sysfsfp);
570  if (verify) {
571  sysfsfp = fopen(temp, "r");
572  if (sysfsfp == NULL) {
573  printf("could not open file to verify\n");
574  ret = -errno;
575  goto error_free;
576  }
577  fscanf(sysfsfp, "%s", temp);
578  fclose(sysfsfp);
579  if (strcmp(temp, val) != 0) {
580  printf("Possible failure in string write of %s "
581  "Should be %s "
582  "written to %s\%s\n",
583  temp,
584  val,
585  basedir,
586  filename);
587  ret = -1;
588  }
589  }
590 error_free:
591  free(temp);
592 
593  return ret;
594 }
595 
602 int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
603 {
604  return _write_sysfs_string(filename, basedir, val, 1);
605 }
606 
607 int write_sysfs_string(char *filename, char *basedir, char *val)
608 {
609  return _write_sysfs_string(filename, basedir, val, 0);
610 }
611 
612 int read_sysfs_posint(char *filename, char *basedir)
613 {
614  int ret;
615  FILE *sysfsfp;
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);
622  sysfsfp = fopen(temp, "r");
623  if (sysfsfp == NULL) {
624  ret = -errno;
625  goto error_free;
626  }
627  fscanf(sysfsfp, "%d\n", &ret);
628  fclose(sysfsfp);
629 error_free:
630  free(temp);
631  return ret;
632 }
633 
634 int 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);
651 error_free:
652  free(temp);
653  return ret;
654 }