]>
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 | ||
d9d7b990 IT |
23 | static char * const iio_direction[] = { |
24 | "in", | |
25 | "out", | |
26 | }; | |
27 | ||
e58537cc JC |
28 | /** |
29 | * iioutils_break_up_name() - extract generic name from full channel name | |
30 | * @full_name: the full channel name | |
31 | * @generic_name: the output generic channel name | |
32 | **/ | |
bdcb31d0 | 33 | int iioutils_break_up_name(const char *full_name, |
e58537cc JC |
34 | char **generic_name) |
35 | { | |
36 | char *current; | |
37 | char *w, *r; | |
d9d7b990 IT |
38 | char *working, *prefix = ""; |
39 | int i; | |
40 | ||
41 | for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++) | |
42 | if (!strncmp(full_name, iio_direction[i], | |
43 | strlen(iio_direction[i]))) { | |
44 | prefix = iio_direction[i]; | |
45 | break; | |
46 | } | |
79bdd48a | 47 | |
d9d7b990 | 48 | current = strdup(full_name + strlen(prefix) + 1); |
e58537cc | 49 | working = strtok(current, "_\0"); |
d9d7b990 | 50 | |
e58537cc JC |
51 | w = working; |
52 | r = working; | |
53 | ||
8b68bb20 | 54 | while (*r != '\0') { |
e58537cc JC |
55 | if (!isdigit(*r)) { |
56 | *w = *r; | |
57 | w++; | |
58 | } | |
59 | r++; | |
60 | } | |
61 | *w = '\0'; | |
d9d7b990 | 62 | asprintf(generic_name, "%s_%s", prefix, working); |
e58537cc JC |
63 | free(current); |
64 | ||
65 | return 0; | |
66 | } | |
67 | ||
e58537cc JC |
68 | /** |
69 | * iioutils_get_type() - find and process _type attribute data | |
70 | * @is_signed: output whether channel is signed | |
71 | * @bytes: output how many bytes the channel storage occupies | |
72 | * @mask: output a bit mask for the raw data | |
117cf8b7 | 73 | * @be: big endian |
e58537cc JC |
74 | * @device_dir: the iio device directory |
75 | * @name: the channel name | |
76 | * @generic_name: the channel type name | |
77 | **/ | |
bdcb31d0 | 78 | int iioutils_get_type(unsigned *is_signed, |
e58537cc JC |
79 | unsigned *bytes, |
80 | unsigned *bits_used, | |
52615d47 | 81 | unsigned *shift, |
e58537cc | 82 | uint64_t *mask, |
117cf8b7 | 83 | unsigned *be, |
e58537cc JC |
84 | const char *device_dir, |
85 | const char *name, | |
86 | const char *generic_name) | |
87 | { | |
88 | FILE *sysfsfp; | |
89 | int ret; | |
90 | DIR *dp; | |
91 | char *scan_el_dir, *builtname, *builtname_generic, *filename = 0; | |
117cf8b7 | 92 | char signchar, endianchar; |
fc7f95a9 | 93 | unsigned padint; |
e58537cc JC |
94 | const struct dirent *ent; |
95 | ||
96 | ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir); | |
97 | if (ret < 0) { | |
98 | ret = -ENOMEM; | |
99 | goto error_ret; | |
100 | } | |
101 | ret = asprintf(&builtname, FORMAT_TYPE_FILE, name); | |
102 | if (ret < 0) { | |
103 | ret = -ENOMEM; | |
104 | goto error_free_scan_el_dir; | |
105 | } | |
106 | ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name); | |
107 | if (ret < 0) { | |
108 | ret = -ENOMEM; | |
109 | goto error_free_builtname; | |
110 | } | |
111 | ||
112 | dp = opendir(scan_el_dir); | |
113 | if (dp == NULL) { | |
114 | ret = -errno; | |
115 | goto error_free_builtname_generic; | |
116 | } | |
117 | while (ent = readdir(dp), ent != NULL) | |
118 | /* | |
119 | * Do we allow devices to override a generic name with | |
120 | * a specific one? | |
121 | */ | |
122 | if ((strcmp(builtname, ent->d_name) == 0) || | |
123 | (strcmp(builtname_generic, ent->d_name) == 0)) { | |
124 | ret = asprintf(&filename, | |
125 | "%s/%s", scan_el_dir, ent->d_name); | |
126 | if (ret < 0) { | |
127 | ret = -ENOMEM; | |
128 | goto error_closedir; | |
129 | } | |
130 | sysfsfp = fopen(filename, "r"); | |
131 | if (sysfsfp == NULL) { | |
e58537cc | 132 | ret = -errno; |
2b6a6e67 | 133 | printf("failed to open %s\n", filename); |
e58537cc JC |
134 | goto error_free_filename; |
135 | } | |
a7f7c364 JC |
136 | |
137 | ret = fscanf(sysfsfp, | |
138 | "%ce:%c%u/%u>>%u", | |
139 | &endianchar, | |
140 | &signchar, | |
141 | bits_used, | |
142 | &padint, shift); | |
143 | if (ret < 0) { | |
578f737d | 144 | ret = -errno; |
2b6a6e67 | 145 | printf("failed to pass scan type description\n"); |
578f737d | 146 | goto error_close_sysfsfp; |
dc8b5d6e HK |
147 | } else if (ret != 5) { |
148 | ret = -EIO; | |
149 | printf("scan type description didn't match\n"); | |
150 | goto error_close_sysfsfp; | |
a7f7c364 | 151 | } |
117cf8b7 | 152 | *be = (endianchar == 'b'); |
e58537cc | 153 | *bytes = padint / 8; |
fc7f95a9 | 154 | if (*bits_used == 64) |
e58537cc JC |
155 | *mask = ~0; |
156 | else | |
157 | *mask = (1 << *bits_used) - 1; | |
158 | if (signchar == 's') | |
159 | *is_signed = 1; | |
160 | else | |
161 | *is_signed = 0; | |
a7f7c364 JC |
162 | fclose(sysfsfp); |
163 | free(filename); | |
164 | ||
165 | filename = 0; | |
578f737d | 166 | sysfsfp = 0; |
e58537cc | 167 | } |
578f737d PM |
168 | error_close_sysfsfp: |
169 | if (sysfsfp) | |
170 | fclose(sysfsfp); | |
e58537cc JC |
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 | ||
bdcb31d0 | 186 | int iioutils_get_param_float(float *output, |
e58537cc JC |
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 | ||
8b68bb20 MH |
245 | /** |
246 | * bsort_channel_array_by_index() - reorder so that the array is in index order | |
247 | * | |
248 | **/ | |
249 | ||
bdcb31d0 | 250 | void bsort_channel_array_by_index(struct iio_channel_info **ci_array, |
8b68bb20 MH |
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 | } | |
e58537cc JC |
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 | **/ | |
bdcb31d0 | 271 | int build_channel_array(const char *device_dir, |
e58537cc JC |
272 | struct iio_channel_info **ci_array, |
273 | int *counter) | |
274 | { | |
275 | DIR *dp; | |
276 | FILE *sysfsfp; | |
10937921 | 277 | int count, i; |
e58537cc JC |
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 | } | |
34683a5c | 310 | fscanf(sysfsfp, "%i", &ret); |
e58537cc JC |
311 | if (ret == 1) |
312 | (*counter)++; | |
313 | fclose(sysfsfp); | |
314 | free(filename); | |
315 | } | |
8b68bb20 | 316 | *ci_array = malloc(sizeof(**ci_array) * (*counter)); |
e58537cc JC |
317 | if (*ci_array == NULL) { |
318 | ret = -ENOMEM; | |
319 | goto error_close_dir; | |
320 | } | |
321 | seekdir(dp, 0); | |
7ccd4506 | 322 | count = 0; |
e58537cc JC |
323 | while (ent = readdir(dp), ent != NULL) { |
324 | if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), | |
325 | "_en") == 0) { | |
66c65d90 | 326 | int current_enabled = 0; |
79bdd48a | 327 | |
e58537cc JC |
328 | current = &(*ci_array)[count++]; |
329 | ret = asprintf(&filename, | |
330 | "%s/%s", scan_el_dir, ent->d_name); | |
331 | if (ret < 0) { | |
332 | ret = -ENOMEM; | |
333 | /* decrement count to avoid freeing name */ | |
334 | count--; | |
335 | goto error_cleanup_array; | |
336 | } | |
337 | sysfsfp = fopen(filename, "r"); | |
338 | if (sysfsfp == NULL) { | |
e58537cc | 339 | ret = -errno; |
2b6a6e67 | 340 | free(filename); |
121b5e50 | 341 | count--; |
e58537cc JC |
342 | goto error_cleanup_array; |
343 | } | |
34683a5c | 344 | fscanf(sysfsfp, "%i", ¤t_enabled); |
e58537cc | 345 | fclose(sysfsfp); |
8b68bb20 | 346 | |
66c65d90 | 347 | if (!current_enabled) { |
8b68bb20 MH |
348 | free(filename); |
349 | count--; | |
350 | continue; | |
351 | } | |
352 | ||
e58537cc JC |
353 | current->scale = 1.0; |
354 | current->offset = 0; | |
355 | current->name = strndup(ent->d_name, | |
356 | strlen(ent->d_name) - | |
357 | strlen("_en")); | |
358 | if (current->name == NULL) { | |
359 | free(filename); | |
360 | ret = -ENOMEM; | |
121b5e50 | 361 | count--; |
e58537cc JC |
362 | goto error_cleanup_array; |
363 | } | |
364 | /* Get the generic and specific name elements */ | |
365 | ret = iioutils_break_up_name(current->name, | |
366 | ¤t->generic_name); | |
367 | if (ret) { | |
368 | free(filename); | |
121b5e50 HK |
369 | free(current->name); |
370 | count--; | |
e58537cc JC |
371 | goto error_cleanup_array; |
372 | } | |
373 | ret = asprintf(&filename, | |
374 | "%s/%s_index", | |
375 | scan_el_dir, | |
376 | current->name); | |
377 | if (ret < 0) { | |
378 | free(filename); | |
379 | ret = -ENOMEM; | |
380 | goto error_cleanup_array; | |
381 | } | |
382 | sysfsfp = fopen(filename, "r"); | |
383 | fscanf(sysfsfp, "%u", ¤t->index); | |
384 | fclose(sysfsfp); | |
385 | free(filename); | |
386 | /* Find the scale */ | |
387 | ret = iioutils_get_param_float(¤t->scale, | |
388 | "scale", | |
389 | device_dir, | |
390 | current->name, | |
391 | current->generic_name); | |
392 | if (ret < 0) | |
393 | goto error_cleanup_array; | |
394 | ret = iioutils_get_param_float(¤t->offset, | |
395 | "offset", | |
396 | device_dir, | |
397 | current->name, | |
398 | current->generic_name); | |
399 | if (ret < 0) | |
400 | goto error_cleanup_array; | |
401 | ret = iioutils_get_type(¤t->is_signed, | |
402 | ¤t->bytes, | |
403 | ¤t->bits_used, | |
52615d47 | 404 | ¤t->shift, |
e58537cc | 405 | ¤t->mask, |
117cf8b7 | 406 | ¤t->be, |
e58537cc JC |
407 | device_dir, |
408 | current->name, | |
409 | current->generic_name); | |
410 | } | |
411 | } | |
8b68bb20 | 412 | |
e58537cc | 413 | closedir(dp); |
66dd08fd | 414 | free(scan_el_dir); |
8b68bb20 MH |
415 | /* reorder so that the array is in index order */ |
416 | bsort_channel_array_by_index(ci_array, *counter); | |
e58537cc JC |
417 | |
418 | return 0; | |
419 | ||
420 | error_cleanup_array: | |
63f05c85 | 421 | for (i = count - 1; i >= 0; i--) { |
e58537cc | 422 | free((*ci_array)[i].name); |
63f05c85 HK |
423 | free((*ci_array)[i].generic_name); |
424 | } | |
e58537cc JC |
425 | free(*ci_array); |
426 | error_close_dir: | |
427 | closedir(dp); | |
428 | error_free_name: | |
429 | free(scan_el_dir); | |
430 | error_ret: | |
431 | return ret; | |
432 | } | |
433 | ||
9d8ae6c8 JC |
434 | /** |
435 | * find_type_by_name() - function to match top level types by name | |
436 | * @name: top level type instance name | |
437 | * @type: the type of top level instance being sort | |
438 | * | |
439 | * Typical types this is used for are device and trigger. | |
440 | **/ | |
bdcb31d0 | 441 | int find_type_by_name(const char *name, const char *type) |
c57f1ba7 | 442 | { |
c57f1ba7 | 443 | const struct dirent *ent; |
9d8ae6c8 | 444 | int number, numstrlen; |
c57f1ba7 JC |
445 | |
446 | FILE *nameFile; | |
447 | DIR *dp; | |
9d8ae6c8 JC |
448 | char thisname[IIO_MAX_NAME_LENGTH]; |
449 | char *filename; | |
9d8ae6c8 | 450 | |
c57f1ba7 JC |
451 | dp = opendir(iio_dir); |
452 | if (dp == NULL) { | |
c866ffc7 | 453 | printf("No industrialio devices available\n"); |
9d8ae6c8 | 454 | return -ENODEV; |
c57f1ba7 | 455 | } |
9d8ae6c8 | 456 | |
c57f1ba7 | 457 | while (ent = readdir(dp), ent != NULL) { |
c57f1ba7 | 458 | if (strcmp(ent->d_name, ".") != 0 && |
9d8ae6c8 JC |
459 | strcmp(ent->d_name, "..") != 0 && |
460 | strlen(ent->d_name) > strlen(type) && | |
461 | strncmp(ent->d_name, type, strlen(type)) == 0) { | |
462 | numstrlen = sscanf(ent->d_name + strlen(type), | |
463 | "%d", | |
464 | &number); | |
465 | /* verify the next character is not a colon */ | |
466 | if (strncmp(ent->d_name + strlen(type) + numstrlen, | |
467 | ":", | |
468 | 1) != 0) { | |
469 | filename = malloc(strlen(iio_dir) | |
470 | + strlen(type) | |
9d8ae6c8 | 471 | + numstrlen |
b6ee30a2 | 472 | + 6); |
a4d429e3 PM |
473 | if (filename == NULL) { |
474 | closedir(dp); | |
9d8ae6c8 | 475 | return -ENOMEM; |
a4d429e3 | 476 | } |
9d8ae6c8 JC |
477 | sprintf(filename, "%s%s%d/name", |
478 | iio_dir, | |
479 | type, | |
480 | number); | |
481 | nameFile = fopen(filename, "r"); | |
a4d429e3 PM |
482 | if (!nameFile) { |
483 | free(filename); | |
9d8ae6c8 | 484 | continue; |
a4d429e3 | 485 | } |
9d8ae6c8 | 486 | free(filename); |
c57f1ba7 | 487 | fscanf(nameFile, "%s", thisname); |
c57f1ba7 | 488 | fclose(nameFile); |
a4d429e3 PM |
489 | if (strcmp(name, thisname) == 0) { |
490 | closedir(dp); | |
491 | return number; | |
492 | } | |
c57f1ba7 JC |
493 | } |
494 | } | |
495 | } | |
a4d429e3 | 496 | closedir(dp); |
9d8ae6c8 | 497 | return -ENODEV; |
c57f1ba7 JC |
498 | } |
499 | ||
bdcb31d0 | 500 | int _write_sysfs_int(char *filename, char *basedir, int val, int verify) |
c57f1ba7 | 501 | { |
11cb454f | 502 | int ret = 0; |
9d8ae6c8 JC |
503 | FILE *sysfsfp; |
504 | int test; | |
505 | char *temp = malloc(strlen(basedir) + strlen(filename) + 2); | |
79bdd48a | 506 | |
9d8ae6c8 JC |
507 | if (temp == NULL) |
508 | return -ENOMEM; | |
509 | sprintf(temp, "%s/%s", basedir, filename); | |
c57f1ba7 | 510 | sysfsfp = fopen(temp, "w"); |
9d8ae6c8 | 511 | if (sysfsfp == NULL) { |
9d8ae6c8 | 512 | ret = -errno; |
2b6a6e67 | 513 | printf("failed to open %s\n", temp); |
9d8ae6c8 JC |
514 | goto error_free; |
515 | } | |
c57f1ba7 JC |
516 | fprintf(sysfsfp, "%d", val); |
517 | fclose(sysfsfp); | |
9d8ae6c8 JC |
518 | if (verify) { |
519 | sysfsfp = fopen(temp, "r"); | |
520 | if (sysfsfp == NULL) { | |
9d8ae6c8 | 521 | ret = -errno; |
2b6a6e67 | 522 | printf("failed to open %s\n", temp); |
9d8ae6c8 JC |
523 | goto error_free; |
524 | } | |
525 | fscanf(sysfsfp, "%d", &test); | |
ce7b04c6 | 526 | fclose(sysfsfp); |
9d8ae6c8 JC |
527 | if (test != val) { |
528 | printf("Possible failure in int write %d to %s%s\n", | |
529 | val, | |
530 | basedir, | |
531 | filename); | |
532 | ret = -1; | |
533 | } | |
534 | } | |
535 | error_free: | |
536 | free(temp); | |
537 | return ret; | |
538 | } | |
539 | ||
540 | int write_sysfs_int(char *filename, char *basedir, int val) | |
541 | { | |
542 | return _write_sysfs_int(filename, basedir, val, 0); | |
c57f1ba7 JC |
543 | } |
544 | ||
eaf86ff9 | 545 | int write_sysfs_int_and_verify(char *filename, char *basedir, int val) |
9d8ae6c8 JC |
546 | { |
547 | return _write_sysfs_int(filename, basedir, val, 1); | |
548 | } | |
549 | ||
550 | int _write_sysfs_string(char *filename, char *basedir, char *val, int verify) | |
eaf86ff9 | 551 | { |
e58537cc | 552 | int ret = 0; |
eaf86ff9 | 553 | FILE *sysfsfp; |
9d8ae6c8 | 554 | char *temp = malloc(strlen(basedir) + strlen(filename) + 2); |
79bdd48a | 555 | |
9d8ae6c8 JC |
556 | if (temp == NULL) { |
557 | printf("Memory allocation failed\n"); | |
558 | return -ENOMEM; | |
559 | } | |
560 | sprintf(temp, "%s/%s", basedir, filename); | |
eaf86ff9 | 561 | sysfsfp = fopen(temp, "w"); |
9d8ae6c8 | 562 | if (sysfsfp == NULL) { |
9d8ae6c8 | 563 | ret = -errno; |
2b6a6e67 | 564 | printf("Could not open %s\n", temp); |
9d8ae6c8 JC |
565 | goto error_free; |
566 | } | |
567 | fprintf(sysfsfp, "%s", val); | |
eaf86ff9 | 568 | fclose(sysfsfp); |
9d8ae6c8 JC |
569 | if (verify) { |
570 | sysfsfp = fopen(temp, "r"); | |
571 | if (sysfsfp == NULL) { | |
572 | ret = -errno; | |
2b6a6e67 | 573 | printf("could not open file to verify\n"); |
9d8ae6c8 JC |
574 | goto error_free; |
575 | } | |
576 | fscanf(sysfsfp, "%s", temp); | |
ce7b04c6 | 577 | fclose(sysfsfp); |
9d8ae6c8 JC |
578 | if (strcmp(temp, val) != 0) { |
579 | printf("Possible failure in string write of %s " | |
580 | "Should be %s " | |
25985edc | 581 | "written to %s\%s\n", |
9d8ae6c8 JC |
582 | temp, |
583 | val, | |
584 | basedir, | |
585 | filename); | |
586 | ret = -1; | |
587 | } | |
eaf86ff9 | 588 | } |
9d8ae6c8 JC |
589 | error_free: |
590 | free(temp); | |
eaf86ff9 | 591 | |
9d8ae6c8 | 592 | return ret; |
eaf86ff9 | 593 | } |
e58537cc | 594 | |
c57f1ba7 JC |
595 | /** |
596 | * write_sysfs_string_and_verify() - string write, readback and verify | |
597 | * @filename: name of file to write to | |
598 | * @basedir: the sysfs directory in which the file is to be found | |
599 | * @val: the string to write | |
600 | **/ | |
601 | int write_sysfs_string_and_verify(char *filename, char *basedir, char *val) | |
602 | { | |
9d8ae6c8 JC |
603 | return _write_sysfs_string(filename, basedir, val, 1); |
604 | } | |
c57f1ba7 | 605 | |
9d8ae6c8 JC |
606 | int write_sysfs_string(char *filename, char *basedir, char *val) |
607 | { | |
608 | return _write_sysfs_string(filename, basedir, val, 0); | |
c57f1ba7 JC |
609 | } |
610 | ||
611 | int read_sysfs_posint(char *filename, char *basedir) | |
612 | { | |
613 | int ret; | |
614 | FILE *sysfsfp; | |
9d8ae6c8 | 615 | char *temp = malloc(strlen(basedir) + strlen(filename) + 2); |
79bdd48a | 616 | |
9d8ae6c8 JC |
617 | if (temp == NULL) { |
618 | printf("Memory allocation failed"); | |
619 | return -ENOMEM; | |
620 | } | |
621 | sprintf(temp, "%s/%s", basedir, filename); | |
c57f1ba7 | 622 | sysfsfp = fopen(temp, "r"); |
9d8ae6c8 JC |
623 | if (sysfsfp == NULL) { |
624 | ret = -errno; | |
625 | goto error_free; | |
626 | } | |
c57f1ba7 JC |
627 | fscanf(sysfsfp, "%d\n", &ret); |
628 | fclose(sysfsfp); | |
9d8ae6c8 JC |
629 | error_free: |
630 | free(temp); | |
631 | return ret; | |
632 | } | |
633 | ||
634 | int read_sysfs_float(char *filename, char *basedir, float *val) | |
635 | { | |
f5709d5f | 636 | int ret = 0; |
9d8ae6c8 JC |
637 | FILE *sysfsfp; |
638 | char *temp = malloc(strlen(basedir) + strlen(filename) + 2); | |
79bdd48a | 639 | |
9d8ae6c8 JC |
640 | if (temp == NULL) { |
641 | printf("Memory allocation failed"); | |
642 | return -ENOMEM; | |
643 | } | |
644 | sprintf(temp, "%s/%s", basedir, filename); | |
645 | sysfsfp = fopen(temp, "r"); | |
646 | if (sysfsfp == NULL) { | |
647 | ret = -errno; | |
648 | goto error_free; | |
649 | } | |
650 | fscanf(sysfsfp, "%f\n", val); | |
651 | fclose(sysfsfp); | |
652 | error_free: | |
653 | free(temp); | |
c57f1ba7 JC |
654 | return ret; |
655 | } | |
49d916ec | 656 | |
f5709d5f | 657 | int read_sysfs_string(const char *filename, const char *basedir, char *str) |
49d916ec | 658 | { |
f5709d5f | 659 | int ret = 0; |
49d916ec MS |
660 | FILE *sysfsfp; |
661 | char *temp = malloc(strlen(basedir) + strlen(filename) + 2); | |
79bdd48a | 662 | |
49d916ec MS |
663 | if (temp == NULL) { |
664 | printf("Memory allocation failed"); | |
665 | return -ENOMEM; | |
666 | } | |
667 | sprintf(temp, "%s/%s", basedir, filename); | |
668 | sysfsfp = fopen(temp, "r"); | |
669 | if (sysfsfp == NULL) { | |
670 | ret = -errno; | |
671 | goto error_free; | |
672 | } | |
673 | fscanf(sysfsfp, "%s\n", str); | |
674 | fclose(sysfsfp); | |
675 | error_free: | |
676 | free(temp); | |
677 | return ret; | |
678 | } | |
37e3be9d CO |
679 | |
680 | #endif /* _IIO_UTILS_H */ |