iio_utils.c (21933B)
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 15const char *iio_dir = "/sys/bus/iio/devices/"; 16 17static 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 **/ 29int 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 **/ 86static 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 185error_close_sysfsfp: 186 if (sysfsfp) 187 if (fclose(sysfsfp)) 188 perror("iioutils_get_type(): Failed to close file"); 189 190error_free_filename: 191 if (filename) 192 free(filename); 193 194error_closedir: 195 if (closedir(dp) == -1) 196 perror("iioutils_get_type(): Failed to close directory"); 197 198error_free_builtname_generic: 199 free(builtname_generic); 200error_free_builtname: 201 free(builtname); 202error_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 **/ 218int 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 break; 268 } 269error_free_filename: 270 if (filename) 271 free(filename); 272 273error_closedir: 274 if (closedir(dp) == -1) 275 perror("iioutils_get_param_float(): Failed to close directory"); 276 277error_free_builtname_generic: 278 free(builtname_generic); 279error_free_builtname: 280 free(builtname); 281 282 return ret; 283} 284 285/** 286 * bsort_channel_array_by_index() - sort the array in index order 287 * @ci_array: the iio_channel_info array to be sorted 288 * @cnt: the amount of array elements 289 **/ 290 291void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt) 292{ 293 struct iio_channel_info temp; 294 int x, y; 295 296 for (x = 0; x < cnt; x++) 297 for (y = 0; y < (cnt - 1); y++) 298 if (ci_array[y].index > ci_array[y + 1].index) { 299 temp = ci_array[y + 1]; 300 ci_array[y + 1] = ci_array[y]; 301 ci_array[y] = temp; 302 } 303} 304 305/** 306 * build_channel_array() - function to figure out what channels are present 307 * @device_dir: the IIO device directory in sysfs 308 * @buffer_idx: the IIO buffer for this channel array 309 * @ci_array: output the resulting array of iio_channel_info 310 * @counter: output the amount of array elements 311 * 312 * Returns 0 on success, otherwise a negative error code. 313 **/ 314int build_channel_array(const char *device_dir, int buffer_idx, 315 struct iio_channel_info **ci_array, int *counter) 316{ 317 DIR *dp; 318 FILE *sysfsfp; 319 int count = 0, i; 320 struct iio_channel_info *current; 321 int ret; 322 const struct dirent *ent; 323 char *scan_el_dir; 324 char *filename; 325 326 *counter = 0; 327 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir, buffer_idx); 328 if (ret < 0) 329 return -ENOMEM; 330 331 dp = opendir(scan_el_dir); 332 if (!dp) { 333 ret = -errno; 334 goto error_free_name; 335 } 336 337 while (ent = readdir(dp), ent) 338 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), 339 "_en") == 0) { 340 ret = asprintf(&filename, 341 "%s/%s", scan_el_dir, ent->d_name); 342 if (ret < 0) { 343 ret = -ENOMEM; 344 goto error_close_dir; 345 } 346 347 sysfsfp = fopen(filename, "r"); 348 if (!sysfsfp) { 349 ret = -errno; 350 free(filename); 351 goto error_close_dir; 352 } 353 354 errno = 0; 355 if (fscanf(sysfsfp, "%i", &ret) != 1) { 356 ret = errno ? -errno : -ENODATA; 357 if (fclose(sysfsfp)) 358 perror("build_channel_array(): Failed to close file"); 359 360 free(filename); 361 goto error_close_dir; 362 } 363 if (ret == 1) 364 (*counter)++; 365 366 if (fclose(sysfsfp)) { 367 ret = -errno; 368 free(filename); 369 goto error_close_dir; 370 } 371 372 free(filename); 373 } 374 375 *ci_array = malloc(sizeof(**ci_array) * (*counter)); 376 if (!*ci_array) { 377 ret = -ENOMEM; 378 goto error_close_dir; 379 } 380 381 seekdir(dp, 0); 382 while (ent = readdir(dp), ent) { 383 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), 384 "_en") == 0) { 385 int current_enabled = 0; 386 387 current = &(*ci_array)[count++]; 388 ret = asprintf(&filename, 389 "%s/%s", scan_el_dir, ent->d_name); 390 if (ret < 0) { 391 ret = -ENOMEM; 392 /* decrement count to avoid freeing name */ 393 count--; 394 goto error_cleanup_array; 395 } 396 397 sysfsfp = fopen(filename, "r"); 398 if (!sysfsfp) { 399 ret = -errno; 400 free(filename); 401 count--; 402 goto error_cleanup_array; 403 } 404 405 errno = 0; 406 if (fscanf(sysfsfp, "%i", ¤t_enabled) != 1) { 407 ret = errno ? -errno : -ENODATA; 408 free(filename); 409 count--; 410 goto error_cleanup_array; 411 } 412 413 if (fclose(sysfsfp)) { 414 ret = -errno; 415 free(filename); 416 count--; 417 goto error_cleanup_array; 418 } 419 420 if (!current_enabled) { 421 free(filename); 422 count--; 423 continue; 424 } 425 426 current->scale = 1.0; 427 current->offset = 0; 428 current->name = strndup(ent->d_name, 429 strlen(ent->d_name) - 430 strlen("_en")); 431 if (!current->name) { 432 free(filename); 433 ret = -ENOMEM; 434 count--; 435 goto error_cleanup_array; 436 } 437 438 /* Get the generic and specific name elements */ 439 ret = iioutils_break_up_name(current->name, 440 ¤t->generic_name); 441 if (ret) { 442 free(filename); 443 free(current->name); 444 count--; 445 goto error_cleanup_array; 446 } 447 448 ret = asprintf(&filename, 449 "%s/%s_index", 450 scan_el_dir, 451 current->name); 452 if (ret < 0) { 453 free(filename); 454 ret = -ENOMEM; 455 goto error_cleanup_array; 456 } 457 458 sysfsfp = fopen(filename, "r"); 459 if (!sysfsfp) { 460 ret = -errno; 461 fprintf(stderr, "failed to open %s\n", 462 filename); 463 free(filename); 464 goto error_cleanup_array; 465 } 466 467 errno = 0; 468 if (fscanf(sysfsfp, "%u", ¤t->index) != 1) { 469 ret = errno ? -errno : -ENODATA; 470 if (fclose(sysfsfp)) 471 perror("build_channel_array(): Failed to close file"); 472 473 free(filename); 474 goto error_cleanup_array; 475 } 476 477 if (fclose(sysfsfp)) { 478 ret = -errno; 479 free(filename); 480 goto error_cleanup_array; 481 } 482 483 free(filename); 484 /* Find the scale */ 485 ret = iioutils_get_param_float(¤t->scale, 486 "scale", 487 device_dir, 488 current->name, 489 current->generic_name); 490 if ((ret < 0) && (ret != -ENOENT)) 491 goto error_cleanup_array; 492 493 ret = iioutils_get_param_float(¤t->offset, 494 "offset", 495 device_dir, 496 current->name, 497 current->generic_name); 498 if ((ret < 0) && (ret != -ENOENT)) 499 goto error_cleanup_array; 500 501 ret = iioutils_get_type(¤t->is_signed, 502 ¤t->bytes, 503 ¤t->bits_used, 504 ¤t->shift, 505 ¤t->mask, 506 ¤t->be, 507 device_dir, 508 buffer_idx, 509 current->name, 510 current->generic_name); 511 if (ret < 0) 512 goto error_cleanup_array; 513 } 514 } 515 516 if (closedir(dp) == -1) { 517 ret = -errno; 518 goto error_cleanup_array; 519 } 520 521 free(scan_el_dir); 522 /* reorder so that the array is in index order */ 523 bsort_channel_array_by_index(*ci_array, *counter); 524 525 return 0; 526 527error_cleanup_array: 528 for (i = count - 1; i >= 0; i--) { 529 free((*ci_array)[i].name); 530 free((*ci_array)[i].generic_name); 531 } 532 free(*ci_array); 533 *ci_array = NULL; 534 *counter = 0; 535error_close_dir: 536 if (dp) 537 if (closedir(dp) == -1) 538 perror("build_channel_array(): Failed to close dir"); 539 540error_free_name: 541 free(scan_el_dir); 542 543 return ret; 544} 545 546static int calc_digits(int num) 547{ 548 int count = 0; 549 550 while (num != 0) { 551 num /= 10; 552 count++; 553 } 554 555 return count; 556} 557 558/** 559 * find_type_by_name() - function to match top level types by name 560 * @name: top level type instance name 561 * @type: the type of top level instance being searched 562 * 563 * Returns the device number of a matched IIO device on success, otherwise a 564 * negative error code. 565 * Typical types this is used for are device and trigger. 566 **/ 567int find_type_by_name(const char *name, const char *type) 568{ 569 const struct dirent *ent; 570 int number, numstrlen, ret; 571 572 FILE *namefp; 573 DIR *dp; 574 char thisname[IIO_MAX_NAME_LENGTH]; 575 char *filename; 576 577 dp = opendir(iio_dir); 578 if (!dp) { 579 fprintf(stderr, "No industrialio devices available\n"); 580 return -ENODEV; 581 } 582 583 while (ent = readdir(dp), ent) { 584 if (strcmp(ent->d_name, ".") != 0 && 585 strcmp(ent->d_name, "..") != 0 && 586 strlen(ent->d_name) > strlen(type) && 587 strncmp(ent->d_name, type, strlen(type)) == 0) { 588 errno = 0; 589 ret = sscanf(ent->d_name + strlen(type), "%d", &number); 590 if (ret < 0) { 591 ret = -errno; 592 fprintf(stderr, 593 "failed to read element number\n"); 594 goto error_close_dir; 595 } else if (ret != 1) { 596 ret = -EIO; 597 fprintf(stderr, 598 "failed to match element number\n"); 599 goto error_close_dir; 600 } 601 602 numstrlen = calc_digits(number); 603 /* verify the next character is not a colon */ 604 if (strncmp(ent->d_name + strlen(type) + numstrlen, 605 ":", 1) != 0) { 606 filename = malloc(strlen(iio_dir) + strlen(type) 607 + numstrlen + 6); 608 if (!filename) { 609 ret = -ENOMEM; 610 goto error_close_dir; 611 } 612 613 ret = sprintf(filename, "%s%s%d/name", iio_dir, 614 type, number); 615 if (ret < 0) { 616 free(filename); 617 goto error_close_dir; 618 } 619 620 namefp = fopen(filename, "r"); 621 if (!namefp) { 622 free(filename); 623 continue; 624 } 625 626 free(filename); 627 errno = 0; 628 if (fscanf(namefp, "%s", thisname) != 1) { 629 ret = errno ? -errno : -ENODATA; 630 goto error_close_dir; 631 } 632 633 if (fclose(namefp)) { 634 ret = -errno; 635 goto error_close_dir; 636 } 637 638 if (strcmp(name, thisname) == 0) { 639 if (closedir(dp) == -1) 640 return -errno; 641 642 return number; 643 } 644 } 645 } 646 } 647 if (closedir(dp) == -1) 648 return -errno; 649 650 return -ENODEV; 651 652error_close_dir: 653 if (closedir(dp) == -1) 654 perror("find_type_by_name(): Failed to close directory"); 655 656 return ret; 657} 658 659static int _write_sysfs_int(const char *filename, const char *basedir, int val, 660 int verify) 661{ 662 int ret = 0; 663 FILE *sysfsfp; 664 int test; 665 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 666 667 if (!temp) 668 return -ENOMEM; 669 670 ret = sprintf(temp, "%s/%s", basedir, filename); 671 if (ret < 0) 672 goto error_free; 673 674 sysfsfp = fopen(temp, "w"); 675 if (!sysfsfp) { 676 ret = -errno; 677 fprintf(stderr, "failed to open %s\n", temp); 678 goto error_free; 679 } 680 681 ret = fprintf(sysfsfp, "%d", val); 682 if (ret < 0) { 683 if (fclose(sysfsfp)) 684 perror("_write_sysfs_int(): Failed to close dir"); 685 686 goto error_free; 687 } 688 689 if (fclose(sysfsfp)) { 690 ret = -errno; 691 goto error_free; 692 } 693 694 if (verify) { 695 sysfsfp = fopen(temp, "r"); 696 if (!sysfsfp) { 697 ret = -errno; 698 fprintf(stderr, "failed to open %s\n", temp); 699 goto error_free; 700 } 701 702 if (fscanf(sysfsfp, "%d", &test) != 1) { 703 ret = errno ? -errno : -ENODATA; 704 if (fclose(sysfsfp)) 705 perror("_write_sysfs_int(): Failed to close dir"); 706 707 goto error_free; 708 } 709 710 if (fclose(sysfsfp)) { 711 ret = -errno; 712 goto error_free; 713 } 714 715 if (test != val) { 716 fprintf(stderr, 717 "Possible failure in int write %d to %s/%s\n", 718 val, basedir, filename); 719 ret = -1; 720 } 721 } 722 723error_free: 724 free(temp); 725 return ret; 726} 727 728/** 729 * write_sysfs_int() - write an integer value to a sysfs file 730 * @filename: name of the file to write to 731 * @basedir: the sysfs directory in which the file is to be found 732 * @val: integer value to write to file 733 * 734 * Returns a value >= 0 on success, otherwise a negative error code. 735 **/ 736int write_sysfs_int(const char *filename, const char *basedir, int val) 737{ 738 return _write_sysfs_int(filename, basedir, val, 0); 739} 740 741/** 742 * write_sysfs_int_and_verify() - write an integer value to a sysfs file 743 * and verify 744 * @filename: name of the file to write to 745 * @basedir: the sysfs directory in which the file is to be found 746 * @val: integer value to write to file 747 * 748 * Returns a value >= 0 on success, otherwise a negative error code. 749 **/ 750int write_sysfs_int_and_verify(const char *filename, const char *basedir, 751 int val) 752{ 753 return _write_sysfs_int(filename, basedir, val, 1); 754} 755 756static int _write_sysfs_string(const char *filename, const char *basedir, 757 const char *val, int verify) 758{ 759 int ret = 0; 760 FILE *sysfsfp; 761 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 762 763 if (!temp) { 764 fprintf(stderr, "Memory allocation failed\n"); 765 return -ENOMEM; 766 } 767 768 ret = sprintf(temp, "%s/%s", basedir, filename); 769 if (ret < 0) 770 goto error_free; 771 772 sysfsfp = fopen(temp, "w"); 773 if (!sysfsfp) { 774 ret = -errno; 775 fprintf(stderr, "Could not open %s\n", temp); 776 goto error_free; 777 } 778 779 ret = fprintf(sysfsfp, "%s", val); 780 if (ret < 0) { 781 if (fclose(sysfsfp)) 782 perror("_write_sysfs_string(): Failed to close dir"); 783 784 goto error_free; 785 } 786 787 if (fclose(sysfsfp)) { 788 ret = -errno; 789 goto error_free; 790 } 791 792 if (verify) { 793 sysfsfp = fopen(temp, "r"); 794 if (!sysfsfp) { 795 ret = -errno; 796 fprintf(stderr, "Could not open file to verify\n"); 797 goto error_free; 798 } 799 800 if (fscanf(sysfsfp, "%s", temp) != 1) { 801 ret = errno ? -errno : -ENODATA; 802 if (fclose(sysfsfp)) 803 perror("_write_sysfs_string(): Failed to close dir"); 804 805 goto error_free; 806 } 807 808 if (fclose(sysfsfp)) { 809 ret = -errno; 810 goto error_free; 811 } 812 813 if (strcmp(temp, val) != 0) { 814 fprintf(stderr, 815 "Possible failure in string write of %s " 816 "Should be %s written to %s/%s\n", temp, val, 817 basedir, filename); 818 ret = -1; 819 } 820 } 821 822error_free: 823 free(temp); 824 825 return ret; 826} 827 828/** 829 * write_sysfs_string_and_verify() - string write, readback and verify 830 * @filename: name of file to write to 831 * @basedir: the sysfs directory in which the file is to be found 832 * @val: the string to write 833 * 834 * Returns a value >= 0 on success, otherwise a negative error code. 835 **/ 836int write_sysfs_string_and_verify(const char *filename, const char *basedir, 837 const char *val) 838{ 839 return _write_sysfs_string(filename, basedir, val, 1); 840} 841 842/** 843 * write_sysfs_string() - write string to a sysfs file 844 * @filename: name of file to write to 845 * @basedir: the sysfs directory in which the file is to be found 846 * @val: the string to write 847 * 848 * Returns a value >= 0 on success, otherwise a negative error code. 849 **/ 850int write_sysfs_string(const char *filename, const char *basedir, 851 const char *val) 852{ 853 return _write_sysfs_string(filename, basedir, val, 0); 854} 855 856/** 857 * read_sysfs_posint() - read an integer value from file 858 * @filename: name of file to read from 859 * @basedir: the sysfs directory in which the file is to be found 860 * 861 * Returns the read integer value >= 0 on success, otherwise a negative error 862 * code. 863 **/ 864int read_sysfs_posint(const char *filename, const char *basedir) 865{ 866 int ret; 867 FILE *sysfsfp; 868 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 869 870 if (!temp) { 871 fprintf(stderr, "Memory allocation failed"); 872 return -ENOMEM; 873 } 874 875 ret = sprintf(temp, "%s/%s", basedir, filename); 876 if (ret < 0) 877 goto error_free; 878 879 sysfsfp = fopen(temp, "r"); 880 if (!sysfsfp) { 881 ret = -errno; 882 goto error_free; 883 } 884 885 errno = 0; 886 if (fscanf(sysfsfp, "%d\n", &ret) != 1) { 887 ret = errno ? -errno : -ENODATA; 888 if (fclose(sysfsfp)) 889 perror("read_sysfs_posint(): Failed to close dir"); 890 891 goto error_free; 892 } 893 894 if (fclose(sysfsfp)) 895 ret = -errno; 896 897error_free: 898 free(temp); 899 900 return ret; 901} 902 903/** 904 * read_sysfs_float() - read a float value from file 905 * @filename: name of file to read from 906 * @basedir: the sysfs directory in which the file is to be found 907 * @val: output the read float value 908 * 909 * Returns a value >= 0 on success, otherwise a negative error code. 910 **/ 911int read_sysfs_float(const char *filename, const char *basedir, float *val) 912{ 913 int ret = 0; 914 FILE *sysfsfp; 915 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 916 917 if (!temp) { 918 fprintf(stderr, "Memory allocation failed"); 919 return -ENOMEM; 920 } 921 922 ret = sprintf(temp, "%s/%s", basedir, filename); 923 if (ret < 0) 924 goto error_free; 925 926 sysfsfp = fopen(temp, "r"); 927 if (!sysfsfp) { 928 ret = -errno; 929 goto error_free; 930 } 931 932 errno = 0; 933 if (fscanf(sysfsfp, "%f\n", val) != 1) { 934 ret = errno ? -errno : -ENODATA; 935 if (fclose(sysfsfp)) 936 perror("read_sysfs_float(): Failed to close dir"); 937 938 goto error_free; 939 } 940 941 if (fclose(sysfsfp)) 942 ret = -errno; 943 944error_free: 945 free(temp); 946 947 return ret; 948} 949 950/** 951 * read_sysfs_string() - read a string from file 952 * @filename: name of file to read from 953 * @basedir: the sysfs directory in which the file is to be found 954 * @str: output the read string 955 * 956 * Returns a value >= 0 on success, otherwise a negative error code. 957 **/ 958int read_sysfs_string(const char *filename, const char *basedir, char *str) 959{ 960 int ret = 0; 961 FILE *sysfsfp; 962 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 963 964 if (!temp) { 965 fprintf(stderr, "Memory allocation failed"); 966 return -ENOMEM; 967 } 968 969 ret = sprintf(temp, "%s/%s", basedir, filename); 970 if (ret < 0) 971 goto error_free; 972 973 sysfsfp = fopen(temp, "r"); 974 if (!sysfsfp) { 975 ret = -errno; 976 goto error_free; 977 } 978 979 errno = 0; 980 if (fscanf(sysfsfp, "%s\n", str) != 1) { 981 ret = errno ? -errno : -ENODATA; 982 if (fclose(sysfsfp)) 983 perror("read_sysfs_string(): Failed to close dir"); 984 985 goto error_free; 986 } 987 988 if (fclose(sysfsfp)) 989 ret = -errno; 990 991error_free: 992 free(temp); 993 994 return ret; 995}