blob: a95270f3335376ca46f494ba8190a9343e8bffea [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
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020032 *
33 * Returns 0 on success, or a negative error code if string extraction failed.
Jonathan Camerone58537c2010-10-08 12:14:14 +010034 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020035int iioutils_break_up_name(const char *full_name, char **generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +010036{
37 char *current;
38 char *w, *r;
Irina Tirdead9d7b992015-03-27 13:53:00 +020039 char *working, *prefix = "";
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020040 int i, ret;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +030041
Cristina Opriceana34cbea12015-07-13 16:20:11 +030042 for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
Irina Tirdead9d7b992015-03-27 13:53:00 +020043 if (!strncmp(full_name, iio_direction[i],
44 strlen(iio_direction[i]))) {
45 prefix = iio_direction[i];
46 break;
47 }
48
49 current = strdup(full_name + strlen(prefix) + 1);
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020050 if (!current)
51 return -ENOMEM;
52
Jonathan Camerone58537c2010-10-08 12:14:14 +010053 working = strtok(current, "_\0");
Hartmut Knaack53118552015-05-31 14:40:14 +020054 if (!working) {
55 free(current);
56 return -EINVAL;
57 }
Irina Tirdead9d7b992015-03-27 13:53:00 +020058
Jonathan Camerone58537c2010-10-08 12:14:14 +010059 w = working;
60 r = working;
61
Michael Hennerich8b68bb22011-03-08 08:55:48 +010062 while (*r != '\0') {
Jonathan Camerone58537c2010-10-08 12:14:14 +010063 if (!isdigit(*r)) {
64 *w = *r;
65 w++;
66 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020067
Jonathan Camerone58537c2010-10-08 12:14:14 +010068 r++;
69 }
70 *w = '\0';
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020071 ret = asprintf(generic_name, "%s_%s", prefix, working);
Jonathan Camerone58537c2010-10-08 12:14:14 +010072 free(current);
73
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020074 return (ret == -1) ? -ENOMEM : 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +010075}
76
77/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010078 * iioutils_get_type() - find and process _type attribute data
79 * @is_signed: output whether channel is signed
80 * @bytes: output how many bytes the channel storage occupies
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020081 * @bits_used: output number of valid bits of data
82 * @shift: output amount of bits to shift right data before applying bit mask
Jonathan Camerone58537c2010-10-08 12:14:14 +010083 * @mask: output a bit mask for the raw data
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020084 * @be: output if data in big endian
85 * @device_dir: the IIO device directory
Jonathan Camerone58537c2010-10-08 12:14:14 +010086 * @name: the channel name
87 * @generic_name: the channel type name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020088 *
89 * Returns a value >= 0 on success, otherwise a negative error code.
Jonathan Camerone58537c2010-10-08 12:14:14 +010090 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020091int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
92 unsigned *shift, uint64_t *mask, unsigned *be,
93 const char *device_dir, const char *name,
94 const char *generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +010095{
96 FILE *sysfsfp;
97 int ret;
98 DIR *dp;
99 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000100 char signchar, endianchar;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100101 unsigned padint;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100102 const struct dirent *ent;
103
104 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200105 if (ret < 0)
106 return -ENOMEM;
107
Jonathan Camerone58537c2010-10-08 12:14:14 +0100108 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);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300120 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100121 ret = -errno;
122 goto error_free_builtname_generic;
123 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200124
Hartmut Knaack53118552015-05-31 14:40:14 +0200125 ret = -ENOENT;
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300126 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100127 /*
128 * Do we allow devices to override a generic name with
129 * a specific one?
130 */
131 if ((strcmp(builtname, ent->d_name) == 0) ||
132 (strcmp(builtname_generic, ent->d_name) == 0)) {
133 ret = asprintf(&filename,
134 "%s/%s", scan_el_dir, ent->d_name);
135 if (ret < 0) {
136 ret = -ENOMEM;
137 goto error_closedir;
138 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200139
Jonathan Camerone58537c2010-10-08 12:14:14 +0100140 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300141 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100142 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300143 fprintf(stderr, "failed to open %s\n",
144 filename);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100145 goto error_free_filename;
146 }
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000147
148 ret = fscanf(sysfsfp,
149 "%ce:%c%u/%u>>%u",
150 &endianchar,
151 &signchar,
152 bits_used,
153 &padint, shift);
154 if (ret < 0) {
Peter Meerwald578f7372012-06-25 23:13:24 +0200155 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300156 fprintf(stderr,
157 "failed to pass scan type description\n");
Peter Meerwald578f7372012-06-25 23:13:24 +0200158 goto error_close_sysfsfp;
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200159 } else if (ret != 5) {
160 ret = -EIO;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300161 fprintf(stderr,
162 "scan type description didn't match\n");
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200163 goto error_close_sysfsfp;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000164 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200165
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000166 *be = (endianchar == 'b');
Jonathan Camerone58537c2010-10-08 12:14:14 +0100167 *bytes = padint / 8;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +0100168 if (*bits_used == 64)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100169 *mask = ~0;
170 else
Irina Tirdeaae067cb2015-07-24 16:28:05 +0300171 *mask = (1ULL << *bits_used) - 1;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200172
Hartmut Knaack33ebcb22015-05-31 14:40:19 +0200173 *is_signed = (signchar == 's');
Hartmut Knaack53118552015-05-31 14:40:14 +0200174 if (fclose(sysfsfp)) {
175 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300176 fprintf(stderr, "Failed to close %s\n",
177 filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200178 goto error_free_filename;
179 }
180
Hartmut Knaackace76e42015-05-31 14:40:20 +0200181 sysfsfp = 0;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000182 free(filename);
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000183 filename = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100184 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200185
Peter Meerwald578f7372012-06-25 23:13:24 +0200186error_close_sysfsfp:
187 if (sysfsfp)
Hartmut Knaack53118552015-05-31 14:40:14 +0200188 if (fclose(sysfsfp))
189 perror("iioutils_get_type(): Failed to close file");
190
Jonathan Camerone58537c2010-10-08 12:14:14 +0100191error_free_filename:
192 if (filename)
193 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200194
Jonathan Camerone58537c2010-10-08 12:14:14 +0100195error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200196 if (closedir(dp) == -1)
197 perror("iioutils_get_type(): Failed to close directory");
198
Jonathan Camerone58537c2010-10-08 12:14:14 +0100199error_free_builtname_generic:
200 free(builtname_generic);
201error_free_builtname:
202 free(builtname);
203error_free_scan_el_dir:
204 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200205
Jonathan Camerone58537c2010-10-08 12:14:14 +0100206 return ret;
207}
208
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200209/**
210 * iioutils_get_param_float() - read a float value from a channel parameter
211 * @output: output the float value
212 * @param_name: the parameter name to read
213 * @device_dir: the IIO device directory in sysfs
214 * @name: the channel name
215 * @generic_name: the channel type name
216 *
217 * Returns a value >= 0 on success, otherwise a negative error code.
218 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200219int iioutils_get_param_float(float *output, const char *param_name,
220 const char *device_dir, const char *name,
221 const char *generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100222{
223 FILE *sysfsfp;
224 int ret;
225 DIR *dp;
226 char *builtname, *builtname_generic;
227 char *filename = NULL;
228 const struct dirent *ent;
229
230 ret = asprintf(&builtname, "%s_%s", name, param_name);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200231 if (ret < 0)
232 return -ENOMEM;
233
Jonathan Camerone58537c2010-10-08 12:14:14 +0100234 ret = asprintf(&builtname_generic,
235 "%s_%s", generic_name, param_name);
236 if (ret < 0) {
237 ret = -ENOMEM;
238 goto error_free_builtname;
239 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200240
Jonathan Camerone58537c2010-10-08 12:14:14 +0100241 dp = opendir(device_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300242 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100243 ret = -errno;
244 goto error_free_builtname_generic;
245 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200246
Hartmut Knaack53118552015-05-31 14:40:14 +0200247 ret = -ENOENT;
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300248 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100249 if ((strcmp(builtname, ent->d_name) == 0) ||
250 (strcmp(builtname_generic, ent->d_name) == 0)) {
251 ret = asprintf(&filename,
252 "%s/%s", device_dir, ent->d_name);
253 if (ret < 0) {
254 ret = -ENOMEM;
255 goto error_closedir;
256 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200257
Jonathan Camerone58537c2010-10-08 12:14:14 +0100258 sysfsfp = fopen(filename, "r");
259 if (!sysfsfp) {
260 ret = -errno;
261 goto error_free_filename;
262 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200263
Hartmut Knaack53118552015-05-31 14:40:14 +0200264 errno = 0;
265 if (fscanf(sysfsfp, "%f", output) != 1)
266 ret = errno ? -errno : -ENODATA;
267
Jonathan Camerone58537c2010-10-08 12:14:14 +0100268 break;
269 }
270error_free_filename:
271 if (filename)
272 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200273
Jonathan Camerone58537c2010-10-08 12:14:14 +0100274error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200275 if (closedir(dp) == -1)
276 perror("iioutils_get_param_float(): Failed to close directory");
277
Jonathan Camerone58537c2010-10-08 12:14:14 +0100278error_free_builtname_generic:
279 free(builtname_generic);
280error_free_builtname:
281 free(builtname);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200282
Jonathan Camerone58537c2010-10-08 12:14:14 +0100283 return ret;
284}
285
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100286/**
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200287 * bsort_channel_array_by_index() - sort the array in index order
288 * @ci_array: the iio_channel_info array to be sorted
289 * @cnt: the amount of array elements
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100290 **/
291
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200292void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt)
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100293{
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100294 struct iio_channel_info temp;
295 int x, y;
296
297 for (x = 0; x < cnt; x++)
298 for (y = 0; y < (cnt - 1); y++)
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200299 if ((*ci_array)[y].index > (*ci_array)[y + 1].index) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100300 temp = (*ci_array)[y + 1];
301 (*ci_array)[y + 1] = (*ci_array)[y];
302 (*ci_array)[y] = temp;
303 }
304}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100305
306/**
307 * build_channel_array() - function to figure out what channels are present
308 * @device_dir: the IIO device directory in sysfs
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200309 * @ci_array: output the resulting array of iio_channel_info
310 * @counter: output the amount of array elements
311 *
312 * Returns 0 on success, otherwise a negative error code.
Jonathan Camerone58537c2010-10-08 12:14:14 +0100313 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200314int build_channel_array(const char *device_dir,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200315 struct iio_channel_info **ci_array, int *counter)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100316{
317 DIR *dp;
318 FILE *sysfsfp;
Hartmut Knaack1e7c3472015-05-31 14:40:21 +0200319 int count = 0, i;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100320 struct iio_channel_info *current;
321 int ret;
322 const struct dirent *ent;
323 char *scan_el_dir;
324 char *filename;
325
326 *counter = 0;
327 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200328 if (ret < 0)
329 return -ENOMEM;
330
Jonathan Camerone58537c2010-10-08 12:14:14 +0100331 dp = opendir(scan_el_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300332 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100333 ret = -errno;
334 goto error_free_name;
335 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200336
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300337 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100338 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
339 "_en") == 0) {
340 ret = asprintf(&filename,
341 "%s/%s", scan_el_dir, ent->d_name);
342 if (ret < 0) {
343 ret = -ENOMEM;
344 goto error_close_dir;
345 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200346
Jonathan Camerone58537c2010-10-08 12:14:14 +0100347 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300348 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100349 ret = -errno;
350 free(filename);
351 goto error_close_dir;
352 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200353
Hartmut Knaack53118552015-05-31 14:40:14 +0200354 errno = 0;
355 if (fscanf(sysfsfp, "%i", &ret) != 1) {
356 ret = errno ? -errno : -ENODATA;
357 if (fclose(sysfsfp))
358 perror("build_channel_array(): Failed to close file");
359
360 free(filename);
361 goto error_close_dir;
362 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100363 if (ret == 1)
364 (*counter)++;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200365
Hartmut Knaack53118552015-05-31 14:40:14 +0200366 if (fclose(sysfsfp)) {
367 ret = -errno;
368 free(filename);
369 goto error_close_dir;
370 }
371
Jonathan Camerone58537c2010-10-08 12:14:14 +0100372 free(filename);
373 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200374
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100375 *ci_array = malloc(sizeof(**ci_array) * (*counter));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300376 if (!*ci_array) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100377 ret = -ENOMEM;
378 goto error_close_dir;
379 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200380
Jonathan Camerone58537c2010-10-08 12:14:14 +0100381 seekdir(dp, 0);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300382 while (ent = readdir(dp), ent) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100383 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
384 "_en") == 0) {
Craig Markwardt66c65d92014-01-01 15:38:52 +0000385 int current_enabled = 0;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300386
Jonathan Camerone58537c2010-10-08 12:14:14 +0100387 current = &(*ci_array)[count++];
388 ret = asprintf(&filename,
389 "%s/%s", scan_el_dir, ent->d_name);
390 if (ret < 0) {
391 ret = -ENOMEM;
392 /* decrement count to avoid freeing name */
393 count--;
394 goto error_cleanup_array;
395 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200396
Jonathan Camerone58537c2010-10-08 12:14:14 +0100397 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300398 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100399 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200400 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200401 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100402 goto error_cleanup_array;
403 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200404
Hartmut Knaack53118552015-05-31 14:40:14 +0200405 errno = 0;
406 if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
407 ret = errno ? -errno : -ENODATA;
408 free(filename);
409 count--;
410 goto error_cleanup_array;
411 }
412
413 if (fclose(sysfsfp)) {
414 ret = -errno;
415 free(filename);
416 count--;
417 goto error_cleanup_array;
418 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100419
Craig Markwardt66c65d92014-01-01 15:38:52 +0000420 if (!current_enabled) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100421 free(filename);
422 count--;
423 continue;
424 }
425
Jonathan Camerone58537c2010-10-08 12:14:14 +0100426 current->scale = 1.0;
427 current->offset = 0;
428 current->name = strndup(ent->d_name,
429 strlen(ent->d_name) -
430 strlen("_en"));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300431 if (!current->name) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100432 free(filename);
433 ret = -ENOMEM;
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200434 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100435 goto error_cleanup_array;
436 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200437
Jonathan Camerone58537c2010-10-08 12:14:14 +0100438 /* Get the generic and specific name elements */
439 ret = iioutils_break_up_name(current->name,
440 &current->generic_name);
441 if (ret) {
442 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200443 free(current->name);
444 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100445 goto error_cleanup_array;
446 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200447
Jonathan Camerone58537c2010-10-08 12:14:14 +0100448 ret = asprintf(&filename,
449 "%s/%s_index",
450 scan_el_dir,
451 current->name);
452 if (ret < 0) {
453 free(filename);
454 ret = -ENOMEM;
455 goto error_cleanup_array;
456 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200457
Jonathan Camerone58537c2010-10-08 12:14:14 +0100458 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300459 if (!sysfsfp) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200460 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300461 fprintf(stderr, "failed to open %s\n",
462 filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200463 free(filename);
464 goto error_cleanup_array;
465 }
466
467 errno = 0;
468 if (fscanf(sysfsfp, "%u", &current->index) != 1) {
469 ret = errno ? -errno : -ENODATA;
470 if (fclose(sysfsfp))
471 perror("build_channel_array(): Failed to close file");
472
473 free(filename);
474 goto error_cleanup_array;
475 }
476
477 if (fclose(sysfsfp)) {
478 ret = -errno;
479 free(filename);
480 goto error_cleanup_array;
481 }
482
Jonathan Camerone58537c2010-10-08 12:14:14 +0100483 free(filename);
484 /* Find the scale */
485 ret = iioutils_get_param_float(&current->scale,
486 "scale",
487 device_dir,
488 current->name,
489 current->generic_name);
Joo Aun Saw7868dfd2015-07-23 12:53:47 +1000490 if ((ret < 0) && (ret != -ENOENT))
Jonathan Camerone58537c2010-10-08 12:14:14 +0100491 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200492
Jonathan Camerone58537c2010-10-08 12:14:14 +0100493 ret = iioutils_get_param_float(&current->offset,
494 "offset",
495 device_dir,
496 current->name,
497 current->generic_name);
Joo Aun Saw7868dfd2015-07-23 12:53:47 +1000498 if ((ret < 0) && (ret != -ENOENT))
Jonathan Camerone58537c2010-10-08 12:14:14 +0100499 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200500
Jonathan Camerone58537c2010-10-08 12:14:14 +0100501 ret = iioutils_get_type(&current->is_signed,
502 &current->bytes,
503 &current->bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +0100504 &current->shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100505 &current->mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000506 &current->be,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100507 device_dir,
508 current->name,
509 current->generic_name);
Hartmut Knaack53118552015-05-31 14:40:14 +0200510 if (ret < 0)
511 goto error_cleanup_array;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100512 }
513 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100514
Hartmut Knaack53118552015-05-31 14:40:14 +0200515 if (closedir(dp) == -1) {
516 ret = -errno;
517 goto error_cleanup_array;
518 }
519
Hartmut Knaack66dd08f2015-05-31 14:39:43 +0200520 free(scan_el_dir);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100521 /* reorder so that the array is in index order */
522 bsort_channel_array_by_index(ci_array, *counter);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100523
524 return 0;
525
526error_cleanup_array:
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200527 for (i = count - 1; i >= 0; i--) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100528 free((*ci_array)[i].name);
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200529 free((*ci_array)[i].generic_name);
530 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100531 free(*ci_array);
532error_close_dir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200533 if (dp)
534 if (closedir(dp) == -1)
535 perror("build_channel_array(): Failed to close dir");
536
Jonathan Camerone58537c2010-10-08 12:14:14 +0100537error_free_name:
538 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200539
Jonathan Camerone58537c2010-10-08 12:14:14 +0100540 return ret;
541}
542
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200543int calc_digits(int num)
544{
545 int count = 0;
546
547 while (num != 0) {
548 num /= 10;
549 count++;
550 }
551
552 return count;
553}
554
Jonathan Camerone58537c2010-10-08 12:14:14 +0100555/**
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100556 * find_type_by_name() - function to match top level types by name
557 * @name: top level type instance name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200558 * @type: the type of top level instance being searched
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100559 *
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200560 * Returns the device number of a matched IIO device on success, otherwise a
561 * negative error code.
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100562 * Typical types this is used for are device and trigger.
563 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200564int find_type_by_name(const char *name, const char *type)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100565{
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100566 const struct dirent *ent;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200567 int number, numstrlen, ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100568
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200569 FILE *namefp;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100570 DIR *dp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100571 char thisname[IIO_MAX_NAME_LENGTH];
572 char *filename;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100573
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100574 dp = opendir(iio_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300575 if (!dp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300576 fprintf(stderr, "No industrialio devices available\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100577 return -ENODEV;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100578 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100579
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300580 while (ent = readdir(dp), ent) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100581 if (strcmp(ent->d_name, ".") != 0 &&
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200582 strcmp(ent->d_name, "..") != 0 &&
583 strlen(ent->d_name) > strlen(type) &&
584 strncmp(ent->d_name, type, strlen(type)) == 0) {
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200585 errno = 0;
586 ret = sscanf(ent->d_name + strlen(type), "%d", &number);
587 if (ret < 0) {
588 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300589 fprintf(stderr,
590 "failed to read element number\n");
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200591 goto error_close_dir;
592 } else if (ret != 1) {
593 ret = -EIO;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300594 fprintf(stderr,
595 "failed to match element number\n");
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200596 goto error_close_dir;
597 }
598
599 numstrlen = calc_digits(number);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100600 /* verify the next character is not a colon */
601 if (strncmp(ent->d_name + strlen(type) + numstrlen,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200602 ":", 1) != 0) {
603 filename = malloc(strlen(iio_dir) + strlen(type)
604 + numstrlen + 6);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300605 if (!filename) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200606 ret = -ENOMEM;
607 goto error_close_dir;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200608 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200609
610 ret = sprintf(filename, "%s%s%d/name", iio_dir,
611 type, number);
612 if (ret < 0) {
613 free(filename);
614 goto error_close_dir;
615 }
616
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200617 namefp = fopen(filename, "r");
618 if (!namefp) {
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200619 free(filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100620 continue;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200621 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200622
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100623 free(filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200624 errno = 0;
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200625 if (fscanf(namefp, "%s", thisname) != 1) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200626 ret = errno ? -errno : -ENODATA;
627 goto error_close_dir;
628 }
629
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200630 if (fclose(namefp)) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200631 ret = -errno;
632 goto error_close_dir;
633 }
634
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200635 if (strcmp(name, thisname) == 0) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200636 if (closedir(dp) == -1)
637 return -errno;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200638
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200639 return number;
640 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100641 }
642 }
643 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200644 if (closedir(dp) == -1)
645 return -errno;
646
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100647 return -ENODEV;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200648
649error_close_dir:
650 if (closedir(dp) == -1)
651 perror("find_type_by_name(): Failed to close directory");
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200652
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200653 return ret;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100654}
655
Hartmut Knaack9d475252015-05-31 14:40:36 +0200656static int _write_sysfs_int(const char *filename, const char *basedir, int val,
657 int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100658{
Sebastian Andrzej Siewior11cb4542013-10-07 13:42:00 +0100659 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100660 FILE *sysfsfp;
661 int test;
662 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300663
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300664 if (!temp)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100665 return -ENOMEM;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200666
Hartmut Knaack53118552015-05-31 14:40:14 +0200667 ret = sprintf(temp, "%s/%s", basedir, filename);
668 if (ret < 0)
669 goto error_free;
670
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100671 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300672 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100673 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300674 fprintf(stderr, "failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100675 goto error_free;
676 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200677
Hartmut Knaack53118552015-05-31 14:40:14 +0200678 ret = fprintf(sysfsfp, "%d", val);
679 if (ret < 0) {
680 if (fclose(sysfsfp))
681 perror("_write_sysfs_int(): Failed to close dir");
682
683 goto error_free;
684 }
685
686 if (fclose(sysfsfp)) {
687 ret = -errno;
688 goto error_free;
689 }
690
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100691 if (verify) {
692 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300693 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100694 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300695 fprintf(stderr, "failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100696 goto error_free;
697 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200698
Hartmut Knaack53118552015-05-31 14:40:14 +0200699 if (fscanf(sysfsfp, "%d", &test) != 1) {
700 ret = errno ? -errno : -ENODATA;
701 if (fclose(sysfsfp))
702 perror("_write_sysfs_int(): Failed to close dir");
703
704 goto error_free;
705 }
706
707 if (fclose(sysfsfp)) {
708 ret = -errno;
709 goto error_free;
710 }
711
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100712 if (test != val) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300713 fprintf(stderr,
714 "Possible failure in int write %d to %s/%s\n",
715 val, basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100716 ret = -1;
717 }
718 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200719
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100720error_free:
721 free(temp);
722 return ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100723}
724
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200725/**
726 * write_sysfs_int() - write an integer value to a sysfs file
727 * @filename: name of the file to write to
728 * @basedir: the sysfs directory in which the file is to be found
729 * @val: integer value to write to file
730 *
731 * Returns a value >= 0 on success, otherwise a negative error code.
732 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200733int write_sysfs_int(const char *filename, const char *basedir, int val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100734{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100735 return _write_sysfs_int(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100736}
737
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200738/**
739 * write_sysfs_int_and_verify() - write an integer value to a sysfs file
740 * and verify
741 * @filename: name of the file to write to
742 * @basedir: the sysfs directory in which the file is to be found
743 * @val: integer value to write to file
744 *
745 * Returns a value >= 0 on success, otherwise a negative error code.
746 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200747int write_sysfs_int_and_verify(const char *filename, const char *basedir,
748 int val)
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100749{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100750 return _write_sysfs_int(filename, basedir, val, 1);
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100751}
752
Hartmut Knaack9d475252015-05-31 14:40:36 +0200753static int _write_sysfs_string(const char *filename, const char *basedir,
754 const char *val, int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100755{
Jonathan Camerone58537c2010-10-08 12:14:14 +0100756 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100757 FILE *sysfsfp;
758 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300759
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300760 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300761 fprintf(stderr, "Memory allocation failed\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100762 return -ENOMEM;
763 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200764
Hartmut Knaack53118552015-05-31 14:40:14 +0200765 ret = sprintf(temp, "%s/%s", basedir, filename);
766 if (ret < 0)
767 goto error_free;
768
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100769 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300770 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100771 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300772 fprintf(stderr, "Could not open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100773 goto error_free;
774 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200775
Hartmut Knaack53118552015-05-31 14:40:14 +0200776 ret = fprintf(sysfsfp, "%s", val);
777 if (ret < 0) {
778 if (fclose(sysfsfp))
779 perror("_write_sysfs_string(): Failed to close dir");
780
781 goto error_free;
782 }
783
784 if (fclose(sysfsfp)) {
785 ret = -errno;
786 goto error_free;
787 }
788
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100789 if (verify) {
790 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300791 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100792 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300793 fprintf(stderr, "Could not open file to verify\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100794 goto error_free;
795 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200796
Hartmut Knaack53118552015-05-31 14:40:14 +0200797 if (fscanf(sysfsfp, "%s", temp) != 1) {
798 ret = errno ? -errno : -ENODATA;
799 if (fclose(sysfsfp))
800 perror("_write_sysfs_string(): Failed to close dir");
801
802 goto error_free;
803 }
804
805 if (fclose(sysfsfp)) {
806 ret = -errno;
807 goto error_free;
808 }
809
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100810 if (strcmp(temp, val) != 0) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300811 fprintf(stderr,
812 "Possible failure in string write of %s "
813 "Should be %s written to %s/%s\n", temp, val,
814 basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100815 ret = -1;
816 }
817 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200818
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100819error_free:
820 free(temp);
821
822 return ret;
823}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100824
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100825/**
826 * write_sysfs_string_and_verify() - string write, readback and verify
827 * @filename: name of file to write to
828 * @basedir: the sysfs directory in which the file is to be found
829 * @val: the string to write
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200830 *
831 * Returns a value >= 0 on success, otherwise a negative error code.
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100832 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200833int write_sysfs_string_and_verify(const char *filename, const char *basedir,
834 const char *val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100835{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100836 return _write_sysfs_string(filename, basedir, val, 1);
837}
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100838
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200839/**
840 * write_sysfs_string() - write string to a sysfs file
841 * @filename: name of file to write to
842 * @basedir: the sysfs directory in which the file is to be found
843 * @val: the string to write
844 *
845 * Returns a value >= 0 on success, otherwise a negative error code.
846 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200847int write_sysfs_string(const char *filename, const char *basedir,
848 const char *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100849{
850 return _write_sysfs_string(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100851}
852
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200853/**
854 * read_sysfs_posint() - read an integer value from file
855 * @filename: name of file to read from
856 * @basedir: the sysfs directory in which the file is to be found
857 *
858 * Returns the read integer value >= 0 on success, otherwise a negative error
859 * code.
860 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200861int read_sysfs_posint(const char *filename, const char *basedir)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100862{
863 int ret;
864 FILE *sysfsfp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100865 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300866
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300867 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300868 fprintf(stderr, "Memory allocation failed");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100869 return -ENOMEM;
870 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200871
Hartmut Knaack53118552015-05-31 14:40:14 +0200872 ret = sprintf(temp, "%s/%s", basedir, filename);
873 if (ret < 0)
874 goto error_free;
875
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100876 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300877 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100878 ret = -errno;
879 goto error_free;
880 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200881
Hartmut Knaack53118552015-05-31 14:40:14 +0200882 errno = 0;
883 if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
884 ret = errno ? -errno : -ENODATA;
885 if (fclose(sysfsfp))
886 perror("read_sysfs_posint(): Failed to close dir");
887
888 goto error_free;
889 }
890
891 if (fclose(sysfsfp))
892 ret = -errno;
893
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100894error_free:
895 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200896
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100897 return ret;
898}
899
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200900/**
901 * read_sysfs_float() - read a float value from file
902 * @filename: name of file to read from
903 * @basedir: the sysfs directory in which the file is to be found
904 * @val: output the read float value
905 *
906 * Returns a value >= 0 on success, otherwise a negative error code.
907 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200908int read_sysfs_float(const char *filename, const char *basedir, float *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100909{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000910 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100911 FILE *sysfsfp;
912 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300913
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300914 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300915 fprintf(stderr, "Memory allocation failed");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100916 return -ENOMEM;
917 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200918
Hartmut Knaack53118552015-05-31 14:40:14 +0200919 ret = sprintf(temp, "%s/%s", basedir, filename);
920 if (ret < 0)
921 goto error_free;
922
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100923 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300924 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100925 ret = -errno;
926 goto error_free;
927 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200928
Hartmut Knaack53118552015-05-31 14:40:14 +0200929 errno = 0;
930 if (fscanf(sysfsfp, "%f\n", val) != 1) {
931 ret = errno ? -errno : -ENODATA;
932 if (fclose(sysfsfp))
933 perror("read_sysfs_float(): Failed to close dir");
934
935 goto error_free;
936 }
937
938 if (fclose(sysfsfp))
939 ret = -errno;
940
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100941error_free:
942 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200943
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100944 return ret;
945}
Manuel Stahl49d916e2014-05-02 13:23:00 +0100946
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200947/**
948 * read_sysfs_string() - read a string from file
949 * @filename: name of file to read from
950 * @basedir: the sysfs directory in which the file is to be found
951 * @str: output the read string
952 *
953 * Returns a value >= 0 on success, otherwise a negative error code.
954 **/
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000955int read_sysfs_string(const char *filename, const char *basedir, char *str)
Manuel Stahl49d916e2014-05-02 13:23:00 +0100956{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000957 int ret = 0;
Manuel Stahl49d916e2014-05-02 13:23:00 +0100958 FILE *sysfsfp;
959 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300960
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300961 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300962 fprintf(stderr, "Memory allocation failed");
Manuel Stahl49d916e2014-05-02 13:23:00 +0100963 return -ENOMEM;
964 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200965
Hartmut Knaack53118552015-05-31 14:40:14 +0200966 ret = sprintf(temp, "%s/%s", basedir, filename);
967 if (ret < 0)
968 goto error_free;
969
Manuel Stahl49d916e2014-05-02 13:23:00 +0100970 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300971 if (!sysfsfp) {
Manuel Stahl49d916e2014-05-02 13:23:00 +0100972 ret = -errno;
973 goto error_free;
974 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200975
Hartmut Knaack53118552015-05-31 14:40:14 +0200976 errno = 0;
977 if (fscanf(sysfsfp, "%s\n", str) != 1) {
978 ret = errno ? -errno : -ENODATA;
979 if (fclose(sysfsfp))
980 perror("read_sysfs_string(): Failed to close dir");
981
982 goto error_free;
983 }
984
985 if (fclose(sysfsfp))
986 ret = -errno;
987
Manuel Stahl49d916e2014-05-02 13:23:00 +0100988error_free:
989 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200990
Manuel Stahl49d916e2014-05-02 13:23:00 +0100991 return ret;
992}
Cristina Opriceana37e3be92015-03-04 02:37:15 +0200993
994#endif /* _IIO_UTILS_H */