blob: e1828d0d8a38cfd9251a5c350c6f4f1c304f7f48 [file] [log] [blame]
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +01001/* 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 */
Cristina Opriceana37e3be92015-03-04 02:37:15 +02009#ifndef _IIO_UTILS_H
10#define _IIO_UTILS_H
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +010011
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010012#include <string.h>
13#include <stdlib.h>
Jonathan Camerone58537c2010-10-08 12:14:14 +010014#include <stdio.h>
15#include <stdint.h>
Lars-Peter Clausenbc9f35d2011-10-26 17:27:44 +010016#include <dirent.h>
Peter Meerwaldbb233782012-06-25 23:12:17 +020017#include <errno.h>
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +020018#include <ctype.h>
19#include "iio_utils.h"
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +010020
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010021const char *iio_dir = "/sys/bus/iio/devices/";
22
Irina Tirdead9d7b992015-03-27 13:53:00 +020023static char * const iio_direction[] = {
24 "in",
25 "out",
26};
27
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010028/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010029 * 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 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +020033int iioutils_break_up_name(const char *full_name,
Jonathan Camerone58537c2010-10-08 12:14:14 +010034 char **generic_name)
35{
36 char *current;
37 char *w, *r;
Irina Tirdead9d7b992015-03-27 13:53:00 +020038 char *working, *prefix = "";
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020039 int i, ret;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +030040
Irina Tirdead9d7b992015-03-27 13:53:00 +020041 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);
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020049 if (!current)
50 return -ENOMEM;
51
Jonathan Camerone58537c2010-10-08 12:14:14 +010052 working = strtok(current, "_\0");
Hartmut Knaack53118552015-05-31 14:40:14 +020053 if (!working) {
54 free(current);
55 return -EINVAL;
56 }
Irina Tirdead9d7b992015-03-27 13:53:00 +020057
Jonathan Camerone58537c2010-10-08 12:14:14 +010058 w = working;
59 r = working;
60
Michael Hennerich8b68bb22011-03-08 08:55:48 +010061 while (*r != '\0') {
Jonathan Camerone58537c2010-10-08 12:14:14 +010062 if (!isdigit(*r)) {
63 *w = *r;
64 w++;
65 }
66 r++;
67 }
68 *w = '\0';
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020069 ret = asprintf(generic_name, "%s_%s", prefix, working);
Jonathan Camerone58537c2010-10-08 12:14:14 +010070 free(current);
71
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020072 return (ret == -1) ? -ENOMEM : 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +010073}
74
75/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010076 * iioutils_get_type() - find and process _type attribute data
77 * @is_signed: output whether channel is signed
78 * @bytes: output how many bytes the channel storage occupies
79 * @mask: output a bit mask for the raw data
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000080 * @be: big endian
Jonathan Camerone58537c2010-10-08 12:14:14 +010081 * @device_dir: the iio device directory
82 * @name: the channel name
83 * @generic_name: the channel type name
84 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +020085int iioutils_get_type(unsigned *is_signed,
Jonathan Camerone58537c2010-10-08 12:14:14 +010086 unsigned *bytes,
87 unsigned *bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +010088 unsigned *shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +010089 uint64_t *mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000090 unsigned *be,
Jonathan Camerone58537c2010-10-08 12:14:14 +010091 const char *device_dir,
92 const char *name,
93 const char *generic_name)
94{
95 FILE *sysfsfp;
96 int ret;
97 DIR *dp;
98 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000099 char signchar, endianchar;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100100 unsigned padint;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100101 const struct dirent *ent;
102
103 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
104 if (ret < 0) {
105 ret = -ENOMEM;
106 goto error_ret;
107 }
108 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
109 if (ret < 0) {
110 ret = -ENOMEM;
111 goto error_free_scan_el_dir;
112 }
113 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
114 if (ret < 0) {
115 ret = -ENOMEM;
116 goto error_free_builtname;
117 }
118
119 dp = opendir(scan_el_dir);
120 if (dp == NULL) {
121 ret = -errno;
122 goto error_free_builtname_generic;
123 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200124 ret = -ENOENT;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100125 while (ent = readdir(dp), ent != NULL)
126 /*
127 * Do we allow devices to override a generic name with
128 * a specific one?
129 */
130 if ((strcmp(builtname, ent->d_name) == 0) ||
131 (strcmp(builtname_generic, ent->d_name) == 0)) {
132 ret = asprintf(&filename,
133 "%s/%s", scan_el_dir, ent->d_name);
134 if (ret < 0) {
135 ret = -ENOMEM;
136 goto error_closedir;
137 }
138 sysfsfp = fopen(filename, "r");
139 if (sysfsfp == NULL) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100140 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200141 printf("failed to open %s\n", filename);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100142 goto error_free_filename;
143 }
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000144
145 ret = fscanf(sysfsfp,
146 "%ce:%c%u/%u>>%u",
147 &endianchar,
148 &signchar,
149 bits_used,
150 &padint, shift);
151 if (ret < 0) {
Peter Meerwald578f7372012-06-25 23:13:24 +0200152 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200153 printf("failed to pass scan type description\n");
Peter Meerwald578f7372012-06-25 23:13:24 +0200154 goto error_close_sysfsfp;
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200155 } else if (ret != 5) {
156 ret = -EIO;
157 printf("scan type description didn't match\n");
158 goto error_close_sysfsfp;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000159 }
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000160 *be = (endianchar == 'b');
Jonathan Camerone58537c2010-10-08 12:14:14 +0100161 *bytes = padint / 8;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100162 if (*bits_used == 64)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100163 *mask = ~0;
164 else
165 *mask = (1 << *bits_used) - 1;
166 if (signchar == 's')
167 *is_signed = 1;
168 else
169 *is_signed = 0;
Hartmut Knaack53118552015-05-31 14:40:14 +0200170 if (fclose(sysfsfp)) {
171 ret = -errno;
172 printf("Failed to close %s\n", filename);
173 goto error_free_filename;
174 }
175
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000176 free(filename);
177
178 filename = 0;
Peter Meerwald578f7372012-06-25 23:13:24 +0200179 sysfsfp = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100180 }
Peter Meerwald578f7372012-06-25 23:13:24 +0200181error_close_sysfsfp:
182 if (sysfsfp)
Hartmut Knaack53118552015-05-31 14:40:14 +0200183 if (fclose(sysfsfp))
184 perror("iioutils_get_type(): Failed to close file");
185
Jonathan Camerone58537c2010-10-08 12:14:14 +0100186error_free_filename:
187 if (filename)
188 free(filename);
189error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200190 if (closedir(dp) == -1)
191 perror("iioutils_get_type(): Failed to close directory");
192
Jonathan Camerone58537c2010-10-08 12:14:14 +0100193error_free_builtname_generic:
194 free(builtname_generic);
195error_free_builtname:
196 free(builtname);
197error_free_scan_el_dir:
198 free(scan_el_dir);
199error_ret:
200 return ret;
201}
202
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200203int iioutils_get_param_float(float *output,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100204 const char *param_name,
205 const char *device_dir,
206 const char *name,
207 const char *generic_name)
208{
209 FILE *sysfsfp;
210 int ret;
211 DIR *dp;
212 char *builtname, *builtname_generic;
213 char *filename = NULL;
214 const struct dirent *ent;
215
216 ret = asprintf(&builtname, "%s_%s", name, param_name);
217 if (ret < 0) {
218 ret = -ENOMEM;
219 goto error_ret;
220 }
221 ret = asprintf(&builtname_generic,
222 "%s_%s", generic_name, param_name);
223 if (ret < 0) {
224 ret = -ENOMEM;
225 goto error_free_builtname;
226 }
227 dp = opendir(device_dir);
228 if (dp == NULL) {
229 ret = -errno;
230 goto error_free_builtname_generic;
231 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200232 ret = -ENOENT;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100233 while (ent = readdir(dp), ent != NULL)
234 if ((strcmp(builtname, ent->d_name) == 0) ||
235 (strcmp(builtname_generic, ent->d_name) == 0)) {
236 ret = asprintf(&filename,
237 "%s/%s", device_dir, ent->d_name);
238 if (ret < 0) {
239 ret = -ENOMEM;
240 goto error_closedir;
241 }
242 sysfsfp = fopen(filename, "r");
243 if (!sysfsfp) {
244 ret = -errno;
245 goto error_free_filename;
246 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200247 errno = 0;
248 if (fscanf(sysfsfp, "%f", output) != 1)
249 ret = errno ? -errno : -ENODATA;
250
Jonathan Camerone58537c2010-10-08 12:14:14 +0100251 break;
252 }
253error_free_filename:
254 if (filename)
255 free(filename);
256error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200257 if (closedir(dp) == -1)
258 perror("iioutils_get_param_float(): Failed to close directory");
259
Jonathan Camerone58537c2010-10-08 12:14:14 +0100260error_free_builtname_generic:
261 free(builtname_generic);
262error_free_builtname:
263 free(builtname);
264error_ret:
265 return ret;
266}
267
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100268/**
269 * bsort_channel_array_by_index() - reorder so that the array is in index order
270 *
271 **/
272
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200273void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100274 int cnt)
275{
276
277 struct iio_channel_info temp;
278 int x, y;
279
280 for (x = 0; x < cnt; x++)
281 for (y = 0; y < (cnt - 1); y++)
282 if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
283 temp = (*ci_array)[y + 1];
284 (*ci_array)[y + 1] = (*ci_array)[y];
285 (*ci_array)[y] = temp;
286 }
287}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100288
289/**
290 * build_channel_array() - function to figure out what channels are present
291 * @device_dir: the IIO device directory in sysfs
292 * @
293 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200294int build_channel_array(const char *device_dir,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100295 struct iio_channel_info **ci_array,
296 int *counter)
297{
298 DIR *dp;
299 FILE *sysfsfp;
Peter Meerwald10937922012-06-25 23:12:12 +0200300 int count, i;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100301 struct iio_channel_info *current;
302 int ret;
303 const struct dirent *ent;
304 char *scan_el_dir;
305 char *filename;
306
307 *counter = 0;
308 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
309 if (ret < 0) {
310 ret = -ENOMEM;
311 goto error_ret;
312 }
313 dp = opendir(scan_el_dir);
314 if (dp == NULL) {
315 ret = -errno;
316 goto error_free_name;
317 }
318 while (ent = readdir(dp), ent != NULL)
319 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
320 "_en") == 0) {
321 ret = asprintf(&filename,
322 "%s/%s", scan_el_dir, ent->d_name);
323 if (ret < 0) {
324 ret = -ENOMEM;
325 goto error_close_dir;
326 }
327 sysfsfp = fopen(filename, "r");
328 if (sysfsfp == NULL) {
329 ret = -errno;
330 free(filename);
331 goto error_close_dir;
332 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200333 errno = 0;
334 if (fscanf(sysfsfp, "%i", &ret) != 1) {
335 ret = errno ? -errno : -ENODATA;
336 if (fclose(sysfsfp))
337 perror("build_channel_array(): Failed to close file");
338
339 free(filename);
340 goto error_close_dir;
341 }
342
Jonathan Camerone58537c2010-10-08 12:14:14 +0100343 if (ret == 1)
344 (*counter)++;
Hartmut Knaack53118552015-05-31 14:40:14 +0200345 if (fclose(sysfsfp)) {
346 ret = -errno;
347 free(filename);
348 goto error_close_dir;
349 }
350
Jonathan Camerone58537c2010-10-08 12:14:14 +0100351 free(filename);
352 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100353 *ci_array = malloc(sizeof(**ci_array) * (*counter));
Jonathan Camerone58537c2010-10-08 12:14:14 +0100354 if (*ci_array == NULL) {
355 ret = -ENOMEM;
356 goto error_close_dir;
357 }
358 seekdir(dp, 0);
Michael Hennerich7ccd4502011-02-24 16:34:53 +0100359 count = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100360 while (ent = readdir(dp), ent != NULL) {
361 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
362 "_en") == 0) {
Craig Markwardt66c65d92014-01-01 15:38:52 +0000363 int current_enabled = 0;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300364
Jonathan Camerone58537c2010-10-08 12:14:14 +0100365 current = &(*ci_array)[count++];
366 ret = asprintf(&filename,
367 "%s/%s", scan_el_dir, ent->d_name);
368 if (ret < 0) {
369 ret = -ENOMEM;
370 /* decrement count to avoid freeing name */
371 count--;
372 goto error_cleanup_array;
373 }
374 sysfsfp = fopen(filename, "r");
375 if (sysfsfp == NULL) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100376 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200377 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200378 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100379 goto error_cleanup_array;
380 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200381 errno = 0;
382 if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
383 ret = errno ? -errno : -ENODATA;
384 free(filename);
385 count--;
386 goto error_cleanup_array;
387 }
388
389 if (fclose(sysfsfp)) {
390 ret = -errno;
391 free(filename);
392 count--;
393 goto error_cleanup_array;
394 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100395
Craig Markwardt66c65d92014-01-01 15:38:52 +0000396 if (!current_enabled) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100397 free(filename);
398 count--;
399 continue;
400 }
401
Jonathan Camerone58537c2010-10-08 12:14:14 +0100402 current->scale = 1.0;
403 current->offset = 0;
404 current->name = strndup(ent->d_name,
405 strlen(ent->d_name) -
406 strlen("_en"));
407 if (current->name == NULL) {
408 free(filename);
409 ret = -ENOMEM;
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200410 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100411 goto error_cleanup_array;
412 }
413 /* Get the generic and specific name elements */
414 ret = iioutils_break_up_name(current->name,
415 &current->generic_name);
416 if (ret) {
417 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200418 free(current->name);
419 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100420 goto error_cleanup_array;
421 }
422 ret = asprintf(&filename,
423 "%s/%s_index",
424 scan_el_dir,
425 current->name);
426 if (ret < 0) {
427 free(filename);
428 ret = -ENOMEM;
429 goto error_cleanup_array;
430 }
431 sysfsfp = fopen(filename, "r");
Hartmut Knaack53118552015-05-31 14:40:14 +0200432 if (sysfsfp == NULL) {
433 ret = -errno;
434 printf("failed to open %s\n", filename);
435 free(filename);
436 goto error_cleanup_array;
437 }
438
439 errno = 0;
440 if (fscanf(sysfsfp, "%u", &current->index) != 1) {
441 ret = errno ? -errno : -ENODATA;
442 if (fclose(sysfsfp))
443 perror("build_channel_array(): Failed to close file");
444
445 free(filename);
446 goto error_cleanup_array;
447 }
448
449 if (fclose(sysfsfp)) {
450 ret = -errno;
451 free(filename);
452 goto error_cleanup_array;
453 }
454
Jonathan Camerone58537c2010-10-08 12:14:14 +0100455 free(filename);
456 /* Find the scale */
457 ret = iioutils_get_param_float(&current->scale,
458 "scale",
459 device_dir,
460 current->name,
461 current->generic_name);
462 if (ret < 0)
463 goto error_cleanup_array;
464 ret = iioutils_get_param_float(&current->offset,
465 "offset",
466 device_dir,
467 current->name,
468 current->generic_name);
469 if (ret < 0)
470 goto error_cleanup_array;
471 ret = iioutils_get_type(&current->is_signed,
472 &current->bytes,
473 &current->bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +0100474 &current->shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100475 &current->mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000476 &current->be,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100477 device_dir,
478 current->name,
479 current->generic_name);
Hartmut Knaack53118552015-05-31 14:40:14 +0200480 if (ret < 0)
481 goto error_cleanup_array;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100482 }
483 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100484
Hartmut Knaack53118552015-05-31 14:40:14 +0200485 if (closedir(dp) == -1) {
486 ret = -errno;
487 goto error_cleanup_array;
488 }
489
Hartmut Knaack66dd08f2015-05-31 14:39:43 +0200490 free(scan_el_dir);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100491 /* reorder so that the array is in index order */
492 bsort_channel_array_by_index(ci_array, *counter);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100493
494 return 0;
495
496error_cleanup_array:
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200497 for (i = count - 1; i >= 0; i--) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100498 free((*ci_array)[i].name);
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200499 free((*ci_array)[i].generic_name);
500 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100501 free(*ci_array);
502error_close_dir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200503 if (dp)
504 if (closedir(dp) == -1)
505 perror("build_channel_array(): Failed to close dir");
506
Jonathan Camerone58537c2010-10-08 12:14:14 +0100507error_free_name:
508 free(scan_el_dir);
509error_ret:
510 return ret;
511}
512
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200513int calc_digits(int num)
514{
515 int count = 0;
516
517 while (num != 0) {
518 num /= 10;
519 count++;
520 }
521
522 return count;
523}
524
Jonathan Camerone58537c2010-10-08 12:14:14 +0100525/**
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100526 * find_type_by_name() - function to match top level types by name
527 * @name: top level type instance name
528 * @type: the type of top level instance being sort
529 *
530 * Typical types this is used for are device and trigger.
531 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200532int find_type_by_name(const char *name, const char *type)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100533{
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100534 const struct dirent *ent;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200535 int number, numstrlen, ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100536
537 FILE *nameFile;
538 DIR *dp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100539 char thisname[IIO_MAX_NAME_LENGTH];
540 char *filename;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100541
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100542 dp = opendir(iio_dir);
543 if (dp == NULL) {
Peter Meerwaldc866ffc2012-07-01 00:47:41 +0200544 printf("No industrialio devices available\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100545 return -ENODEV;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100546 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100547
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100548 while (ent = readdir(dp), ent != NULL) {
549 if (strcmp(ent->d_name, ".") != 0 &&
550 strcmp(ent->d_name, "..") != 0 &&
551 strlen(ent->d_name) > strlen(type) &&
552 strncmp(ent->d_name, type, strlen(type)) == 0) {
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200553 errno = 0;
554 ret = sscanf(ent->d_name + strlen(type), "%d", &number);
555 if (ret < 0) {
556 ret = -errno;
557 printf("failed to read element number\n");
558 goto error_close_dir;
559 } else if (ret != 1) {
560 ret = -EIO;
561 printf("failed to match element number\n");
562 goto error_close_dir;
563 }
564
565 numstrlen = calc_digits(number);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100566 /* verify the next character is not a colon */
567 if (strncmp(ent->d_name + strlen(type) + numstrlen,
568 ":",
569 1) != 0) {
570 filename = malloc(strlen(iio_dir)
571 + strlen(type)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100572 + numstrlen
Barry Songb6ee30a2010-05-25 17:40:04 +0800573 + 6);
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200574 if (filename == NULL) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200575 ret = -ENOMEM;
576 goto error_close_dir;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200577 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200578
579 ret = sprintf(filename, "%s%s%d/name", iio_dir,
580 type, number);
581 if (ret < 0) {
582 free(filename);
583 goto error_close_dir;
584 }
585
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100586 nameFile = fopen(filename, "r");
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200587 if (!nameFile) {
588 free(filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100589 continue;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200590 }
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100591 free(filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200592 errno = 0;
593 if (fscanf(nameFile, "%s", thisname) != 1) {
594 ret = errno ? -errno : -ENODATA;
595 goto error_close_dir;
596 }
597
598 if (fclose(nameFile)) {
599 ret = -errno;
600 goto error_close_dir;
601 }
602
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200603 if (strcmp(name, thisname) == 0) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200604 if (closedir(dp) == -1)
605 return -errno;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200606 return number;
607 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100608 }
609 }
610 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200611 if (closedir(dp) == -1)
612 return -errno;
613
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100614 return -ENODEV;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200615
616error_close_dir:
617 if (closedir(dp) == -1)
618 perror("find_type_by_name(): Failed to close directory");
619 return ret;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100620}
621
Hartmut Knaack2156b172015-05-31 14:40:01 +0200622static int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100623{
Sebastian Andrzej Siewior11cb4542013-10-07 13:42:00 +0100624 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100625 FILE *sysfsfp;
626 int test;
627 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300628
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100629 if (temp == NULL)
630 return -ENOMEM;
Hartmut Knaack53118552015-05-31 14:40:14 +0200631 ret = sprintf(temp, "%s/%s", basedir, filename);
632 if (ret < 0)
633 goto error_free;
634
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100635 sysfsfp = fopen(temp, "w");
636 if (sysfsfp == NULL) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100637 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200638 printf("failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100639 goto error_free;
640 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200641 ret = fprintf(sysfsfp, "%d", val);
642 if (ret < 0) {
643 if (fclose(sysfsfp))
644 perror("_write_sysfs_int(): Failed to close dir");
645
646 goto error_free;
647 }
648
649 if (fclose(sysfsfp)) {
650 ret = -errno;
651 goto error_free;
652 }
653
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100654 if (verify) {
655 sysfsfp = fopen(temp, "r");
656 if (sysfsfp == NULL) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100657 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200658 printf("failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100659 goto error_free;
660 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200661 if (fscanf(sysfsfp, "%d", &test) != 1) {
662 ret = errno ? -errno : -ENODATA;
663 if (fclose(sysfsfp))
664 perror("_write_sysfs_int(): Failed to close dir");
665
666 goto error_free;
667 }
668
669 if (fclose(sysfsfp)) {
670 ret = -errno;
671 goto error_free;
672 }
673
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100674 if (test != val) {
675 printf("Possible failure in int write %d to %s%s\n",
676 val,
677 basedir,
678 filename);
679 ret = -1;
680 }
681 }
682error_free:
683 free(temp);
684 return ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100685}
686
687int write_sysfs_int(char *filename, char *basedir, int val)
688{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100689 return _write_sysfs_int(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100690}
691
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100692int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
693{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100694 return _write_sysfs_int(filename, basedir, val, 1);
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100695}
696
Hartmut Knaack2156b172015-05-31 14:40:01 +0200697static int _write_sysfs_string(char *filename, char *basedir, char *val,
698 int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100699{
Jonathan Camerone58537c2010-10-08 12:14:14 +0100700 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100701 FILE *sysfsfp;
702 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300703
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100704 if (temp == NULL) {
705 printf("Memory allocation failed\n");
706 return -ENOMEM;
707 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200708 ret = sprintf(temp, "%s/%s", basedir, filename);
709 if (ret < 0)
710 goto error_free;
711
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100712 sysfsfp = fopen(temp, "w");
713 if (sysfsfp == NULL) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100714 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200715 printf("Could not open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100716 goto error_free;
717 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200718 ret = fprintf(sysfsfp, "%s", val);
719 if (ret < 0) {
720 if (fclose(sysfsfp))
721 perror("_write_sysfs_string(): Failed to close dir");
722
723 goto error_free;
724 }
725
726 if (fclose(sysfsfp)) {
727 ret = -errno;
728 goto error_free;
729 }
730
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100731 if (verify) {
732 sysfsfp = fopen(temp, "r");
733 if (sysfsfp == NULL) {
734 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200735 printf("could not open file to verify\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100736 goto error_free;
737 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200738 if (fscanf(sysfsfp, "%s", temp) != 1) {
739 ret = errno ? -errno : -ENODATA;
740 if (fclose(sysfsfp))
741 perror("_write_sysfs_string(): Failed to close dir");
742
743 goto error_free;
744 }
745
746 if (fclose(sysfsfp)) {
747 ret = -errno;
748 goto error_free;
749 }
750
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100751 if (strcmp(temp, val) != 0) {
752 printf("Possible failure in string write of %s "
753 "Should be %s "
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300754 "written to %s\%s\n",
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100755 temp,
756 val,
757 basedir,
758 filename);
759 ret = -1;
760 }
761 }
762error_free:
763 free(temp);
764
765 return ret;
766}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100767
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100768/**
769 * write_sysfs_string_and_verify() - string write, readback and verify
770 * @filename: name of file to write to
771 * @basedir: the sysfs directory in which the file is to be found
772 * @val: the string to write
773 **/
774int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
775{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100776 return _write_sysfs_string(filename, basedir, val, 1);
777}
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100778
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100779int write_sysfs_string(char *filename, char *basedir, char *val)
780{
781 return _write_sysfs_string(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100782}
783
784int read_sysfs_posint(char *filename, char *basedir)
785{
786 int ret;
787 FILE *sysfsfp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100788 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300789
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100790 if (temp == NULL) {
791 printf("Memory allocation failed");
792 return -ENOMEM;
793 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200794 ret = sprintf(temp, "%s/%s", basedir, filename);
795 if (ret < 0)
796 goto error_free;
797
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100798 sysfsfp = fopen(temp, "r");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100799 if (sysfsfp == NULL) {
800 ret = -errno;
801 goto error_free;
802 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200803 errno = 0;
804 if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
805 ret = errno ? -errno : -ENODATA;
806 if (fclose(sysfsfp))
807 perror("read_sysfs_posint(): Failed to close dir");
808
809 goto error_free;
810 }
811
812 if (fclose(sysfsfp))
813 ret = -errno;
814
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100815error_free:
816 free(temp);
817 return ret;
818}
819
820int read_sysfs_float(char *filename, char *basedir, float *val)
821{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000822 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100823 FILE *sysfsfp;
824 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300825
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100826 if (temp == NULL) {
827 printf("Memory allocation failed");
828 return -ENOMEM;
829 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200830 ret = sprintf(temp, "%s/%s", basedir, filename);
831 if (ret < 0)
832 goto error_free;
833
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100834 sysfsfp = fopen(temp, "r");
835 if (sysfsfp == NULL) {
836 ret = -errno;
837 goto error_free;
838 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200839 errno = 0;
840 if (fscanf(sysfsfp, "%f\n", val) != 1) {
841 ret = errno ? -errno : -ENODATA;
842 if (fclose(sysfsfp))
843 perror("read_sysfs_float(): Failed to close dir");
844
845 goto error_free;
846 }
847
848 if (fclose(sysfsfp))
849 ret = -errno;
850
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100851error_free:
852 free(temp);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100853 return ret;
854}
Manuel Stahl49d916e2014-05-02 13:23:00 +0100855
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000856int read_sysfs_string(const char *filename, const char *basedir, char *str)
Manuel Stahl49d916e2014-05-02 13:23:00 +0100857{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000858 int ret = 0;
Manuel Stahl49d916e2014-05-02 13:23:00 +0100859 FILE *sysfsfp;
860 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300861
Manuel Stahl49d916e2014-05-02 13:23:00 +0100862 if (temp == NULL) {
863 printf("Memory allocation failed");
864 return -ENOMEM;
865 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200866 ret = sprintf(temp, "%s/%s", basedir, filename);
867 if (ret < 0)
868 goto error_free;
869
Manuel Stahl49d916e2014-05-02 13:23:00 +0100870 sysfsfp = fopen(temp, "r");
871 if (sysfsfp == NULL) {
872 ret = -errno;
873 goto error_free;
874 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200875 errno = 0;
876 if (fscanf(sysfsfp, "%s\n", str) != 1) {
877 ret = errno ? -errno : -ENODATA;
878 if (fclose(sysfsfp))
879 perror("read_sysfs_string(): Failed to close dir");
880
881 goto error_free;
882 }
883
884 if (fclose(sysfsfp))
885 ret = -errno;
886
Manuel Stahl49d916e2014-05-02 13:23:00 +0100887error_free:
888 free(temp);
889 return ret;
890}
Cristina Opriceana37e3be92015-03-04 02:37:15 +0200891
892#endif /* _IIO_UTILS_H */