blob: c9fedb79e3a2d2cec92f04a7860c6e2c055bd0fc [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 */
9
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010010#include <string.h>
11#include <stdlib.h>
Jonathan Camerone58537c2010-10-08 12:14:14 +010012#include <ctype.h>
13#include <stdio.h>
14#include <stdint.h>
Lars-Peter Clausenbc9f35d2011-10-26 17:27:44 +010015#include <dirent.h>
Peter Meerwaldbb233782012-06-25 23:12:17 +020016#include <errno.h>
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010017
Peter Meerwaldb42f2a02012-06-25 23:12:13 +020018/* Made up value to limit allocation sizes */
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010019#define IIO_MAX_NAME_LENGTH 30
20
Jonathan Cameron1aa04272011-08-30 12:32:47 +010021#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
Jonathan Camerone58537c2010-10-08 12:14:14 +010022#define FORMAT_TYPE_FILE "%s_type"
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +010023
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010024const char *iio_dir = "/sys/bus/iio/devices/";
25
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010026/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010027 * iioutils_break_up_name() - extract generic name from full channel name
28 * @full_name: the full channel name
29 * @generic_name: the output generic channel name
30 **/
Peter Meerwald42196d32012-06-25 23:12:15 +020031inline int iioutils_break_up_name(const char *full_name,
Jonathan Camerone58537c2010-10-08 12:14:14 +010032 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
Michael Hennerich8b68bb22011-03-08 08:55:48 +010042 while (*r != '\0') {
Jonathan Camerone58537c2010-10-08 12:14:14 +010043 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
56/**
57 * struct iio_channel_info - information about a given channel
58 * @name: channel name
59 * @generic_name: general name for channel type
60 * @scale: scale factor to be applied for conversion to si units
61 * @offset: offset to be applied for conversion to si units
62 * @index: the channel index in the buffer output
63 * @bytes: number of bytes occupied in buffer output
64 * @mask: a bit mask for the raw output
65 * @is_signed: is the raw value stored signed
66 * @enabled: is this channel enabled
67 **/
68struct iio_channel_info {
69 char *name;
70 char *generic_name;
71 float scale;
72 float offset;
73 unsigned index;
74 unsigned bytes;
75 unsigned bits_used;
Jonathan Cameron52615d42011-05-18 14:41:19 +010076 unsigned shift;
Jonathan Camerone58537c2010-10-08 12:14:14 +010077 uint64_t mask;
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000078 unsigned be;
Jonathan Camerone58537c2010-10-08 12:14:14 +010079 unsigned is_signed;
Jonathan Camerone58537c2010-10-08 12:14:14 +010080 unsigned location;
81};
82
83/**
84 * iioutils_get_type() - find and process _type attribute data
85 * @is_signed: output whether channel is signed
86 * @bytes: output how many bytes the channel storage occupies
87 * @mask: output a bit mask for the raw data
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000088 * @be: big endian
Jonathan Camerone58537c2010-10-08 12:14:14 +010089 * @device_dir: the iio device directory
90 * @name: the channel name
91 * @generic_name: the channel type name
92 **/
93inline int iioutils_get_type(unsigned *is_signed,
94 unsigned *bytes,
95 unsigned *bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +010096 unsigned *shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +010097 uint64_t *mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000098 unsigned *be,
Jonathan Camerone58537c2010-10-08 12:14:14 +010099 const char *device_dir,
100 const char *name,
101 const char *generic_name)
102{
103 FILE *sysfsfp;
104 int ret;
105 DIR *dp;
106 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000107 char signchar, endianchar;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100108 unsigned padint;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100109 const struct dirent *ent;
110
111 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
112 if (ret < 0) {
113 ret = -ENOMEM;
114 goto error_ret;
115 }
116 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
117 if (ret < 0) {
118 ret = -ENOMEM;
119 goto error_free_scan_el_dir;
120 }
121 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
122 if (ret < 0) {
123 ret = -ENOMEM;
124 goto error_free_builtname;
125 }
126
127 dp = opendir(scan_el_dir);
128 if (dp == NULL) {
129 ret = -errno;
130 goto error_free_builtname_generic;
131 }
132 while (ent = readdir(dp), ent != NULL)
133 /*
134 * Do we allow devices to override a generic name with
135 * a specific one?
136 */
137 if ((strcmp(builtname, ent->d_name) == 0) ||
138 (strcmp(builtname_generic, ent->d_name) == 0)) {
139 ret = asprintf(&filename,
140 "%s/%s", scan_el_dir, ent->d_name);
141 if (ret < 0) {
142 ret = -ENOMEM;
143 goto error_closedir;
144 }
145 sysfsfp = fopen(filename, "r");
146 if (sysfsfp == NULL) {
147 printf("failed to open %s\n", filename);
148 ret = -errno;
149 goto error_free_filename;
150 }
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000151
152 ret = fscanf(sysfsfp,
153 "%ce:%c%u/%u>>%u",
154 &endianchar,
155 &signchar,
156 bits_used,
157 &padint, shift);
158 if (ret < 0) {
159 printf("failed to pass scan type description\n");
Peter Meerwald578f7372012-06-25 23:13:24 +0200160 ret = -errno;
161 goto error_close_sysfsfp;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000162 }
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000163 *be = (endianchar == 'b');
Jonathan Camerone58537c2010-10-08 12:14:14 +0100164 *bytes = padint / 8;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100165 if (*bits_used == 64)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100166 *mask = ~0;
167 else
168 *mask = (1 << *bits_used) - 1;
169 if (signchar == 's')
170 *is_signed = 1;
171 else
172 *is_signed = 0;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000173 fclose(sysfsfp);
174 free(filename);
175
176 filename = 0;
Peter Meerwald578f7372012-06-25 23:13:24 +0200177 sysfsfp = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100178 }
Peter Meerwald578f7372012-06-25 23:13:24 +0200179error_close_sysfsfp:
180 if (sysfsfp)
181 fclose(sysfsfp);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100182error_free_filename:
183 if (filename)
184 free(filename);
185error_closedir:
186 closedir(dp);
187error_free_builtname_generic:
188 free(builtname_generic);
189error_free_builtname:
190 free(builtname);
191error_free_scan_el_dir:
192 free(scan_el_dir);
193error_ret:
194 return ret;
195}
196
197inline int iioutils_get_param_float(float *output,
198 const char *param_name,
199 const char *device_dir,
200 const char *name,
201 const char *generic_name)
202{
203 FILE *sysfsfp;
204 int ret;
205 DIR *dp;
206 char *builtname, *builtname_generic;
207 char *filename = NULL;
208 const struct dirent *ent;
209
210 ret = asprintf(&builtname, "%s_%s", name, param_name);
211 if (ret < 0) {
212 ret = -ENOMEM;
213 goto error_ret;
214 }
215 ret = asprintf(&builtname_generic,
216 "%s_%s", generic_name, param_name);
217 if (ret < 0) {
218 ret = -ENOMEM;
219 goto error_free_builtname;
220 }
221 dp = opendir(device_dir);
222 if (dp == NULL) {
223 ret = -errno;
224 goto error_free_builtname_generic;
225 }
226 while (ent = readdir(dp), ent != NULL)
227 if ((strcmp(builtname, ent->d_name) == 0) ||
228 (strcmp(builtname_generic, ent->d_name) == 0)) {
229 ret = asprintf(&filename,
230 "%s/%s", device_dir, ent->d_name);
231 if (ret < 0) {
232 ret = -ENOMEM;
233 goto error_closedir;
234 }
235 sysfsfp = fopen(filename, "r");
236 if (!sysfsfp) {
237 ret = -errno;
238 goto error_free_filename;
239 }
240 fscanf(sysfsfp, "%f", output);
241 break;
242 }
243error_free_filename:
244 if (filename)
245 free(filename);
246error_closedir:
247 closedir(dp);
248error_free_builtname_generic:
249 free(builtname_generic);
250error_free_builtname:
251 free(builtname);
252error_ret:
253 return ret;
254}
255
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100256/**
257 * bsort_channel_array_by_index() - reorder so that the array is in index order
258 *
259 **/
260
261inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
262 int cnt)
263{
264
265 struct iio_channel_info temp;
266 int x, y;
267
268 for (x = 0; x < cnt; x++)
269 for (y = 0; y < (cnt - 1); y++)
270 if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
271 temp = (*ci_array)[y + 1];
272 (*ci_array)[y + 1] = (*ci_array)[y];
273 (*ci_array)[y] = temp;
274 }
275}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100276
277/**
278 * build_channel_array() - function to figure out what channels are present
279 * @device_dir: the IIO device directory in sysfs
280 * @
281 **/
282inline int build_channel_array(const char *device_dir,
283 struct iio_channel_info **ci_array,
284 int *counter)
285{
286 DIR *dp;
287 FILE *sysfsfp;
Peter Meerwald10937922012-06-25 23:12:12 +0200288 int count, i;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100289 struct iio_channel_info *current;
290 int ret;
291 const struct dirent *ent;
292 char *scan_el_dir;
293 char *filename;
294
295 *counter = 0;
296 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
297 if (ret < 0) {
298 ret = -ENOMEM;
299 goto error_ret;
300 }
301 dp = opendir(scan_el_dir);
302 if (dp == NULL) {
303 ret = -errno;
304 goto error_free_name;
305 }
306 while (ent = readdir(dp), ent != NULL)
307 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
308 "_en") == 0) {
309 ret = asprintf(&filename,
310 "%s/%s", scan_el_dir, ent->d_name);
311 if (ret < 0) {
312 ret = -ENOMEM;
313 goto error_close_dir;
314 }
315 sysfsfp = fopen(filename, "r");
316 if (sysfsfp == NULL) {
317 ret = -errno;
318 free(filename);
319 goto error_close_dir;
320 }
321 fscanf(sysfsfp, "%u", &ret);
322 if (ret == 1)
323 (*counter)++;
324 fclose(sysfsfp);
325 free(filename);
326 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100327 *ci_array = malloc(sizeof(**ci_array) * (*counter));
Jonathan Camerone58537c2010-10-08 12:14:14 +0100328 if (*ci_array == NULL) {
329 ret = -ENOMEM;
330 goto error_close_dir;
331 }
332 seekdir(dp, 0);
Michael Hennerich7ccd4502011-02-24 16:34:53 +0100333 count = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100334 while (ent = readdir(dp), ent != NULL) {
335 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
336 "_en") == 0) {
Craig Markwardt66c65d92014-01-01 15:38:52 +0000337 int current_enabled = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100338 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 }
Craig Markwardt66c65d92014-01-01 15:38:52 +0000353 fscanf(sysfsfp, "%u", &current_enabled);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100354 fclose(sysfsfp);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100355
Craig Markwardt66c65d92014-01-01 15:38:52 +0000356 if (!current_enabled) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100357 free(filename);
358 count--;
359 continue;
360 }
361
Jonathan Camerone58537c2010-10-08 12:14:14 +0100362 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,
Jonathan Cameron52615d42011-05-18 14:41:19 +0100410 &current->shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100411 &current->mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000412 &current->be,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100413 device_dir,
414 current->name,
415 current->generic_name);
416 }
417 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100418
Jonathan Camerone58537c2010-10-08 12:14:14 +0100419 closedir(dp);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100420 /* reorder so that the array is in index order */
421 bsort_channel_array_by_index(ci_array, *counter);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100422
423 return 0;
424
425error_cleanup_array:
roel kluin267024a2011-01-01 18:01:51 +0000426 for (i = count - 1; i >= 0; i--)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100427 free((*ci_array)[i].name);
428 free(*ci_array);
429error_close_dir:
430 closedir(dp);
431error_free_name:
432 free(scan_el_dir);
433error_ret:
434 return ret;
435}
436
437/**
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100438 * find_type_by_name() - function to match top level types by name
439 * @name: top level type instance name
440 * @type: the type of top level instance being sort
441 *
442 * Typical types this is used for are device and trigger.
443 **/
444inline int find_type_by_name(const char *name, const char *type)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100445{
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100446 const struct dirent *ent;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100447 int number, numstrlen;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100448
449 FILE *nameFile;
450 DIR *dp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100451 char thisname[IIO_MAX_NAME_LENGTH];
452 char *filename;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100453
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100454 dp = opendir(iio_dir);
455 if (dp == NULL) {
Peter Meerwaldc866ffc2012-07-01 00:47:41 +0200456 printf("No industrialio devices available\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100457 return -ENODEV;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100458 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100459
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100460 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)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100474 + numstrlen
Barry Songb6ee30a2010-05-25 17:40:04 +0800475 + 6);
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200476 if (filename == NULL) {
477 closedir(dp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100478 return -ENOMEM;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200479 }
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100480 sprintf(filename, "%s%s%d/name",
481 iio_dir,
482 type,
483 number);
484 nameFile = fopen(filename, "r");
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200485 if (!nameFile) {
486 free(filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100487 continue;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200488 }
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100489 free(filename);
490 fscanf(nameFile, "%s", thisname);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100491 fclose(nameFile);
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200492 if (strcmp(name, thisname) == 0) {
493 closedir(dp);
494 return number;
495 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100496 }
497 }
498 }
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200499 closedir(dp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100500 return -ENODEV;
501}
502
503inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
504{
Sebastian Andrzej Siewior11cb4542013-10-07 13:42:00 +0100505 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100506 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);
Peter Meerwaldce7b04c2012-06-25 23:13:26 +0200528 fclose(sysfsfp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100529 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 }
537error_free:
538 free(temp);
539 return ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100540}
541
542int write_sysfs_int(char *filename, char *basedir, int val)
543{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100544 return _write_sysfs_int(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100545}
546
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100547int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
548{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100549 return _write_sysfs_int(filename, basedir, val, 1);
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100550}
551
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100552int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
553{
Jonathan Camerone58537c2010-10-08 12:14:14 +0100554 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100555 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) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100573 printf("could not open file to verify\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100574 ret = -errno;
575 goto error_free;
576 }
577 fscanf(sysfsfp, "%s", temp);
Peter Meerwaldce7b04c2012-06-25 23:13:26 +0200578 fclose(sysfsfp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100579 if (strcmp(temp, val) != 0) {
580 printf("Possible failure in string write of %s "
581 "Should be %s "
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300582 "written to %s\%s\n",
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100583 temp,
584 val,
585 basedir,
586 filename);
587 ret = -1;
588 }
589 }
590error_free:
591 free(temp);
592
593 return ret;
594}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100595
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100596/**
597 * write_sysfs_string_and_verify() - string write, readback and verify
598 * @filename: name of file to write to
599 * @basedir: the sysfs directory in which the file is to be found
600 * @val: the string to write
601 **/
602int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
603{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100604 return _write_sysfs_string(filename, basedir, val, 1);
605}
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100606
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100607int write_sysfs_string(char *filename, char *basedir, char *val)
608{
609 return _write_sysfs_string(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100610}
611
612int read_sysfs_posint(char *filename, char *basedir)
613{
614 int ret;
615 FILE *sysfsfp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100616 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);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100622 sysfsfp = fopen(temp, "r");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100623 if (sysfsfp == NULL) {
624 ret = -errno;
625 goto error_free;
626 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100627 fscanf(sysfsfp, "%d\n", &ret);
628 fclose(sysfsfp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100629error_free:
630 free(temp);
631 return ret;
632}
633
634int 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);
651error_free:
652 free(temp);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100653 return ret;
654}