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