blob: e177f4022d400f59af67eb3ac35c24b920fb3d4a [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;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200143 printf("failed to open %s\n", filename);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100144 goto error_free_filename;
145 }
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000146
147 ret = fscanf(sysfsfp,
148 "%ce:%c%u/%u>>%u",
149 &endianchar,
150 &signchar,
151 bits_used,
152 &padint, shift);
153 if (ret < 0) {
Peter Meerwald578f7372012-06-25 23:13:24 +0200154 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200155 printf("failed to pass scan type description\n");
Peter Meerwald578f7372012-06-25 23:13:24 +0200156 goto error_close_sysfsfp;
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200157 } else if (ret != 5) {
158 ret = -EIO;
159 printf("scan type description didn't match\n");
160 goto error_close_sysfsfp;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000161 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200162
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;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200169
Hartmut Knaack33ebcb22015-05-31 14:40:19 +0200170 *is_signed = (signchar == 's');
Hartmut Knaack53118552015-05-31 14:40:14 +0200171 if (fclose(sysfsfp)) {
172 ret = -errno;
173 printf("Failed to close %s\n", filename);
174 goto error_free_filename;
175 }
176
Hartmut Knaackace76e42015-05-31 14:40:20 +0200177 sysfsfp = 0;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000178 free(filename);
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000179 filename = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100180 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200181
Peter Meerwald578f7372012-06-25 23:13:24 +0200182error_close_sysfsfp:
183 if (sysfsfp)
Hartmut Knaack53118552015-05-31 14:40:14 +0200184 if (fclose(sysfsfp))
185 perror("iioutils_get_type(): Failed to close file");
186
Jonathan Camerone58537c2010-10-08 12:14:14 +0100187error_free_filename:
188 if (filename)
189 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200190
Jonathan Camerone58537c2010-10-08 12:14:14 +0100191error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200192 if (closedir(dp) == -1)
193 perror("iioutils_get_type(): Failed to close directory");
194
Jonathan Camerone58537c2010-10-08 12:14:14 +0100195error_free_builtname_generic:
196 free(builtname_generic);
197error_free_builtname:
198 free(builtname);
199error_free_scan_el_dir:
200 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200201
Jonathan Camerone58537c2010-10-08 12:14:14 +0100202 return ret;
203}
204
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200205/**
206 * iioutils_get_param_float() - read a float value from a channel parameter
207 * @output: output the float value
208 * @param_name: the parameter name to read
209 * @device_dir: the IIO device directory in sysfs
210 * @name: the channel name
211 * @generic_name: the channel type name
212 *
213 * Returns a value >= 0 on success, otherwise a negative error code.
214 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200215int iioutils_get_param_float(float *output, const char *param_name,
216 const char *device_dir, const char *name,
217 const char *generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100218{
219 FILE *sysfsfp;
220 int ret;
221 DIR *dp;
222 char *builtname, *builtname_generic;
223 char *filename = NULL;
224 const struct dirent *ent;
225
226 ret = asprintf(&builtname, "%s_%s", name, param_name);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200227 if (ret < 0)
228 return -ENOMEM;
229
Jonathan Camerone58537c2010-10-08 12:14:14 +0100230 ret = asprintf(&builtname_generic,
231 "%s_%s", generic_name, param_name);
232 if (ret < 0) {
233 ret = -ENOMEM;
234 goto error_free_builtname;
235 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200236
Jonathan Camerone58537c2010-10-08 12:14:14 +0100237 dp = opendir(device_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300238 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100239 ret = -errno;
240 goto error_free_builtname_generic;
241 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200242
Hartmut Knaack53118552015-05-31 14:40:14 +0200243 ret = -ENOENT;
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300244 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100245 if ((strcmp(builtname, ent->d_name) == 0) ||
246 (strcmp(builtname_generic, ent->d_name) == 0)) {
247 ret = asprintf(&filename,
248 "%s/%s", device_dir, ent->d_name);
249 if (ret < 0) {
250 ret = -ENOMEM;
251 goto error_closedir;
252 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200253
Jonathan Camerone58537c2010-10-08 12:14:14 +0100254 sysfsfp = fopen(filename, "r");
255 if (!sysfsfp) {
256 ret = -errno;
257 goto error_free_filename;
258 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200259
Hartmut Knaack53118552015-05-31 14:40:14 +0200260 errno = 0;
261 if (fscanf(sysfsfp, "%f", output) != 1)
262 ret = errno ? -errno : -ENODATA;
263
Jonathan Camerone58537c2010-10-08 12:14:14 +0100264 break;
265 }
266error_free_filename:
267 if (filename)
268 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200269
Jonathan Camerone58537c2010-10-08 12:14:14 +0100270error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200271 if (closedir(dp) == -1)
272 perror("iioutils_get_param_float(): Failed to close directory");
273
Jonathan Camerone58537c2010-10-08 12:14:14 +0100274error_free_builtname_generic:
275 free(builtname_generic);
276error_free_builtname:
277 free(builtname);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200278
Jonathan Camerone58537c2010-10-08 12:14:14 +0100279 return ret;
280}
281
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100282/**
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200283 * bsort_channel_array_by_index() - sort the array in index order
284 * @ci_array: the iio_channel_info array to be sorted
285 * @cnt: the amount of array elements
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100286 **/
287
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200288void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt)
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100289{
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100290 struct iio_channel_info temp;
291 int x, y;
292
293 for (x = 0; x < cnt; x++)
294 for (y = 0; y < (cnt - 1); y++)
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200295 if ((*ci_array)[y].index > (*ci_array)[y + 1].index) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100296 temp = (*ci_array)[y + 1];
297 (*ci_array)[y + 1] = (*ci_array)[y];
298 (*ci_array)[y] = temp;
299 }
300}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100301
302/**
303 * build_channel_array() - function to figure out what channels are present
304 * @device_dir: the IIO device directory in sysfs
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200305 * @ci_array: output the resulting array of iio_channel_info
306 * @counter: output the amount of array elements
307 *
308 * Returns 0 on success, otherwise a negative error code.
Jonathan Camerone58537c2010-10-08 12:14:14 +0100309 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200310int build_channel_array(const char *device_dir,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200311 struct iio_channel_info **ci_array, int *counter)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100312{
313 DIR *dp;
314 FILE *sysfsfp;
Hartmut Knaack1e7c3472015-05-31 14:40:21 +0200315 int count = 0, i;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100316 struct iio_channel_info *current;
317 int ret;
318 const struct dirent *ent;
319 char *scan_el_dir;
320 char *filename;
321
322 *counter = 0;
323 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200324 if (ret < 0)
325 return -ENOMEM;
326
Jonathan Camerone58537c2010-10-08 12:14:14 +0100327 dp = opendir(scan_el_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300328 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100329 ret = -errno;
330 goto error_free_name;
331 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200332
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300333 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100334 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
335 "_en") == 0) {
336 ret = asprintf(&filename,
337 "%s/%s", scan_el_dir, ent->d_name);
338 if (ret < 0) {
339 ret = -ENOMEM;
340 goto error_close_dir;
341 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200342
Jonathan Camerone58537c2010-10-08 12:14:14 +0100343 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300344 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100345 ret = -errno;
346 free(filename);
347 goto error_close_dir;
348 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200349
Hartmut Knaack53118552015-05-31 14:40:14 +0200350 errno = 0;
351 if (fscanf(sysfsfp, "%i", &ret) != 1) {
352 ret = errno ? -errno : -ENODATA;
353 if (fclose(sysfsfp))
354 perror("build_channel_array(): Failed to close file");
355
356 free(filename);
357 goto error_close_dir;
358 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100359 if (ret == 1)
360 (*counter)++;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200361
Hartmut Knaack53118552015-05-31 14:40:14 +0200362 if (fclose(sysfsfp)) {
363 ret = -errno;
364 free(filename);
365 goto error_close_dir;
366 }
367
Jonathan Camerone58537c2010-10-08 12:14:14 +0100368 free(filename);
369 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200370
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100371 *ci_array = malloc(sizeof(**ci_array) * (*counter));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300372 if (!*ci_array) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100373 ret = -ENOMEM;
374 goto error_close_dir;
375 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200376
Jonathan Camerone58537c2010-10-08 12:14:14 +0100377 seekdir(dp, 0);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300378 while (ent = readdir(dp), ent) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100379 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
380 "_en") == 0) {
Craig Markwardt66c65d92014-01-01 15:38:52 +0000381 int current_enabled = 0;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300382
Jonathan Camerone58537c2010-10-08 12:14:14 +0100383 current = &(*ci_array)[count++];
384 ret = asprintf(&filename,
385 "%s/%s", scan_el_dir, ent->d_name);
386 if (ret < 0) {
387 ret = -ENOMEM;
388 /* decrement count to avoid freeing name */
389 count--;
390 goto error_cleanup_array;
391 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200392
Jonathan Camerone58537c2010-10-08 12:14:14 +0100393 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300394 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100395 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200396 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200397 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100398 goto error_cleanup_array;
399 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200400
Hartmut Knaack53118552015-05-31 14:40:14 +0200401 errno = 0;
402 if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
403 ret = errno ? -errno : -ENODATA;
404 free(filename);
405 count--;
406 goto error_cleanup_array;
407 }
408
409 if (fclose(sysfsfp)) {
410 ret = -errno;
411 free(filename);
412 count--;
413 goto error_cleanup_array;
414 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100415
Craig Markwardt66c65d92014-01-01 15:38:52 +0000416 if (!current_enabled) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100417 free(filename);
418 count--;
419 continue;
420 }
421
Jonathan Camerone58537c2010-10-08 12:14:14 +0100422 current->scale = 1.0;
423 current->offset = 0;
424 current->name = strndup(ent->d_name,
425 strlen(ent->d_name) -
426 strlen("_en"));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300427 if (!current->name) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100428 free(filename);
429 ret = -ENOMEM;
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200430 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100431 goto error_cleanup_array;
432 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200433
Jonathan Camerone58537c2010-10-08 12:14:14 +0100434 /* Get the generic and specific name elements */
435 ret = iioutils_break_up_name(current->name,
436 &current->generic_name);
437 if (ret) {
438 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200439 free(current->name);
440 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100441 goto error_cleanup_array;
442 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200443
Jonathan Camerone58537c2010-10-08 12:14:14 +0100444 ret = asprintf(&filename,
445 "%s/%s_index",
446 scan_el_dir,
447 current->name);
448 if (ret < 0) {
449 free(filename);
450 ret = -ENOMEM;
451 goto error_cleanup_array;
452 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200453
Jonathan Camerone58537c2010-10-08 12:14:14 +0100454 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300455 if (!sysfsfp) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200456 ret = -errno;
457 printf("failed to open %s\n", filename);
458 free(filename);
459 goto error_cleanup_array;
460 }
461
462 errno = 0;
463 if (fscanf(sysfsfp, "%u", &current->index) != 1) {
464 ret = errno ? -errno : -ENODATA;
465 if (fclose(sysfsfp))
466 perror("build_channel_array(): Failed to close file");
467
468 free(filename);
469 goto error_cleanup_array;
470 }
471
472 if (fclose(sysfsfp)) {
473 ret = -errno;
474 free(filename);
475 goto error_cleanup_array;
476 }
477
Jonathan Camerone58537c2010-10-08 12:14:14 +0100478 free(filename);
479 /* Find the scale */
480 ret = iioutils_get_param_float(&current->scale,
481 "scale",
482 device_dir,
483 current->name,
484 current->generic_name);
485 if (ret < 0)
486 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200487
Jonathan Camerone58537c2010-10-08 12:14:14 +0100488 ret = iioutils_get_param_float(&current->offset,
489 "offset",
490 device_dir,
491 current->name,
492 current->generic_name);
493 if (ret < 0)
494 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200495
Jonathan Camerone58537c2010-10-08 12:14:14 +0100496 ret = iioutils_get_type(&current->is_signed,
497 &current->bytes,
498 &current->bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +0100499 &current->shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100500 &current->mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000501 &current->be,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100502 device_dir,
503 current->name,
504 current->generic_name);
Hartmut Knaack53118552015-05-31 14:40:14 +0200505 if (ret < 0)
506 goto error_cleanup_array;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100507 }
508 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100509
Hartmut Knaack53118552015-05-31 14:40:14 +0200510 if (closedir(dp) == -1) {
511 ret = -errno;
512 goto error_cleanup_array;
513 }
514
Hartmut Knaack66dd08f2015-05-31 14:39:43 +0200515 free(scan_el_dir);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100516 /* reorder so that the array is in index order */
517 bsort_channel_array_by_index(ci_array, *counter);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100518
519 return 0;
520
521error_cleanup_array:
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200522 for (i = count - 1; i >= 0; i--) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100523 free((*ci_array)[i].name);
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200524 free((*ci_array)[i].generic_name);
525 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100526 free(*ci_array);
527error_close_dir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200528 if (dp)
529 if (closedir(dp) == -1)
530 perror("build_channel_array(): Failed to close dir");
531
Jonathan Camerone58537c2010-10-08 12:14:14 +0100532error_free_name:
533 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200534
Jonathan Camerone58537c2010-10-08 12:14:14 +0100535 return ret;
536}
537
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200538int calc_digits(int num)
539{
540 int count = 0;
541
542 while (num != 0) {
543 num /= 10;
544 count++;
545 }
546
547 return count;
548}
549
Jonathan Camerone58537c2010-10-08 12:14:14 +0100550/**
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100551 * find_type_by_name() - function to match top level types by name
552 * @name: top level type instance name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200553 * @type: the type of top level instance being searched
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100554 *
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200555 * Returns the device number of a matched IIO device on success, otherwise a
556 * negative error code.
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100557 * Typical types this is used for are device and trigger.
558 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200559int find_type_by_name(const char *name, const char *type)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100560{
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100561 const struct dirent *ent;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200562 int number, numstrlen, ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100563
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200564 FILE *namefp;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100565 DIR *dp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100566 char thisname[IIO_MAX_NAME_LENGTH];
567 char *filename;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100568
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100569 dp = opendir(iio_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300570 if (!dp) {
Peter Meerwaldc866ffc2012-07-01 00:47:41 +0200571 printf("No industrialio devices available\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100572 return -ENODEV;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100573 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100574
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300575 while (ent = readdir(dp), ent) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100576 if (strcmp(ent->d_name, ".") != 0 &&
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200577 strcmp(ent->d_name, "..") != 0 &&
578 strlen(ent->d_name) > strlen(type) &&
579 strncmp(ent->d_name, type, strlen(type)) == 0) {
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200580 errno = 0;
581 ret = sscanf(ent->d_name + strlen(type), "%d", &number);
582 if (ret < 0) {
583 ret = -errno;
584 printf("failed to read element number\n");
585 goto error_close_dir;
586 } else if (ret != 1) {
587 ret = -EIO;
588 printf("failed to match element number\n");
589 goto error_close_dir;
590 }
591
592 numstrlen = calc_digits(number);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100593 /* verify the next character is not a colon */
594 if (strncmp(ent->d_name + strlen(type) + numstrlen,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200595 ":", 1) != 0) {
596 filename = malloc(strlen(iio_dir) + strlen(type)
597 + numstrlen + 6);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300598 if (!filename) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200599 ret = -ENOMEM;
600 goto error_close_dir;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200601 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200602
603 ret = sprintf(filename, "%s%s%d/name", iio_dir,
604 type, number);
605 if (ret < 0) {
606 free(filename);
607 goto error_close_dir;
608 }
609
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200610 namefp = fopen(filename, "r");
611 if (!namefp) {
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200612 free(filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100613 continue;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200614 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200615
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100616 free(filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200617 errno = 0;
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200618 if (fscanf(namefp, "%s", thisname) != 1) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200619 ret = errno ? -errno : -ENODATA;
620 goto error_close_dir;
621 }
622
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200623 if (fclose(namefp)) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200624 ret = -errno;
625 goto error_close_dir;
626 }
627
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200628 if (strcmp(name, thisname) == 0) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200629 if (closedir(dp) == -1)
630 return -errno;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200631
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200632 return number;
633 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100634 }
635 }
636 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200637 if (closedir(dp) == -1)
638 return -errno;
639
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100640 return -ENODEV;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200641
642error_close_dir:
643 if (closedir(dp) == -1)
644 perror("find_type_by_name(): Failed to close directory");
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200645
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200646 return ret;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100647}
648
Hartmut Knaack9d475252015-05-31 14:40:36 +0200649static int _write_sysfs_int(const char *filename, const char *basedir, int val,
650 int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100651{
Sebastian Andrzej Siewior11cb4542013-10-07 13:42:00 +0100652 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100653 FILE *sysfsfp;
654 int test;
655 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300656
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300657 if (!temp)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100658 return -ENOMEM;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200659
Hartmut Knaack53118552015-05-31 14:40:14 +0200660 ret = sprintf(temp, "%s/%s", basedir, filename);
661 if (ret < 0)
662 goto error_free;
663
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100664 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300665 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100666 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200667 printf("failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100668 goto error_free;
669 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200670
Hartmut Knaack53118552015-05-31 14:40:14 +0200671 ret = fprintf(sysfsfp, "%d", val);
672 if (ret < 0) {
673 if (fclose(sysfsfp))
674 perror("_write_sysfs_int(): Failed to close dir");
675
676 goto error_free;
677 }
678
679 if (fclose(sysfsfp)) {
680 ret = -errno;
681 goto error_free;
682 }
683
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100684 if (verify) {
685 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300686 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100687 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200688 printf("failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100689 goto error_free;
690 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200691
Hartmut Knaack53118552015-05-31 14:40:14 +0200692 if (fscanf(sysfsfp, "%d", &test) != 1) {
693 ret = errno ? -errno : -ENODATA;
694 if (fclose(sysfsfp))
695 perror("_write_sysfs_int(): Failed to close dir");
696
697 goto error_free;
698 }
699
700 if (fclose(sysfsfp)) {
701 ret = -errno;
702 goto error_free;
703 }
704
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100705 if (test != val) {
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200706 printf("Possible failure in int write %d to %s/%s\n",
707 val, basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100708 ret = -1;
709 }
710 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200711
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100712error_free:
713 free(temp);
714 return ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100715}
716
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200717/**
718 * write_sysfs_int() - write an integer value to a sysfs file
719 * @filename: name of the file to write to
720 * @basedir: the sysfs directory in which the file is to be found
721 * @val: integer value to write to file
722 *
723 * Returns a value >= 0 on success, otherwise a negative error code.
724 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200725int write_sysfs_int(const char *filename, const char *basedir, int val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100726{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100727 return _write_sysfs_int(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100728}
729
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200730/**
731 * write_sysfs_int_and_verify() - write an integer value to a sysfs file
732 * and verify
733 * @filename: name of the file to write to
734 * @basedir: the sysfs directory in which the file is to be found
735 * @val: integer value to write to file
736 *
737 * Returns a value >= 0 on success, otherwise a negative error code.
738 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200739int write_sysfs_int_and_verify(const char *filename, const char *basedir,
740 int val)
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100741{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100742 return _write_sysfs_int(filename, basedir, val, 1);
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100743}
744
Hartmut Knaack9d475252015-05-31 14:40:36 +0200745static int _write_sysfs_string(const char *filename, const char *basedir,
746 const char *val, int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100747{
Jonathan Camerone58537c2010-10-08 12:14:14 +0100748 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100749 FILE *sysfsfp;
750 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300751
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300752 if (!temp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100753 printf("Memory allocation failed\n");
754 return -ENOMEM;
755 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200756
Hartmut Knaack53118552015-05-31 14:40:14 +0200757 ret = sprintf(temp, "%s/%s", basedir, filename);
758 if (ret < 0)
759 goto error_free;
760
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100761 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300762 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100763 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200764 printf("Could not open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100765 goto error_free;
766 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200767
Hartmut Knaack53118552015-05-31 14:40:14 +0200768 ret = fprintf(sysfsfp, "%s", val);
769 if (ret < 0) {
770 if (fclose(sysfsfp))
771 perror("_write_sysfs_string(): Failed to close dir");
772
773 goto error_free;
774 }
775
776 if (fclose(sysfsfp)) {
777 ret = -errno;
778 goto error_free;
779 }
780
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100781 if (verify) {
782 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300783 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100784 ret = -errno;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200785 printf("Could not open file to verify\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100786 goto error_free;
787 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200788
Hartmut Knaack53118552015-05-31 14:40:14 +0200789 if (fscanf(sysfsfp, "%s", temp) != 1) {
790 ret = errno ? -errno : -ENODATA;
791 if (fclose(sysfsfp))
792 perror("_write_sysfs_string(): Failed to close dir");
793
794 goto error_free;
795 }
796
797 if (fclose(sysfsfp)) {
798 ret = -errno;
799 goto error_free;
800 }
801
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100802 if (strcmp(temp, val) != 0) {
803 printf("Possible failure in string write of %s "
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200804 "Should be %s written to %s/%s\n", temp, val,
805 basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100806 ret = -1;
807 }
808 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200809
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100810error_free:
811 free(temp);
812
813 return ret;
814}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100815
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100816/**
817 * write_sysfs_string_and_verify() - string write, readback and verify
818 * @filename: name of file to write to
819 * @basedir: the sysfs directory in which the file is to be found
820 * @val: the string to write
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200821 *
822 * Returns a value >= 0 on success, otherwise a negative error code.
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100823 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200824int write_sysfs_string_and_verify(const char *filename, const char *basedir,
825 const char *val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100826{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100827 return _write_sysfs_string(filename, basedir, val, 1);
828}
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100829
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200830/**
831 * write_sysfs_string() - write string to a sysfs file
832 * @filename: name of file to write to
833 * @basedir: the sysfs directory in which the file is to be found
834 * @val: the string to write
835 *
836 * Returns a value >= 0 on success, otherwise a negative error code.
837 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200838int write_sysfs_string(const char *filename, const char *basedir,
839 const char *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100840{
841 return _write_sysfs_string(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100842}
843
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200844/**
845 * read_sysfs_posint() - read an integer value from file
846 * @filename: name of file to read from
847 * @basedir: the sysfs directory in which the file is to be found
848 *
849 * Returns the read integer value >= 0 on success, otherwise a negative error
850 * code.
851 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200852int read_sysfs_posint(const char *filename, const char *basedir)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100853{
854 int ret;
855 FILE *sysfsfp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100856 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300857
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300858 if (!temp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100859 printf("Memory allocation failed");
860 return -ENOMEM;
861 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200862
Hartmut Knaack53118552015-05-31 14:40:14 +0200863 ret = sprintf(temp, "%s/%s", basedir, filename);
864 if (ret < 0)
865 goto error_free;
866
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100867 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300868 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100869 ret = -errno;
870 goto error_free;
871 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200872
Hartmut Knaack53118552015-05-31 14:40:14 +0200873 errno = 0;
874 if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
875 ret = errno ? -errno : -ENODATA;
876 if (fclose(sysfsfp))
877 perror("read_sysfs_posint(): Failed to close dir");
878
879 goto error_free;
880 }
881
882 if (fclose(sysfsfp))
883 ret = -errno;
884
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100885error_free:
886 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200887
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100888 return ret;
889}
890
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200891/**
892 * read_sysfs_float() - read a float value from file
893 * @filename: name of file to read from
894 * @basedir: the sysfs directory in which the file is to be found
895 * @val: output the read float value
896 *
897 * Returns a value >= 0 on success, otherwise a negative error code.
898 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200899int read_sysfs_float(const char *filename, const char *basedir, float *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100900{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000901 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100902 FILE *sysfsfp;
903 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300904
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300905 if (!temp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100906 printf("Memory allocation failed");
907 return -ENOMEM;
908 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200909
Hartmut Knaack53118552015-05-31 14:40:14 +0200910 ret = sprintf(temp, "%s/%s", basedir, filename);
911 if (ret < 0)
912 goto error_free;
913
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100914 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300915 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100916 ret = -errno;
917 goto error_free;
918 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200919
Hartmut Knaack53118552015-05-31 14:40:14 +0200920 errno = 0;
921 if (fscanf(sysfsfp, "%f\n", val) != 1) {
922 ret = errno ? -errno : -ENODATA;
923 if (fclose(sysfsfp))
924 perror("read_sysfs_float(): Failed to close dir");
925
926 goto error_free;
927 }
928
929 if (fclose(sysfsfp))
930 ret = -errno;
931
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100932error_free:
933 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200934
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100935 return ret;
936}
Manuel Stahl49d916e2014-05-02 13:23:00 +0100937
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200938/**
939 * read_sysfs_string() - read a string from file
940 * @filename: name of file to read from
941 * @basedir: the sysfs directory in which the file is to be found
942 * @str: output the read string
943 *
944 * Returns a value >= 0 on success, otherwise a negative error code.
945 **/
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000946int read_sysfs_string(const char *filename, const char *basedir, char *str)
Manuel Stahl49d916e2014-05-02 13:23:00 +0100947{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000948 int ret = 0;
Manuel Stahl49d916e2014-05-02 13:23:00 +0100949 FILE *sysfsfp;
950 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300951
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300952 if (!temp) {
Manuel Stahl49d916e2014-05-02 13:23:00 +0100953 printf("Memory allocation failed");
954 return -ENOMEM;
955 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200956
Hartmut Knaack53118552015-05-31 14:40:14 +0200957 ret = sprintf(temp, "%s/%s", basedir, filename);
958 if (ret < 0)
959 goto error_free;
960
Manuel Stahl49d916e2014-05-02 13:23:00 +0100961 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300962 if (!sysfsfp) {
Manuel Stahl49d916e2014-05-02 13:23:00 +0100963 ret = -errno;
964 goto error_free;
965 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200966
Hartmut Knaack53118552015-05-31 14:40:14 +0200967 errno = 0;
968 if (fscanf(sysfsfp, "%s\n", str) != 1) {
969 ret = errno ? -errno : -ENODATA;
970 if (fclose(sysfsfp))
971 perror("read_sysfs_string(): Failed to close dir");
972
973 goto error_free;
974 }
975
976 if (fclose(sysfsfp))
977 ret = -errno;
978
Manuel Stahl49d916e2014-05-02 13:23:00 +0100979error_free:
980 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200981
Manuel Stahl49d916e2014-05-02 13:23:00 +0100982 return ret;
983}
Cristina Opriceana37e3be92015-03-04 02:37:15 +0200984
985#endif /* _IIO_UTILS_H */