blob: 4bbd6e7959cdad471e6cb0bdbf0d0cda915cd743 [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 */
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +01009#include <string.h>
10#include <stdlib.h>
Jonathan Camerone58537c2010-10-08 12:14:14 +010011#include <stdio.h>
12#include <stdint.h>
Lars-Peter Clausenbc9f35d2011-10-26 17:27:44 +010013#include <dirent.h>
Peter Meerwaldbb233782012-06-25 23:12:17 +020014#include <errno.h>
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +020015#include <ctype.h>
16#include "iio_utils.h"
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +010017
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010018const char *iio_dir = "/sys/bus/iio/devices/";
19
Irina Tirdead9d7b992015-03-27 13:53:00 +020020static char * const iio_direction[] = {
21 "in",
22 "out",
23};
24
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +010025/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010026 * iioutils_break_up_name() - extract generic name from full channel name
27 * @full_name: the full channel name
28 * @generic_name: the output generic channel name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020029 *
30 * Returns 0 on success, or a negative error code if string extraction failed.
Jonathan Camerone58537c2010-10-08 12:14:14 +010031 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020032int iioutils_break_up_name(const char *full_name, char **generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +010033{
34 char *current;
35 char *w, *r;
Irina Tirdead9d7b992015-03-27 13:53:00 +020036 char *working, *prefix = "";
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020037 int i, ret;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +030038
Cristina Opriceana34cbea12015-07-13 16:20:11 +030039 for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
Irina Tirdead9d7b992015-03-27 13:53:00 +020040 if (!strncmp(full_name, iio_direction[i],
41 strlen(iio_direction[i]))) {
42 prefix = iio_direction[i];
43 break;
44 }
45
46 current = strdup(full_name + strlen(prefix) + 1);
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020047 if (!current)
48 return -ENOMEM;
49
Jonathan Camerone58537c2010-10-08 12:14:14 +010050 working = strtok(current, "_\0");
Hartmut Knaack53118552015-05-31 14:40:14 +020051 if (!working) {
52 free(current);
53 return -EINVAL;
54 }
Irina Tirdead9d7b992015-03-27 13:53:00 +020055
Jonathan Camerone58537c2010-10-08 12:14:14 +010056 w = working;
57 r = working;
58
Michael Hennerich8b68bb22011-03-08 08:55:48 +010059 while (*r != '\0') {
Jonathan Camerone58537c2010-10-08 12:14:14 +010060 if (!isdigit(*r)) {
61 *w = *r;
62 w++;
63 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020064
Jonathan Camerone58537c2010-10-08 12:14:14 +010065 r++;
66 }
67 *w = '\0';
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020068 ret = asprintf(generic_name, "%s_%s", prefix, working);
Jonathan Camerone58537c2010-10-08 12:14:14 +010069 free(current);
70
Hartmut Knaacke9e45b42015-05-31 14:40:02 +020071 return (ret == -1) ? -ENOMEM : 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +010072}
73
74/**
Jonathan Camerone58537c2010-10-08 12:14:14 +010075 * iioutils_get_type() - find and process _type attribute data
76 * @is_signed: output whether channel is signed
77 * @bytes: output how many bytes the channel storage occupies
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020078 * @bits_used: output number of valid bits of data
79 * @shift: output amount of bits to shift right data before applying bit mask
Jonathan Camerone58537c2010-10-08 12:14:14 +010080 * @mask: output a bit mask for the raw data
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020081 * @be: output if data in big endian
82 * @device_dir: the IIO device directory
Jonathan Camerone58537c2010-10-08 12:14:14 +010083 * @name: the channel name
84 * @generic_name: the channel type name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +020085 *
86 * Returns a value >= 0 on success, otherwise a negative error code.
Jonathan Camerone58537c2010-10-08 12:14:14 +010087 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +020088int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
89 unsigned *shift, uint64_t *mask, unsigned *be,
90 const char *device_dir, const char *name,
91 const char *generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +010092{
93 FILE *sysfsfp;
94 int ret;
95 DIR *dp;
96 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
Jonathan Cameron117cf8b2011-12-04 19:10:59 +000097 char signchar, endianchar;
Michael Hennerichfc7f95a2011-02-24 16:34:54 +010098 unsigned padint;
Jonathan Camerone58537c2010-10-08 12:14:14 +010099 const struct dirent *ent;
100
101 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200102 if (ret < 0)
103 return -ENOMEM;
104
Jonathan Camerone58537c2010-10-08 12:14:14 +0100105 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
106 if (ret < 0) {
107 ret = -ENOMEM;
108 goto error_free_scan_el_dir;
109 }
110 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
111 if (ret < 0) {
112 ret = -ENOMEM;
113 goto error_free_builtname;
114 }
115
116 dp = opendir(scan_el_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300117 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100118 ret = -errno;
119 goto error_free_builtname_generic;
120 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200121
Hartmut Knaack53118552015-05-31 14:40:14 +0200122 ret = -ENOENT;
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300123 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100124 /*
125 * Do we allow devices to override a generic name with
126 * a specific one?
127 */
128 if ((strcmp(builtname, ent->d_name) == 0) ||
129 (strcmp(builtname_generic, ent->d_name) == 0)) {
130 ret = asprintf(&filename,
131 "%s/%s", scan_el_dir, ent->d_name);
132 if (ret < 0) {
133 ret = -ENOMEM;
134 goto error_closedir;
135 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200136
Jonathan Camerone58537c2010-10-08 12:14:14 +0100137 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300138 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100139 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300140 fprintf(stderr, "failed to open %s\n",
141 filename);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100142 goto error_free_filename;
143 }
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000144
145 ret = fscanf(sysfsfp,
146 "%ce:%c%u/%u>>%u",
147 &endianchar,
148 &signchar,
149 bits_used,
150 &padint, shift);
151 if (ret < 0) {
Peter Meerwald578f7372012-06-25 23:13:24 +0200152 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300153 fprintf(stderr,
154 "failed to pass scan type description\n");
Peter Meerwald578f7372012-06-25 23:13:24 +0200155 goto error_close_sysfsfp;
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200156 } else if (ret != 5) {
157 ret = -EIO;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300158 fprintf(stderr,
159 "scan type description didn't match\n");
Hartmut Knaackdc8b5d62015-05-31 14:39:59 +0200160 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
Irina Tirdeaae067cb2015-07-24 16:28:05 +0300168 *mask = (1ULL << *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;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300173 fprintf(stderr, "Failed to close %s\n",
174 filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200175 goto error_free_filename;
176 }
177
Hartmut Knaackace76e42015-05-31 14:40:20 +0200178 sysfsfp = 0;
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000179 free(filename);
Jonathan Camerona7f7c362011-12-04 19:10:58 +0000180 filename = 0;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100181 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200182
Peter Meerwald578f7372012-06-25 23:13:24 +0200183error_close_sysfsfp:
184 if (sysfsfp)
Hartmut Knaack53118552015-05-31 14:40:14 +0200185 if (fclose(sysfsfp))
186 perror("iioutils_get_type(): Failed to close file");
187
Jonathan Camerone58537c2010-10-08 12:14:14 +0100188error_free_filename:
189 if (filename)
190 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200191
Jonathan Camerone58537c2010-10-08 12:14:14 +0100192error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200193 if (closedir(dp) == -1)
194 perror("iioutils_get_type(): Failed to close directory");
195
Jonathan Camerone58537c2010-10-08 12:14:14 +0100196error_free_builtname_generic:
197 free(builtname_generic);
198error_free_builtname:
199 free(builtname);
200error_free_scan_el_dir:
201 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200202
Jonathan Camerone58537c2010-10-08 12:14:14 +0100203 return ret;
204}
205
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200206/**
207 * iioutils_get_param_float() - read a float value from a channel parameter
208 * @output: output the float value
209 * @param_name: the parameter name to read
210 * @device_dir: the IIO device directory in sysfs
211 * @name: the channel name
212 * @generic_name: the channel type name
213 *
214 * Returns a value >= 0 on success, otherwise a negative error code.
215 **/
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200216int iioutils_get_param_float(float *output, const char *param_name,
217 const char *device_dir, const char *name,
218 const char *generic_name)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100219{
220 FILE *sysfsfp;
221 int ret;
222 DIR *dp;
223 char *builtname, *builtname_generic;
224 char *filename = NULL;
225 const struct dirent *ent;
226
227 ret = asprintf(&builtname, "%s_%s", name, param_name);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200228 if (ret < 0)
229 return -ENOMEM;
230
Jonathan Camerone58537c2010-10-08 12:14:14 +0100231 ret = asprintf(&builtname_generic,
232 "%s_%s", generic_name, param_name);
233 if (ret < 0) {
234 ret = -ENOMEM;
235 goto error_free_builtname;
236 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200237
Jonathan Camerone58537c2010-10-08 12:14:14 +0100238 dp = opendir(device_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300239 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100240 ret = -errno;
241 goto error_free_builtname_generic;
242 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200243
Hartmut Knaack53118552015-05-31 14:40:14 +0200244 ret = -ENOENT;
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300245 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100246 if ((strcmp(builtname, ent->d_name) == 0) ||
247 (strcmp(builtname_generic, ent->d_name) == 0)) {
248 ret = asprintf(&filename,
249 "%s/%s", device_dir, ent->d_name);
250 if (ret < 0) {
251 ret = -ENOMEM;
252 goto error_closedir;
253 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200254
Jonathan Camerone58537c2010-10-08 12:14:14 +0100255 sysfsfp = fopen(filename, "r");
256 if (!sysfsfp) {
257 ret = -errno;
258 goto error_free_filename;
259 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200260
Hartmut Knaack53118552015-05-31 14:40:14 +0200261 errno = 0;
262 if (fscanf(sysfsfp, "%f", output) != 1)
263 ret = errno ? -errno : -ENODATA;
264
Jonathan Camerone58537c2010-10-08 12:14:14 +0100265 break;
266 }
267error_free_filename:
268 if (filename)
269 free(filename);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200270
Jonathan Camerone58537c2010-10-08 12:14:14 +0100271error_closedir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200272 if (closedir(dp) == -1)
273 perror("iioutils_get_param_float(): Failed to close directory");
274
Jonathan Camerone58537c2010-10-08 12:14:14 +0100275error_free_builtname_generic:
276 free(builtname_generic);
277error_free_builtname:
278 free(builtname);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200279
Jonathan Camerone58537c2010-10-08 12:14:14 +0100280 return ret;
281}
282
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100283/**
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200284 * bsort_channel_array_by_index() - sort the array in index order
285 * @ci_array: the iio_channel_info array to be sorted
286 * @cnt: the amount of array elements
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100287 **/
288
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200289void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt)
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100290{
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100291 struct iio_channel_info temp;
292 int x, y;
293
294 for (x = 0; x < cnt; x++)
295 for (y = 0; y < (cnt - 1); y++)
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200296 if ((*ci_array)[y].index > (*ci_array)[y + 1].index) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100297 temp = (*ci_array)[y + 1];
298 (*ci_array)[y + 1] = (*ci_array)[y];
299 (*ci_array)[y] = temp;
300 }
301}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100302
303/**
304 * build_channel_array() - function to figure out what channels are present
305 * @device_dir: the IIO device directory in sysfs
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200306 * @ci_array: output the resulting array of iio_channel_info
307 * @counter: output the amount of array elements
308 *
309 * Returns 0 on success, otherwise a negative error code.
Jonathan Camerone58537c2010-10-08 12:14:14 +0100310 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200311int build_channel_array(const char *device_dir,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200312 struct iio_channel_info **ci_array, int *counter)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100313{
314 DIR *dp;
315 FILE *sysfsfp;
Hartmut Knaack1e7c3472015-05-31 14:40:21 +0200316 int count = 0, i;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100317 struct iio_channel_info *current;
318 int ret;
319 const struct dirent *ent;
320 char *scan_el_dir;
321 char *filename;
322
323 *counter = 0;
324 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200325 if (ret < 0)
326 return -ENOMEM;
327
Jonathan Camerone58537c2010-10-08 12:14:14 +0100328 dp = opendir(scan_el_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300329 if (!dp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100330 ret = -errno;
331 goto error_free_name;
332 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200333
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300334 while (ent = readdir(dp), ent)
Jonathan Camerone58537c2010-10-08 12:14:14 +0100335 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
336 "_en") == 0) {
337 ret = asprintf(&filename,
338 "%s/%s", scan_el_dir, ent->d_name);
339 if (ret < 0) {
340 ret = -ENOMEM;
341 goto error_close_dir;
342 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200343
Jonathan Camerone58537c2010-10-08 12:14:14 +0100344 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300345 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100346 ret = -errno;
347 free(filename);
348 goto error_close_dir;
349 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200350
Hartmut Knaack53118552015-05-31 14:40:14 +0200351 errno = 0;
352 if (fscanf(sysfsfp, "%i", &ret) != 1) {
353 ret = errno ? -errno : -ENODATA;
354 if (fclose(sysfsfp))
355 perror("build_channel_array(): Failed to close file");
356
357 free(filename);
358 goto error_close_dir;
359 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100360 if (ret == 1)
361 (*counter)++;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200362
Hartmut Knaack53118552015-05-31 14:40:14 +0200363 if (fclose(sysfsfp)) {
364 ret = -errno;
365 free(filename);
366 goto error_close_dir;
367 }
368
Jonathan Camerone58537c2010-10-08 12:14:14 +0100369 free(filename);
370 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200371
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100372 *ci_array = malloc(sizeof(**ci_array) * (*counter));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300373 if (!*ci_array) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100374 ret = -ENOMEM;
375 goto error_close_dir;
376 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200377
Jonathan Camerone58537c2010-10-08 12:14:14 +0100378 seekdir(dp, 0);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300379 while (ent = readdir(dp), ent) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100380 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
381 "_en") == 0) {
Craig Markwardt66c65d92014-01-01 15:38:52 +0000382 int current_enabled = 0;
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300383
Jonathan Camerone58537c2010-10-08 12:14:14 +0100384 current = &(*ci_array)[count++];
385 ret = asprintf(&filename,
386 "%s/%s", scan_el_dir, ent->d_name);
387 if (ret < 0) {
388 ret = -ENOMEM;
389 /* decrement count to avoid freeing name */
390 count--;
391 goto error_cleanup_array;
392 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200393
Jonathan Camerone58537c2010-10-08 12:14:14 +0100394 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300395 if (!sysfsfp) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100396 ret = -errno;
Hartmut Knaack2b6a6e62015-05-31 14:39:48 +0200397 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200398 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100399 goto error_cleanup_array;
400 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200401
Hartmut Knaack53118552015-05-31 14:40:14 +0200402 errno = 0;
403 if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
404 ret = errno ? -errno : -ENODATA;
405 free(filename);
406 count--;
407 goto error_cleanup_array;
408 }
409
410 if (fclose(sysfsfp)) {
411 ret = -errno;
412 free(filename);
413 count--;
414 goto error_cleanup_array;
415 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100416
Craig Markwardt66c65d92014-01-01 15:38:52 +0000417 if (!current_enabled) {
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100418 free(filename);
419 count--;
420 continue;
421 }
422
Jonathan Camerone58537c2010-10-08 12:14:14 +0100423 current->scale = 1.0;
424 current->offset = 0;
425 current->name = strndup(ent->d_name,
426 strlen(ent->d_name) -
427 strlen("_en"));
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300428 if (!current->name) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100429 free(filename);
430 ret = -ENOMEM;
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200431 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100432 goto error_cleanup_array;
433 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200434
Jonathan Camerone58537c2010-10-08 12:14:14 +0100435 /* Get the generic and specific name elements */
436 ret = iioutils_break_up_name(current->name,
437 &current->generic_name);
438 if (ret) {
439 free(filename);
Hartmut Knaack121b5e52015-05-31 14:39:45 +0200440 free(current->name);
441 count--;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100442 goto error_cleanup_array;
443 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200444
Jonathan Camerone58537c2010-10-08 12:14:14 +0100445 ret = asprintf(&filename,
446 "%s/%s_index",
447 scan_el_dir,
448 current->name);
449 if (ret < 0) {
450 free(filename);
451 ret = -ENOMEM;
452 goto error_cleanup_array;
453 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200454
Jonathan Camerone58537c2010-10-08 12:14:14 +0100455 sysfsfp = fopen(filename, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300456 if (!sysfsfp) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200457 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300458 fprintf(stderr, "failed to open %s\n",
459 filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200460 free(filename);
461 goto error_cleanup_array;
462 }
463
464 errno = 0;
465 if (fscanf(sysfsfp, "%u", &current->index) != 1) {
466 ret = errno ? -errno : -ENODATA;
467 if (fclose(sysfsfp))
468 perror("build_channel_array(): Failed to close file");
469
470 free(filename);
471 goto error_cleanup_array;
472 }
473
474 if (fclose(sysfsfp)) {
475 ret = -errno;
476 free(filename);
477 goto error_cleanup_array;
478 }
479
Jonathan Camerone58537c2010-10-08 12:14:14 +0100480 free(filename);
481 /* Find the scale */
482 ret = iioutils_get_param_float(&current->scale,
483 "scale",
484 device_dir,
485 current->name,
486 current->generic_name);
Joo Aun Saw7868dfd2015-07-23 12:53:47 +1000487 if ((ret < 0) && (ret != -ENOENT))
Jonathan Camerone58537c2010-10-08 12:14:14 +0100488 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200489
Jonathan Camerone58537c2010-10-08 12:14:14 +0100490 ret = iioutils_get_param_float(&current->offset,
491 "offset",
492 device_dir,
493 current->name,
494 current->generic_name);
Joo Aun Saw7868dfd2015-07-23 12:53:47 +1000495 if ((ret < 0) && (ret != -ENOENT))
Jonathan Camerone58537c2010-10-08 12:14:14 +0100496 goto error_cleanup_array;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200497
Jonathan Camerone58537c2010-10-08 12:14:14 +0100498 ret = iioutils_get_type(&current->is_signed,
499 &current->bytes,
500 &current->bits_used,
Jonathan Cameron52615d42011-05-18 14:41:19 +0100501 &current->shift,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100502 &current->mask,
Jonathan Cameron117cf8b2011-12-04 19:10:59 +0000503 &current->be,
Jonathan Camerone58537c2010-10-08 12:14:14 +0100504 device_dir,
505 current->name,
506 current->generic_name);
Hartmut Knaack53118552015-05-31 14:40:14 +0200507 if (ret < 0)
508 goto error_cleanup_array;
Jonathan Camerone58537c2010-10-08 12:14:14 +0100509 }
510 }
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100511
Hartmut Knaack53118552015-05-31 14:40:14 +0200512 if (closedir(dp) == -1) {
513 ret = -errno;
514 goto error_cleanup_array;
515 }
516
Hartmut Knaack66dd08f2015-05-31 14:39:43 +0200517 free(scan_el_dir);
Michael Hennerich8b68bb22011-03-08 08:55:48 +0100518 /* reorder so that the array is in index order */
519 bsort_channel_array_by_index(ci_array, *counter);
Jonathan Camerone58537c2010-10-08 12:14:14 +0100520
521 return 0;
522
523error_cleanup_array:
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200524 for (i = count - 1; i >= 0; i--) {
Jonathan Camerone58537c2010-10-08 12:14:14 +0100525 free((*ci_array)[i].name);
Hartmut Knaack63f05c82015-05-31 14:39:44 +0200526 free((*ci_array)[i].generic_name);
527 }
Jonathan Camerone58537c2010-10-08 12:14:14 +0100528 free(*ci_array);
529error_close_dir:
Hartmut Knaack53118552015-05-31 14:40:14 +0200530 if (dp)
531 if (closedir(dp) == -1)
532 perror("build_channel_array(): Failed to close dir");
533
Jonathan Camerone58537c2010-10-08 12:14:14 +0100534error_free_name:
535 free(scan_el_dir);
Hartmut Knaack0e799872015-05-31 14:40:17 +0200536
Jonathan Camerone58537c2010-10-08 12:14:14 +0100537 return ret;
538}
539
Joo Aun Saw5e37c522015-07-28 11:46:13 +1000540static int calc_digits(int num)
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200541{
542 int count = 0;
543
544 while (num != 0) {
545 num /= 10;
546 count++;
547 }
548
549 return count;
550}
551
Jonathan Camerone58537c2010-10-08 12:14:14 +0100552/**
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100553 * find_type_by_name() - function to match top level types by name
554 * @name: top level type instance name
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200555 * @type: the type of top level instance being searched
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100556 *
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200557 * Returns the device number of a matched IIO device on success, otherwise a
558 * negative error code.
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100559 * Typical types this is used for are device and trigger.
560 **/
Roberta Dobrescubdcb31d2015-02-26 10:49:24 +0200561int find_type_by_name(const char *name, const char *type)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100562{
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100563 const struct dirent *ent;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200564 int number, numstrlen, ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100565
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200566 FILE *namefp;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100567 DIR *dp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100568 char thisname[IIO_MAX_NAME_LENGTH];
569 char *filename;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100570
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100571 dp = opendir(iio_dir);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300572 if (!dp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300573 fprintf(stderr, "No industrialio devices available\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100574 return -ENODEV;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100575 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100576
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300577 while (ent = readdir(dp), ent) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100578 if (strcmp(ent->d_name, ".") != 0 &&
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200579 strcmp(ent->d_name, "..") != 0 &&
580 strlen(ent->d_name) > strlen(type) &&
581 strncmp(ent->d_name, type, strlen(type)) == 0) {
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200582 errno = 0;
583 ret = sscanf(ent->d_name + strlen(type), "%d", &number);
584 if (ret < 0) {
585 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300586 fprintf(stderr,
587 "failed to read element number\n");
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200588 goto error_close_dir;
589 } else if (ret != 1) {
590 ret = -EIO;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300591 fprintf(stderr,
592 "failed to match element number\n");
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200593 goto error_close_dir;
594 }
595
596 numstrlen = calc_digits(number);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100597 /* verify the next character is not a colon */
598 if (strncmp(ent->d_name + strlen(type) + numstrlen,
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200599 ":", 1) != 0) {
600 filename = malloc(strlen(iio_dir) + strlen(type)
601 + numstrlen + 6);
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300602 if (!filename) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200603 ret = -ENOMEM;
604 goto error_close_dir;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200605 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200606
607 ret = sprintf(filename, "%s%s%d/name", iio_dir,
608 type, number);
609 if (ret < 0) {
610 free(filename);
611 goto error_close_dir;
612 }
613
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200614 namefp = fopen(filename, "r");
615 if (!namefp) {
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200616 free(filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100617 continue;
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200618 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200619
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100620 free(filename);
Hartmut Knaack53118552015-05-31 14:40:14 +0200621 errno = 0;
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200622 if (fscanf(namefp, "%s", thisname) != 1) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200623 ret = errno ? -errno : -ENODATA;
624 goto error_close_dir;
625 }
626
Hartmut Knaacka9d7acc2015-06-10 21:51:21 +0200627 if (fclose(namefp)) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200628 ret = -errno;
629 goto error_close_dir;
630 }
631
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200632 if (strcmp(name, thisname) == 0) {
Hartmut Knaack53118552015-05-31 14:40:14 +0200633 if (closedir(dp) == -1)
634 return -errno;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200635
Peter Meerwalda4d429e2012-06-25 23:13:25 +0200636 return number;
637 }
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100638 }
639 }
640 }
Hartmut Knaack53118552015-05-31 14:40:14 +0200641 if (closedir(dp) == -1)
642 return -errno;
643
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100644 return -ENODEV;
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200645
646error_close_dir:
647 if (closedir(dp) == -1)
648 perror("find_type_by_name(): Failed to close directory");
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200649
Hartmut Knaack096f9b82015-05-31 14:40:00 +0200650 return ret;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100651}
652
Hartmut Knaack9d475252015-05-31 14:40:36 +0200653static int _write_sysfs_int(const char *filename, const char *basedir, int val,
654 int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100655{
Sebastian Andrzej Siewior11cb4542013-10-07 13:42:00 +0100656 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100657 FILE *sysfsfp;
658 int test;
659 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300660
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300661 if (!temp)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100662 return -ENOMEM;
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200663
Hartmut Knaack53118552015-05-31 14:40:14 +0200664 ret = sprintf(temp, "%s/%s", basedir, filename);
665 if (ret < 0)
666 goto error_free;
667
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100668 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300669 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100670 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300671 fprintf(stderr, "failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100672 goto error_free;
673 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200674
Hartmut Knaack53118552015-05-31 14:40:14 +0200675 ret = fprintf(sysfsfp, "%d", val);
676 if (ret < 0) {
677 if (fclose(sysfsfp))
678 perror("_write_sysfs_int(): Failed to close dir");
679
680 goto error_free;
681 }
682
683 if (fclose(sysfsfp)) {
684 ret = -errno;
685 goto error_free;
686 }
687
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100688 if (verify) {
689 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300690 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100691 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300692 fprintf(stderr, "failed to open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100693 goto error_free;
694 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200695
Hartmut Knaack53118552015-05-31 14:40:14 +0200696 if (fscanf(sysfsfp, "%d", &test) != 1) {
697 ret = errno ? -errno : -ENODATA;
698 if (fclose(sysfsfp))
699 perror("_write_sysfs_int(): Failed to close dir");
700
701 goto error_free;
702 }
703
704 if (fclose(sysfsfp)) {
705 ret = -errno;
706 goto error_free;
707 }
708
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100709 if (test != val) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300710 fprintf(stderr,
711 "Possible failure in int write %d to %s/%s\n",
712 val, basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100713 ret = -1;
714 }
715 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200716
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100717error_free:
718 free(temp);
719 return ret;
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100720}
721
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200722/**
723 * write_sysfs_int() - write an integer value to a sysfs file
724 * @filename: name of the file to write to
725 * @basedir: the sysfs directory in which the file is to be found
726 * @val: integer value to write to file
727 *
728 * Returns a value >= 0 on success, otherwise a negative error code.
729 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200730int write_sysfs_int(const char *filename, const char *basedir, int val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100731{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100732 return _write_sysfs_int(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100733}
734
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200735/**
736 * write_sysfs_int_and_verify() - write an integer value to a sysfs file
737 * and verify
738 * @filename: name of the file to write to
739 * @basedir: the sysfs directory in which the file is to be found
740 * @val: integer value to write to file
741 *
742 * Returns a value >= 0 on success, otherwise a negative error code.
743 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200744int write_sysfs_int_and_verify(const char *filename, const char *basedir,
745 int val)
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100746{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100747 return _write_sysfs_int(filename, basedir, val, 1);
Jonathan Cameroneaf86ff2010-05-04 14:43:04 +0100748}
749
Hartmut Knaack9d475252015-05-31 14:40:36 +0200750static int _write_sysfs_string(const char *filename, const char *basedir,
751 const char *val, int verify)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100752{
Jonathan Camerone58537c2010-10-08 12:14:14 +0100753 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100754 FILE *sysfsfp;
755 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300756
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300757 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300758 fprintf(stderr, "Memory allocation failed\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100759 return -ENOMEM;
760 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200761
Hartmut Knaack53118552015-05-31 14:40:14 +0200762 ret = sprintf(temp, "%s/%s", basedir, filename);
763 if (ret < 0)
764 goto error_free;
765
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100766 sysfsfp = fopen(temp, "w");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300767 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100768 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300769 fprintf(stderr, "Could not open %s\n", temp);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100770 goto error_free;
771 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200772
Hartmut Knaack53118552015-05-31 14:40:14 +0200773 ret = fprintf(sysfsfp, "%s", val);
774 if (ret < 0) {
775 if (fclose(sysfsfp))
776 perror("_write_sysfs_string(): Failed to close dir");
777
778 goto error_free;
779 }
780
781 if (fclose(sysfsfp)) {
782 ret = -errno;
783 goto error_free;
784 }
785
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100786 if (verify) {
787 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300788 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100789 ret = -errno;
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300790 fprintf(stderr, "Could not open file to verify\n");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100791 goto error_free;
792 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200793
Hartmut Knaack53118552015-05-31 14:40:14 +0200794 if (fscanf(sysfsfp, "%s", temp) != 1) {
795 ret = errno ? -errno : -ENODATA;
796 if (fclose(sysfsfp))
797 perror("_write_sysfs_string(): Failed to close dir");
798
799 goto error_free;
800 }
801
802 if (fclose(sysfsfp)) {
803 ret = -errno;
804 goto error_free;
805 }
806
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100807 if (strcmp(temp, val) != 0) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300808 fprintf(stderr,
809 "Possible failure in string write of %s "
810 "Should be %s written to %s/%s\n", temp, val,
811 basedir, filename);
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100812 ret = -1;
813 }
814 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200815
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100816error_free:
817 free(temp);
818
819 return ret;
820}
Jonathan Camerone58537c2010-10-08 12:14:14 +0100821
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100822/**
823 * write_sysfs_string_and_verify() - string write, readback and verify
824 * @filename: name of file to write to
825 * @basedir: the sysfs directory in which the file is to be found
826 * @val: the string to write
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200827 *
828 * Returns a value >= 0 on success, otherwise a negative error code.
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100829 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200830int write_sysfs_string_and_verify(const char *filename, const char *basedir,
831 const char *val)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100832{
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100833 return _write_sysfs_string(filename, basedir, val, 1);
834}
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100835
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200836/**
837 * write_sysfs_string() - write string to a sysfs file
838 * @filename: name of file to write to
839 * @basedir: the sysfs directory in which the file is to be found
840 * @val: the string to write
841 *
842 * Returns a value >= 0 on success, otherwise a negative error code.
843 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200844int write_sysfs_string(const char *filename, const char *basedir,
845 const char *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100846{
847 return _write_sysfs_string(filename, basedir, val, 0);
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100848}
849
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200850/**
851 * read_sysfs_posint() - read an integer value from file
852 * @filename: name of file to read from
853 * @basedir: the sysfs directory in which the file is to be found
854 *
855 * Returns the read integer value >= 0 on success, otherwise a negative error
856 * code.
857 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200858int read_sysfs_posint(const char *filename, const char *basedir)
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100859{
860 int ret;
861 FILE *sysfsfp;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100862 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300863
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300864 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300865 fprintf(stderr, "Memory allocation failed");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100866 return -ENOMEM;
867 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200868
Hartmut Knaack53118552015-05-31 14:40:14 +0200869 ret = sprintf(temp, "%s/%s", basedir, filename);
870 if (ret < 0)
871 goto error_free;
872
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100873 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300874 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100875 ret = -errno;
876 goto error_free;
877 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200878
Hartmut Knaack53118552015-05-31 14:40:14 +0200879 errno = 0;
880 if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
881 ret = errno ? -errno : -ENODATA;
882 if (fclose(sysfsfp))
883 perror("read_sysfs_posint(): Failed to close dir");
884
885 goto error_free;
886 }
887
888 if (fclose(sysfsfp))
889 ret = -errno;
890
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100891error_free:
892 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200893
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100894 return ret;
895}
896
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200897/**
898 * read_sysfs_float() - read a float value from file
899 * @filename: name of file to read from
900 * @basedir: the sysfs directory in which the file is to be found
901 * @val: output the read float value
902 *
903 * Returns a value >= 0 on success, otherwise a negative error code.
904 **/
Hartmut Knaack9d475252015-05-31 14:40:36 +0200905int read_sysfs_float(const char *filename, const char *basedir, float *val)
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100906{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000907 int ret = 0;
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100908 FILE *sysfsfp;
909 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300910
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300911 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300912 fprintf(stderr, "Memory allocation failed");
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100913 return -ENOMEM;
914 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200915
Hartmut Knaack53118552015-05-31 14:40:14 +0200916 ret = sprintf(temp, "%s/%s", basedir, filename);
917 if (ret < 0)
918 goto error_free;
919
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100920 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300921 if (!sysfsfp) {
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100922 ret = -errno;
923 goto error_free;
924 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200925
Hartmut Knaack53118552015-05-31 14:40:14 +0200926 errno = 0;
927 if (fscanf(sysfsfp, "%f\n", val) != 1) {
928 ret = errno ? -errno : -ENODATA;
929 if (fclose(sysfsfp))
930 perror("read_sysfs_float(): Failed to close dir");
931
932 goto error_free;
933 }
934
935 if (fclose(sysfsfp))
936 ret = -errno;
937
Jonathan Cameron9d8ae6c2010-05-04 14:43:13 +0100938error_free:
939 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200940
Jonathan Cameronc57f1ba2009-08-18 18:06:32 +0100941 return ret;
942}
Manuel Stahl49d916e2014-05-02 13:23:00 +0100943
Hartmut Knaack5dc65d72015-05-31 14:40:16 +0200944/**
945 * read_sysfs_string() - read a string from file
946 * @filename: name of file to read from
947 * @basedir: the sysfs directory in which the file is to be found
948 * @str: output the read string
949 *
950 * Returns a value >= 0 on success, otherwise a negative error code.
951 **/
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000952int read_sysfs_string(const char *filename, const char *basedir, char *str)
Manuel Stahl49d916e2014-05-02 13:23:00 +0100953{
Peter Meerwaldf5709d52014-12-06 06:00:00 +0000954 int ret = 0;
Manuel Stahl49d916e2014-05-02 13:23:00 +0100955 FILE *sysfsfp;
956 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
Melike Yurtoglu79bdd482014-10-03 23:35:54 +0300957
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300958 if (!temp) {
Cristina Opriceanad9abc612015-07-17 18:43:42 +0300959 fprintf(stderr, "Memory allocation failed");
Manuel Stahl49d916e2014-05-02 13:23:00 +0100960 return -ENOMEM;
961 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200962
Hartmut Knaack53118552015-05-31 14:40:14 +0200963 ret = sprintf(temp, "%s/%s", basedir, filename);
964 if (ret < 0)
965 goto error_free;
966
Manuel Stahl49d916e2014-05-02 13:23:00 +0100967 sysfsfp = fopen(temp, "r");
Cristina Opriceanaff1ac632015-07-13 16:15:56 +0300968 if (!sysfsfp) {
Manuel Stahl49d916e2014-05-02 13:23:00 +0100969 ret = -errno;
970 goto error_free;
971 }
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200972
Hartmut Knaack53118552015-05-31 14:40:14 +0200973 errno = 0;
974 if (fscanf(sysfsfp, "%s\n", str) != 1) {
975 ret = errno ? -errno : -ENODATA;
976 if (fclose(sysfsfp))
977 perror("read_sysfs_string(): Failed to close dir");
978
979 goto error_free;
980 }
981
982 if (fclose(sysfsfp))
983 ret = -errno;
984
Manuel Stahl49d916e2014-05-02 13:23:00 +0100985error_free:
986 free(temp);
Hartmut Knaack7663a4a2015-06-10 21:51:20 +0200987
Manuel Stahl49d916e2014-05-02 13:23:00 +0100988 return ret;
989}