Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/iio/iio_utils.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* IIO - useful set of util functionality
3
*
4
* Copyright (c) 2008 Jonathan Cameron
5
*/
6
#include <string.h>
7
#include <stdlib.h>
8
#include <stdio.h>
9
#include <stdint.h>
10
#include <dirent.h>
11
#include <errno.h>
12
#include <ctype.h>
13
#include "iio_utils.h"
14
15
const char *iio_dir = "/sys/bus/iio/devices/";
16
17
static char * const iio_direction[] = {
18
"in",
19
"out",
20
};
21
22
/**
23
* iioutils_break_up_name() - extract generic name from full channel name
24
* @full_name: the full channel name
25
* @generic_name: the output generic channel name
26
*
27
* Returns 0 on success, or a negative error code if string extraction failed.
28
**/
29
int iioutils_break_up_name(const char *full_name, char **generic_name)
30
{
31
char *current;
32
char *w, *r;
33
char *working, *prefix = "";
34
int i, ret;
35
36
for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
37
if (!strncmp(full_name, iio_direction[i],
38
strlen(iio_direction[i]))) {
39
prefix = iio_direction[i];
40
break;
41
}
42
43
current = strdup(full_name + strlen(prefix) + 1);
44
if (!current)
45
return -ENOMEM;
46
47
working = strtok(current, "_\0");
48
if (!working) {
49
free(current);
50
return -EINVAL;
51
}
52
53
w = working;
54
r = working;
55
56
while (*r != '\0') {
57
if (!isdigit(*r)) {
58
*w = *r;
59
w++;
60
}
61
62
r++;
63
}
64
*w = '\0';
65
ret = asprintf(generic_name, "%s_%s", prefix, working);
66
free(current);
67
68
return (ret == -1) ? -ENOMEM : 0;
69
}
70
71
/**
72
* iioutils_get_type() - find and process _type attribute data
73
* @is_signed: output whether channel is signed
74
* @bytes: output how many bytes the channel storage occupies
75
* @bits_used: output number of valid bits of data
76
* @shift: output amount of bits to shift right data before applying bit mask
77
* @mask: output a bit mask for the raw data
78
* @be: output if data in big endian
79
* @device_dir: the IIO device directory
80
* @buffer_idx: the IIO buffer index
81
* @name: the channel name
82
* @generic_name: the channel type name
83
*
84
* Returns a value >= 0 on success, otherwise a negative error code.
85
**/
86
static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes,
87
unsigned int *bits_used, unsigned int *shift,
88
uint64_t *mask, unsigned int *be,
89
const char *device_dir, int buffer_idx,
90
const char *name, const char *generic_name)
91
{
92
FILE *sysfsfp;
93
int ret;
94
DIR *dp;
95
char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
96
char signchar, endianchar;
97
unsigned padint;
98
const struct dirent *ent;
99
100
ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir, buffer_idx);
101
if (ret < 0)
102
return -ENOMEM;
103
104
ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
105
if (ret < 0) {
106
ret = -ENOMEM;
107
goto error_free_scan_el_dir;
108
}
109
ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
110
if (ret < 0) {
111
ret = -ENOMEM;
112
goto error_free_builtname;
113
}
114
115
dp = opendir(scan_el_dir);
116
if (!dp) {
117
ret = -errno;
118
goto error_free_builtname_generic;
119
}
120
121
ret = -ENOENT;
122
while (ent = readdir(dp), ent)
123
if ((strcmp(builtname, ent->d_name) == 0) ||
124
(strcmp(builtname_generic, ent->d_name) == 0)) {
125
ret = asprintf(&filename,
126
"%s/%s", scan_el_dir, ent->d_name);
127
if (ret < 0) {
128
ret = -ENOMEM;
129
goto error_closedir;
130
}
131
132
sysfsfp = fopen(filename, "r");
133
if (!sysfsfp) {
134
ret = -errno;
135
fprintf(stderr, "failed to open %s\n",
136
filename);
137
goto error_free_filename;
138
}
139
140
ret = fscanf(sysfsfp,
141
"%ce:%c%u/%u>>%u",
142
&endianchar,
143
&signchar,
144
bits_used,
145
&padint, shift);
146
if (ret < 0) {
147
ret = -errno;
148
fprintf(stderr,
149
"failed to pass scan type description\n");
150
goto error_close_sysfsfp;
151
} else if (ret != 5) {
152
ret = -EIO;
153
fprintf(stderr,
154
"scan type description didn't match\n");
155
goto error_close_sysfsfp;
156
}
157
158
*be = (endianchar == 'b');
159
*bytes = padint / 8;
160
if (*bits_used == 64)
161
*mask = ~(0ULL);
162
else
163
*mask = (1ULL << *bits_used) - 1ULL;
164
165
*is_signed = (signchar == 's');
166
if (fclose(sysfsfp)) {
167
ret = -errno;
168
fprintf(stderr, "Failed to close %s\n",
169
filename);
170
goto error_free_filename;
171
}
172
173
sysfsfp = 0;
174
free(filename);
175
filename = 0;
176
177
/*
178
* Avoid having a more generic entry overwriting
179
* the settings.
180
*/
181
if (strcmp(builtname, ent->d_name) == 0)
182
break;
183
}
184
185
error_close_sysfsfp:
186
if (sysfsfp)
187
if (fclose(sysfsfp))
188
perror("iioutils_get_type(): Failed to close file");
189
190
error_free_filename:
191
if (filename)
192
free(filename);
193
194
error_closedir:
195
if (closedir(dp) == -1)
196
perror("iioutils_get_type(): Failed to close directory");
197
198
error_free_builtname_generic:
199
free(builtname_generic);
200
error_free_builtname:
201
free(builtname);
202
error_free_scan_el_dir:
203
free(scan_el_dir);
204
205
return ret;
206
}
207
208
/**
209
* iioutils_get_param_float() - read a float value from a channel parameter
210
* @output: output the float value
211
* @param_name: the parameter name to read
212
* @device_dir: the IIO device directory in sysfs
213
* @name: the channel name
214
* @generic_name: the channel type name
215
*
216
* Returns a value >= 0 on success, otherwise a negative error code.
217
**/
218
int iioutils_get_param_float(float *output, const char *param_name,
219
const char *device_dir, const char *name,
220
const char *generic_name)
221
{
222
FILE *sysfsfp;
223
int ret;
224
DIR *dp;
225
char *builtname, *builtname_generic;
226
char *filename = NULL;
227
const struct dirent *ent;
228
229
ret = asprintf(&builtname, "%s_%s", name, param_name);
230
if (ret < 0)
231
return -ENOMEM;
232
233
ret = asprintf(&builtname_generic,
234
"%s_%s", generic_name, param_name);
235
if (ret < 0) {
236
ret = -ENOMEM;
237
goto error_free_builtname;
238
}
239
240
dp = opendir(device_dir);
241
if (!dp) {
242
ret = -errno;
243
goto error_free_builtname_generic;
244
}
245
246
ret = -ENOENT;
247
while (ent = readdir(dp), ent)
248
if ((strcmp(builtname, ent->d_name) == 0) ||
249
(strcmp(builtname_generic, ent->d_name) == 0)) {
250
ret = asprintf(&filename,
251
"%s/%s", device_dir, ent->d_name);
252
if (ret < 0) {
253
ret = -ENOMEM;
254
goto error_closedir;
255
}
256
257
sysfsfp = fopen(filename, "r");
258
if (!sysfsfp) {
259
ret = -errno;
260
goto error_free_filename;
261
}
262
263
errno = 0;
264
if (fscanf(sysfsfp, "%f", output) != 1)
265
ret = errno ? -errno : -ENODATA;
266
267
fclose(sysfsfp);
268
break;
269
}
270
error_free_filename:
271
if (filename)
272
free(filename);
273
274
error_closedir:
275
if (closedir(dp) == -1)
276
perror("iioutils_get_param_float(): Failed to close directory");
277
278
error_free_builtname_generic:
279
free(builtname_generic);
280
error_free_builtname:
281
free(builtname);
282
283
return ret;
284
}
285
286
/**
287
* 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
290
**/
291
292
void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt)
293
{
294
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++)
299
if (ci_array[y].index > ci_array[y + 1].index) {
300
temp = ci_array[y + 1];
301
ci_array[y + 1] = ci_array[y];
302
ci_array[y] = temp;
303
}
304
}
305
306
/**
307
* build_channel_array() - function to figure out what channels are present
308
* @device_dir: the IIO device directory in sysfs
309
* @buffer_idx: the IIO buffer for this channel array
310
* @ci_array: output the resulting array of iio_channel_info
311
* @counter: output the amount of array elements
312
*
313
* Returns 0 on success, otherwise a negative error code.
314
**/
315
int build_channel_array(const char *device_dir, int buffer_idx,
316
struct iio_channel_info **ci_array, int *counter)
317
{
318
DIR *dp;
319
FILE *sysfsfp;
320
int count = 0, i;
321
struct iio_channel_info *current;
322
int ret;
323
const struct dirent *ent;
324
char *scan_el_dir;
325
char *filename;
326
327
*counter = 0;
328
ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir, buffer_idx);
329
if (ret < 0)
330
return -ENOMEM;
331
332
dp = opendir(scan_el_dir);
333
if (!dp) {
334
ret = -errno;
335
goto error_free_name;
336
}
337
338
while (ent = readdir(dp), ent)
339
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
340
"_en") == 0) {
341
ret = asprintf(&filename,
342
"%s/%s", scan_el_dir, ent->d_name);
343
if (ret < 0) {
344
ret = -ENOMEM;
345
goto error_close_dir;
346
}
347
348
sysfsfp = fopen(filename, "r");
349
free(filename);
350
if (!sysfsfp) {
351
ret = -errno;
352
goto error_close_dir;
353
}
354
355
errno = 0;
356
if (fscanf(sysfsfp, "%i", &ret) != 1) {
357
ret = errno ? -errno : -ENODATA;
358
if (fclose(sysfsfp))
359
perror("build_channel_array(): Failed to close file");
360
361
goto error_close_dir;
362
}
363
if (ret == 1)
364
(*counter)++;
365
366
if (fclose(sysfsfp)) {
367
ret = -errno;
368
goto error_close_dir;
369
}
370
371
}
372
373
*ci_array = malloc(sizeof(**ci_array) * (*counter));
374
if (!*ci_array) {
375
ret = -ENOMEM;
376
goto error_close_dir;
377
}
378
379
rewinddir(dp);
380
while (ent = readdir(dp), ent) {
381
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
382
"_en") == 0) {
383
int current_enabled = 0;
384
385
current = &(*ci_array)[count++];
386
ret = asprintf(&filename,
387
"%s/%s", scan_el_dir, ent->d_name);
388
if (ret < 0) {
389
ret = -ENOMEM;
390
/* decrement count to avoid freeing name */
391
count--;
392
goto error_cleanup_array;
393
}
394
395
sysfsfp = fopen(filename, "r");
396
free(filename);
397
if (!sysfsfp) {
398
ret = -errno;
399
count--;
400
goto error_cleanup_array;
401
}
402
403
errno = 0;
404
if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
405
ret = errno ? -errno : -ENODATA;
406
count--;
407
goto error_cleanup_array;
408
}
409
410
if (fclose(sysfsfp)) {
411
ret = -errno;
412
count--;
413
goto error_cleanup_array;
414
}
415
416
if (!current_enabled) {
417
count--;
418
continue;
419
}
420
421
current->scale = 1.0;
422
current->offset = 0;
423
current->name = strndup(ent->d_name,
424
strlen(ent->d_name) -
425
strlen("_en"));
426
if (!current->name) {
427
ret = -ENOMEM;
428
count--;
429
goto error_cleanup_array;
430
}
431
432
/* Get the generic and specific name elements */
433
ret = iioutils_break_up_name(current->name,
434
&current->generic_name);
435
if (ret) {
436
free(current->name);
437
count--;
438
goto error_cleanup_array;
439
}
440
441
ret = asprintf(&filename,
442
"%s/%s_index",
443
scan_el_dir,
444
current->name);
445
if (ret < 0) {
446
ret = -ENOMEM;
447
goto error_cleanup_array;
448
}
449
450
sysfsfp = fopen(filename, "r");
451
free(filename);
452
if (!sysfsfp) {
453
ret = -errno;
454
fprintf(stderr, "failed to open %s/%s_index\n",
455
scan_el_dir, current->name);
456
goto error_cleanup_array;
457
}
458
459
errno = 0;
460
if (fscanf(sysfsfp, "%u", &current->index) != 1) {
461
ret = errno ? -errno : -ENODATA;
462
if (fclose(sysfsfp))
463
perror("build_channel_array(): Failed to close file");
464
465
goto error_cleanup_array;
466
}
467
468
if (fclose(sysfsfp)) {
469
ret = -errno;
470
goto error_cleanup_array;
471
}
472
473
/* Find the scale */
474
ret = iioutils_get_param_float(&current->scale,
475
"scale",
476
device_dir,
477
current->name,
478
current->generic_name);
479
if ((ret < 0) && (ret != -ENOENT))
480
goto error_cleanup_array;
481
482
ret = iioutils_get_param_float(&current->offset,
483
"offset",
484
device_dir,
485
current->name,
486
current->generic_name);
487
if ((ret < 0) && (ret != -ENOENT))
488
goto error_cleanup_array;
489
490
ret = iioutils_get_type(&current->is_signed,
491
&current->bytes,
492
&current->bits_used,
493
&current->shift,
494
&current->mask,
495
&current->be,
496
device_dir,
497
buffer_idx,
498
current->name,
499
current->generic_name);
500
if (ret < 0)
501
goto error_cleanup_array;
502
}
503
}
504
505
if (closedir(dp) == -1) {
506
ret = -errno;
507
goto error_cleanup_array;
508
}
509
510
free(scan_el_dir);
511
/* reorder so that the array is in index order */
512
bsort_channel_array_by_index(*ci_array, *counter);
513
514
return 0;
515
516
error_cleanup_array:
517
for (i = count - 1; i >= 0; i--) {
518
free((*ci_array)[i].name);
519
free((*ci_array)[i].generic_name);
520
}
521
free(*ci_array);
522
*ci_array = NULL;
523
*counter = 0;
524
error_close_dir:
525
if (dp)
526
if (closedir(dp) == -1)
527
perror("build_channel_array(): Failed to close dir");
528
529
error_free_name:
530
free(scan_el_dir);
531
532
return ret;
533
}
534
535
static int calc_digits(int num)
536
{
537
int count = 0;
538
539
/* It takes a digit to represent zero */
540
if (!num)
541
return 1;
542
543
while (num != 0) {
544
num /= 10;
545
count++;
546
}
547
548
return count;
549
}
550
551
/**
552
* find_type_by_name() - function to match top level types by name
553
* @name: top level type instance name
554
* @type: the type of top level instance being searched
555
*
556
* Returns the device number of a matched IIO device on success, otherwise a
557
* negative error code.
558
* Typical types this is used for are device and trigger.
559
**/
560
int find_type_by_name(const char *name, const char *type)
561
{
562
const struct dirent *ent;
563
int number, numstrlen, ret;
564
565
FILE *namefp;
566
DIR *dp;
567
char thisname[IIO_MAX_NAME_LENGTH];
568
char *filename;
569
570
dp = opendir(iio_dir);
571
if (!dp) {
572
fprintf(stderr, "No industrialio devices available\n");
573
return -ENODEV;
574
}
575
576
while (ent = readdir(dp), ent) {
577
if (strcmp(ent->d_name, ".") != 0 &&
578
strcmp(ent->d_name, "..") != 0 &&
579
strlen(ent->d_name) > strlen(type) &&
580
strncmp(ent->d_name, type, strlen(type)) == 0) {
581
errno = 0;
582
ret = sscanf(ent->d_name + strlen(type), "%d", &number);
583
if (ret < 0) {
584
ret = -errno;
585
fprintf(stderr,
586
"failed to read element number\n");
587
goto error_close_dir;
588
} else if (ret != 1) {
589
ret = -EIO;
590
fprintf(stderr,
591
"failed to match element number\n");
592
goto error_close_dir;
593
}
594
595
numstrlen = calc_digits(number);
596
/* verify the next character is not a colon */
597
if (strncmp(ent->d_name + strlen(type) + numstrlen,
598
":", 1) != 0) {
599
filename = malloc(strlen(iio_dir) + strlen(type)
600
+ numstrlen + 6);
601
if (!filename) {
602
ret = -ENOMEM;
603
goto error_close_dir;
604
}
605
606
ret = sprintf(filename, "%s%s%d/name", iio_dir,
607
type, number);
608
if (ret < 0) {
609
free(filename);
610
goto error_close_dir;
611
}
612
613
namefp = fopen(filename, "r");
614
if (!namefp) {
615
free(filename);
616
continue;
617
}
618
619
free(filename);
620
errno = 0;
621
if (fscanf(namefp, "%s", thisname) != 1) {
622
ret = errno ? -errno : -ENODATA;
623
goto error_close_dir;
624
}
625
626
if (fclose(namefp)) {
627
ret = -errno;
628
goto error_close_dir;
629
}
630
631
if (strcmp(name, thisname) == 0) {
632
if (closedir(dp) == -1)
633
return -errno;
634
635
return number;
636
}
637
}
638
}
639
}
640
if (closedir(dp) == -1)
641
return -errno;
642
643
return -ENODEV;
644
645
error_close_dir:
646
if (closedir(dp) == -1)
647
perror("find_type_by_name(): Failed to close directory");
648
649
return ret;
650
}
651
652
static int _write_sysfs_int(const char *filename, const char *basedir, int val,
653
int verify)
654
{
655
int ret = 0;
656
FILE *sysfsfp;
657
int test;
658
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
659
660
if (!temp)
661
return -ENOMEM;
662
663
ret = sprintf(temp, "%s/%s", basedir, filename);
664
if (ret < 0)
665
goto error_free;
666
667
sysfsfp = fopen(temp, "w");
668
if (!sysfsfp) {
669
ret = -errno;
670
fprintf(stderr, "failed to open %s\n", temp);
671
goto error_free;
672
}
673
674
ret = fprintf(sysfsfp, "%d", val);
675
if (ret < 0) {
676
if (fclose(sysfsfp))
677
perror("_write_sysfs_int(): Failed to close dir");
678
679
goto error_free;
680
}
681
682
if (fclose(sysfsfp)) {
683
ret = -errno;
684
goto error_free;
685
}
686
687
if (verify) {
688
sysfsfp = fopen(temp, "r");
689
if (!sysfsfp) {
690
ret = -errno;
691
fprintf(stderr, "failed to open %s\n", temp);
692
goto error_free;
693
}
694
695
if (fscanf(sysfsfp, "%d", &test) != 1) {
696
ret = errno ? -errno : -ENODATA;
697
if (fclose(sysfsfp))
698
perror("_write_sysfs_int(): Failed to close dir");
699
700
goto error_free;
701
}
702
703
if (fclose(sysfsfp)) {
704
ret = -errno;
705
goto error_free;
706
}
707
708
if (test != val) {
709
fprintf(stderr,
710
"Possible failure in int write %d to %s/%s\n",
711
val, basedir, filename);
712
ret = -1;
713
}
714
}
715
716
error_free:
717
free(temp);
718
return ret;
719
}
720
721
/**
722
* write_sysfs_int() - write an integer value to a sysfs file
723
* @filename: name of the file to write to
724
* @basedir: the sysfs directory in which the file is to be found
725
* @val: integer value to write to file
726
*
727
* Returns a value >= 0 on success, otherwise a negative error code.
728
**/
729
int write_sysfs_int(const char *filename, const char *basedir, int val)
730
{
731
return _write_sysfs_int(filename, basedir, val, 0);
732
}
733
734
/**
735
* write_sysfs_int_and_verify() - write an integer value to a sysfs file
736
* and verify
737
* @filename: name of the file to write to
738
* @basedir: the sysfs directory in which the file is to be found
739
* @val: integer value to write to file
740
*
741
* Returns a value >= 0 on success, otherwise a negative error code.
742
**/
743
int write_sysfs_int_and_verify(const char *filename, const char *basedir,
744
int val)
745
{
746
return _write_sysfs_int(filename, basedir, val, 1);
747
}
748
749
static int _write_sysfs_string(const char *filename, const char *basedir,
750
const char *val, int verify)
751
{
752
int ret = 0;
753
FILE *sysfsfp;
754
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
755
756
if (!temp) {
757
fprintf(stderr, "Memory allocation failed\n");
758
return -ENOMEM;
759
}
760
761
ret = sprintf(temp, "%s/%s", basedir, filename);
762
if (ret < 0)
763
goto error_free;
764
765
sysfsfp = fopen(temp, "w");
766
if (!sysfsfp) {
767
ret = -errno;
768
fprintf(stderr, "Could not open %s\n", temp);
769
goto error_free;
770
}
771
772
ret = fprintf(sysfsfp, "%s", val);
773
if (ret < 0) {
774
if (fclose(sysfsfp))
775
perror("_write_sysfs_string(): Failed to close dir");
776
777
goto error_free;
778
}
779
780
if (fclose(sysfsfp)) {
781
ret = -errno;
782
goto error_free;
783
}
784
785
if (verify) {
786
sysfsfp = fopen(temp, "r");
787
if (!sysfsfp) {
788
ret = -errno;
789
fprintf(stderr, "Could not open file to verify\n");
790
goto error_free;
791
}
792
793
if (fscanf(sysfsfp, "%s", temp) != 1) {
794
ret = errno ? -errno : -ENODATA;
795
if (fclose(sysfsfp))
796
perror("_write_sysfs_string(): Failed to close dir");
797
798
goto error_free;
799
}
800
801
if (fclose(sysfsfp)) {
802
ret = -errno;
803
goto error_free;
804
}
805
806
if (strcmp(temp, val) != 0) {
807
fprintf(stderr,
808
"Possible failure in string write of %s "
809
"Should be %s written to %s/%s\n", temp, val,
810
basedir, filename);
811
ret = -1;
812
}
813
}
814
815
error_free:
816
free(temp);
817
818
return ret;
819
}
820
821
/**
822
* write_sysfs_string_and_verify() - string write, readback and verify
823
* @filename: name of file to write to
824
* @basedir: the sysfs directory in which the file is to be found
825
* @val: the string to write
826
*
827
* Returns a value >= 0 on success, otherwise a negative error code.
828
**/
829
int write_sysfs_string_and_verify(const char *filename, const char *basedir,
830
const char *val)
831
{
832
return _write_sysfs_string(filename, basedir, val, 1);
833
}
834
835
/**
836
* write_sysfs_string() - write string to a sysfs file
837
* @filename: name of file to write to
838
* @basedir: the sysfs directory in which the file is to be found
839
* @val: the string to write
840
*
841
* Returns a value >= 0 on success, otherwise a negative error code.
842
**/
843
int write_sysfs_string(const char *filename, const char *basedir,
844
const char *val)
845
{
846
return _write_sysfs_string(filename, basedir, val, 0);
847
}
848
849
/**
850
* read_sysfs_posint() - read an integer value from file
851
* @filename: name of file to read from
852
* @basedir: the sysfs directory in which the file is to be found
853
*
854
* Returns the read integer value >= 0 on success, otherwise a negative error
855
* code.
856
**/
857
int read_sysfs_posint(const char *filename, const char *basedir)
858
{
859
int ret;
860
FILE *sysfsfp;
861
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
862
863
if (!temp) {
864
fprintf(stderr, "Memory allocation failed");
865
return -ENOMEM;
866
}
867
868
ret = sprintf(temp, "%s/%s", basedir, filename);
869
if (ret < 0)
870
goto error_free;
871
872
sysfsfp = fopen(temp, "r");
873
if (!sysfsfp) {
874
ret = -errno;
875
goto error_free;
876
}
877
878
errno = 0;
879
if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
880
ret = errno ? -errno : -ENODATA;
881
if (fclose(sysfsfp))
882
perror("read_sysfs_posint(): Failed to close dir");
883
884
goto error_free;
885
}
886
887
if (fclose(sysfsfp))
888
ret = -errno;
889
890
error_free:
891
free(temp);
892
893
return ret;
894
}
895
896
/**
897
* read_sysfs_float() - read a float value from file
898
* @filename: name of file to read from
899
* @basedir: the sysfs directory in which the file is to be found
900
* @val: output the read float value
901
*
902
* Returns a value >= 0 on success, otherwise a negative error code.
903
**/
904
int read_sysfs_float(const char *filename, const char *basedir, float *val)
905
{
906
int ret = 0;
907
FILE *sysfsfp;
908
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
909
910
if (!temp) {
911
fprintf(stderr, "Memory allocation failed");
912
return -ENOMEM;
913
}
914
915
ret = sprintf(temp, "%s/%s", basedir, filename);
916
if (ret < 0)
917
goto error_free;
918
919
sysfsfp = fopen(temp, "r");
920
if (!sysfsfp) {
921
ret = -errno;
922
goto error_free;
923
}
924
925
errno = 0;
926
if (fscanf(sysfsfp, "%f\n", val) != 1) {
927
ret = errno ? -errno : -ENODATA;
928
if (fclose(sysfsfp))
929
perror("read_sysfs_float(): Failed to close dir");
930
931
goto error_free;
932
}
933
934
if (fclose(sysfsfp))
935
ret = -errno;
936
937
error_free:
938
free(temp);
939
940
return ret;
941
}
942
943
/**
944
* read_sysfs_string() - read a string from file
945
* @filename: name of file to read from
946
* @basedir: the sysfs directory in which the file is to be found
947
* @str: output the read string
948
*
949
* Returns a value >= 0 on success, otherwise a negative error code.
950
**/
951
int read_sysfs_string(const char *filename, const char *basedir, char *str)
952
{
953
int ret = 0;
954
FILE *sysfsfp;
955
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
956
957
if (!temp) {
958
fprintf(stderr, "Memory allocation failed");
959
return -ENOMEM;
960
}
961
962
ret = sprintf(temp, "%s/%s", basedir, filename);
963
if (ret < 0)
964
goto error_free;
965
966
sysfsfp = fopen(temp, "r");
967
if (!sysfsfp) {
968
ret = -errno;
969
goto error_free;
970
}
971
972
errno = 0;
973
if (fscanf(sysfsfp, "%s\n", str) != 1) {
974
ret = errno ? -errno : -ENODATA;
975
if (fclose(sysfsfp))
976
perror("read_sysfs_string(): Failed to close dir");
977
978
goto error_free;
979
}
980
981
if (fclose(sysfsfp))
982
ret = -errno;
983
984
error_free:
985
free(temp);
986
987
return ret;
988
}
989
990