1 /* 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 */ 9 #include <string.h> 10 #include <stdlib.h> 11 #include <stdio.h> 12 #include <stdint.h> 13 #include <dirent.h> 14 #include <errno.h> 15 #include <ctype.h> 16 #include "iio_utils.h" 17 18 const char *iio_dir = "/sys/bus/iio/devices/"; 19 20 static char * const iio_direction[] = { 21 "in", 22 "out", 23 }; 24 25 /** 26 * 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 29 * 30 * Returns 0 on success, or a negative error code if string extraction failed. 31 **/ 32 int iioutils_break_up_name(const char *full_name, char **generic_name) 33 { 34 char *current; 35 char *w, *r; 36 char *working, *prefix = ""; 37 int i, ret; 38 39 for (i = 0; i < ARRAY_SIZE(iio_direction); i++) 40 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); 47 if (!current) 48 return -ENOMEM; 49 50 working = strtok(current, "_\0"); 51 if (!working) { 52 free(current); 53 return -EINVAL; 54 } 55 56 w = working; 57 r = working; 58 59 while (*r != '\0') { 60 if (!isdigit(*r)) { 61 *w = *r; 62 w++; 63 } 64 65 r++; 66 } 67 *w = '\0'; 68 ret = asprintf(generic_name, "%s_%s", prefix, working); 69 free(current); 70 71 return (ret == -1) ? -ENOMEM : 0; 72 } 73 74 /** 75 * 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 78 * @bits_used: output number of valid bits of data 79 * @shift: output amount of bits to shift right data before applying bit mask 80 * @mask: output a bit mask for the raw data 81 * @be: output if data in big endian 82 * @device_dir: the IIO device directory 83 * @name: the channel name 84 * @generic_name: the channel type name 85 * 86 * Returns a value >= 0 on success, otherwise a negative error code. 87 **/ 88 int 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) 92 { 93 FILE *sysfsfp; 94 int ret; 95 DIR *dp; 96 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0; 97 char signchar, endianchar; 98 unsigned padint; 99 const struct dirent *ent; 100 101 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir); 102 if (ret < 0) 103 return -ENOMEM; 104 105 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); 117 if (!dp) { 118 ret = -errno; 119 goto error_free_builtname_generic; 120 } 121 122 ret = -ENOENT; 123 while (ent = readdir(dp), ent) 124 if ((strcmp(builtname, ent->d_name) == 0) || 125 (strcmp(builtname_generic, ent->d_name) == 0)) { 126 ret = asprintf(&filename, 127 "%s/%s", scan_el_dir, ent->d_name); 128 if (ret < 0) { 129 ret = -ENOMEM; 130 goto error_closedir; 131 } 132 133 sysfsfp = fopen(filename, "r"); 134 if (!sysfsfp) { 135 ret = -errno; 136 fprintf(stderr, "failed to open %s\n", 137 filename); 138 goto error_free_filename; 139 } 140 141 ret = fscanf(sysfsfp, 142 "%ce:%c%u/%u>>%u", 143 &endianchar, 144 &signchar, 145 bits_used, 146 &padint, shift); 147 if (ret < 0) { 148 ret = -errno; 149 fprintf(stderr, 150 "failed to pass scan type description\n"); 151 goto error_close_sysfsfp; 152 } else if (ret != 5) { 153 ret = -EIO; 154 fprintf(stderr, 155 "scan type description didn't match\n"); 156 goto error_close_sysfsfp; 157 } 158 159 *be = (endianchar == 'b'); 160 *bytes = padint / 8; 161 if (*bits_used == 64) 162 *mask = ~0; 163 else 164 *mask = (1ULL << *bits_used) - 1; 165 166 *is_signed = (signchar == 's'); 167 if (fclose(sysfsfp)) { 168 ret = -errno; 169 fprintf(stderr, "Failed to close %s\n", 170 filename); 171 goto error_free_filename; 172 } 173 174 sysfsfp = 0; 175 free(filename); 176 filename = 0; 177 178 /* 179 * Avoid having a more generic entry overwriting 180 * the settings. 181 */ 182 if (strcmp(builtname, ent->d_name) == 0) 183 break; 184 } 185 186 error_close_sysfsfp: 187 if (sysfsfp) 188 if (fclose(sysfsfp)) 189 perror("iioutils_get_type(): Failed to close file"); 190 191 error_free_filename: 192 if (filename) 193 free(filename); 194 195 error_closedir: 196 if (closedir(dp) == -1) 197 perror("iioutils_get_type(): Failed to close directory"); 198 199 error_free_builtname_generic: 200 free(builtname_generic); 201 error_free_builtname: 202 free(builtname); 203 error_free_scan_el_dir: 204 free(scan_el_dir); 205 206 return ret; 207 } 208 209 /** 210 * iioutils_get_param_float() - read a float value from a channel parameter 211 * @output: output the float value 212 * @param_name: the parameter name to read 213 * @device_dir: the IIO device directory in sysfs 214 * @name: the channel name 215 * @generic_name: the channel type name 216 * 217 * Returns a value >= 0 on success, otherwise a negative error code. 218 **/ 219 int iioutils_get_param_float(float *output, const char *param_name, 220 const char *device_dir, const char *name, 221 const char *generic_name) 222 { 223 FILE *sysfsfp; 224 int ret; 225 DIR *dp; 226 char *builtname, *builtname_generic; 227 char *filename = NULL; 228 const struct dirent *ent; 229 230 ret = asprintf(&builtname, "%s_%s", name, param_name); 231 if (ret < 0) 232 return -ENOMEM; 233 234 ret = asprintf(&builtname_generic, 235 "%s_%s", generic_name, param_name); 236 if (ret < 0) { 237 ret = -ENOMEM; 238 goto error_free_builtname; 239 } 240 241 dp = opendir(device_dir); 242 if (!dp) { 243 ret = -errno; 244 goto error_free_builtname_generic; 245 } 246 247 ret = -ENOENT; 248 while (ent = readdir(dp), ent) 249 if ((strcmp(builtname, ent->d_name) == 0) || 250 (strcmp(builtname_generic, ent->d_name) == 0)) { 251 ret = asprintf(&filename, 252 "%s/%s", device_dir, ent->d_name); 253 if (ret < 0) { 254 ret = -ENOMEM; 255 goto error_closedir; 256 } 257 258 sysfsfp = fopen(filename, "r"); 259 if (!sysfsfp) { 260 ret = -errno; 261 goto error_free_filename; 262 } 263 264 errno = 0; 265 if (fscanf(sysfsfp, "%f", output) != 1) 266 ret = errno ? -errno : -ENODATA; 267 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 * @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 **/ 314 int build_channel_array(const char *device_dir, 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); 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 current->name, 509 current->generic_name); 510 if (ret < 0) 511 goto error_cleanup_array; 512 } 513 } 514 515 if (closedir(dp) == -1) { 516 ret = -errno; 517 goto error_cleanup_array; 518 } 519 520 free(scan_el_dir); 521 /* reorder so that the array is in index order */ 522 bsort_channel_array_by_index(*ci_array, *counter); 523 524 return 0; 525 526 error_cleanup_array: 527 for (i = count - 1; i >= 0; i--) { 528 free((*ci_array)[i].name); 529 free((*ci_array)[i].generic_name); 530 } 531 free(*ci_array); 532 *ci_array = NULL; 533 *counter = 0; 534 error_close_dir: 535 if (dp) 536 if (closedir(dp) == -1) 537 perror("build_channel_array(): Failed to close dir"); 538 539 error_free_name: 540 free(scan_el_dir); 541 542 return ret; 543 } 544 545 static int calc_digits(int num) 546 { 547 int count = 0; 548 549 while (num != 0) { 550 num /= 10; 551 count++; 552 } 553 554 return count; 555 } 556 557 /** 558 * find_type_by_name() - function to match top level types by name 559 * @name: top level type instance name 560 * @type: the type of top level instance being searched 561 * 562 * Returns the device number of a matched IIO device on success, otherwise a 563 * negative error code. 564 * Typical types this is used for are device and trigger. 565 **/ 566 int find_type_by_name(const char *name, const char *type) 567 { 568 const struct dirent *ent; 569 int number, numstrlen, ret; 570 571 FILE *namefp; 572 DIR *dp; 573 char thisname[IIO_MAX_NAME_LENGTH]; 574 char *filename; 575 576 dp = opendir(iio_dir); 577 if (!dp) { 578 fprintf(stderr, "No industrialio devices available\n"); 579 return -ENODEV; 580 } 581 582 while (ent = readdir(dp), ent) { 583 if (strcmp(ent->d_name, ".") != 0 && 584 strcmp(ent->d_name, "..") != 0 && 585 strlen(ent->d_name) > strlen(type) && 586 strncmp(ent->d_name, type, strlen(type)) == 0) { 587 errno = 0; 588 ret = sscanf(ent->d_name + strlen(type), "%d", &number); 589 if (ret < 0) { 590 ret = -errno; 591 fprintf(stderr, 592 "failed to read element number\n"); 593 goto error_close_dir; 594 } else if (ret != 1) { 595 ret = -EIO; 596 fprintf(stderr, 597 "failed to match element number\n"); 598 goto error_close_dir; 599 } 600 601 numstrlen = calc_digits(number); 602 /* verify the next character is not a colon */ 603 if (strncmp(ent->d_name + strlen(type) + numstrlen, 604 ":", 1) != 0) { 605 filename = malloc(strlen(iio_dir) + strlen(type) 606 + numstrlen + 6); 607 if (!filename) { 608 ret = -ENOMEM; 609 goto error_close_dir; 610 } 611 612 ret = sprintf(filename, "%s%s%d/name", iio_dir, 613 type, number); 614 if (ret < 0) { 615 free(filename); 616 goto error_close_dir; 617 } 618 619 namefp = fopen(filename, "r"); 620 if (!namefp) { 621 free(filename); 622 continue; 623 } 624 625 free(filename); 626 errno = 0; 627 if (fscanf(namefp, "%s", thisname) != 1) { 628 ret = errno ? -errno : -ENODATA; 629 goto error_close_dir; 630 } 631 632 if (fclose(namefp)) { 633 ret = -errno; 634 goto error_close_dir; 635 } 636 637 if (strcmp(name, thisname) == 0) { 638 if (closedir(dp) == -1) 639 return -errno; 640 641 return number; 642 } 643 } 644 } 645 } 646 if (closedir(dp) == -1) 647 return -errno; 648 649 return -ENODEV; 650 651 error_close_dir: 652 if (closedir(dp) == -1) 653 perror("find_type_by_name(): Failed to close directory"); 654 655 return ret; 656 } 657 658 static int _write_sysfs_int(const char *filename, const char *basedir, int val, 659 int verify) 660 { 661 int ret = 0; 662 FILE *sysfsfp; 663 int test; 664 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 665 666 if (!temp) 667 return -ENOMEM; 668 669 ret = sprintf(temp, "%s/%s", basedir, filename); 670 if (ret < 0) 671 goto error_free; 672 673 sysfsfp = fopen(temp, "w"); 674 if (!sysfsfp) { 675 ret = -errno; 676 fprintf(stderr, "failed to open %s\n", temp); 677 goto error_free; 678 } 679 680 ret = fprintf(sysfsfp, "%d", val); 681 if (ret < 0) { 682 if (fclose(sysfsfp)) 683 perror("_write_sysfs_int(): Failed to close dir"); 684 685 goto error_free; 686 } 687 688 if (fclose(sysfsfp)) { 689 ret = -errno; 690 goto error_free; 691 } 692 693 if (verify) { 694 sysfsfp = fopen(temp, "r"); 695 if (!sysfsfp) { 696 ret = -errno; 697 fprintf(stderr, "failed to open %s\n", temp); 698 goto error_free; 699 } 700 701 if (fscanf(sysfsfp, "%d", &test) != 1) { 702 ret = errno ? -errno : -ENODATA; 703 if (fclose(sysfsfp)) 704 perror("_write_sysfs_int(): Failed to close dir"); 705 706 goto error_free; 707 } 708 709 if (fclose(sysfsfp)) { 710 ret = -errno; 711 goto error_free; 712 } 713 714 if (test != val) { 715 fprintf(stderr, 716 "Possible failure in int write %d to %s/%s\n", 717 val, basedir, filename); 718 ret = -1; 719 } 720 } 721 722 error_free: 723 free(temp); 724 return ret; 725 } 726 727 /** 728 * write_sysfs_int() - write an integer value to a sysfs file 729 * @filename: name of the file to write to 730 * @basedir: the sysfs directory in which the file is to be found 731 * @val: integer value to write to file 732 * 733 * Returns a value >= 0 on success, otherwise a negative error code. 734 **/ 735 int write_sysfs_int(const char *filename, const char *basedir, int val) 736 { 737 return _write_sysfs_int(filename, basedir, val, 0); 738 } 739 740 /** 741 * write_sysfs_int_and_verify() - write an integer value to a sysfs file 742 * and verify 743 * @filename: name of the file to write to 744 * @basedir: the sysfs directory in which the file is to be found 745 * @val: integer value to write to file 746 * 747 * Returns a value >= 0 on success, otherwise a negative error code. 748 **/ 749 int write_sysfs_int_and_verify(const char *filename, const char *basedir, 750 int val) 751 { 752 return _write_sysfs_int(filename, basedir, val, 1); 753 } 754 755 static int _write_sysfs_string(const char *filename, const char *basedir, 756 const char *val, int verify) 757 { 758 int ret = 0; 759 FILE *sysfsfp; 760 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 761 762 if (!temp) { 763 fprintf(stderr, "Memory allocation failed\n"); 764 return -ENOMEM; 765 } 766 767 ret = sprintf(temp, "%s/%s", basedir, filename); 768 if (ret < 0) 769 goto error_free; 770 771 sysfsfp = fopen(temp, "w"); 772 if (!sysfsfp) { 773 ret = -errno; 774 fprintf(stderr, "Could not open %s\n", temp); 775 goto error_free; 776 } 777 778 ret = fprintf(sysfsfp, "%s", val); 779 if (ret < 0) { 780 if (fclose(sysfsfp)) 781 perror("_write_sysfs_string(): Failed to close dir"); 782 783 goto error_free; 784 } 785 786 if (fclose(sysfsfp)) { 787 ret = -errno; 788 goto error_free; 789 } 790 791 if (verify) { 792 sysfsfp = fopen(temp, "r"); 793 if (!sysfsfp) { 794 ret = -errno; 795 fprintf(stderr, "Could not open file to verify\n"); 796 goto error_free; 797 } 798 799 if (fscanf(sysfsfp, "%s", temp) != 1) { 800 ret = errno ? -errno : -ENODATA; 801 if (fclose(sysfsfp)) 802 perror("_write_sysfs_string(): Failed to close dir"); 803 804 goto error_free; 805 } 806 807 if (fclose(sysfsfp)) { 808 ret = -errno; 809 goto error_free; 810 } 811 812 if (strcmp(temp, val) != 0) { 813 fprintf(stderr, 814 "Possible failure in string write of %s " 815 "Should be %s written to %s/%s\n", temp, val, 816 basedir, filename); 817 ret = -1; 818 } 819 } 820 821 error_free: 822 free(temp); 823 824 return ret; 825 } 826 827 /** 828 * write_sysfs_string_and_verify() - string write, readback and verify 829 * @filename: name of file to write to 830 * @basedir: the sysfs directory in which the file is to be found 831 * @val: the string to write 832 * 833 * Returns a value >= 0 on success, otherwise a negative error code. 834 **/ 835 int write_sysfs_string_and_verify(const char *filename, const char *basedir, 836 const char *val) 837 { 838 return _write_sysfs_string(filename, basedir, val, 1); 839 } 840 841 /** 842 * write_sysfs_string() - write string to a sysfs file 843 * @filename: name of file to write to 844 * @basedir: the sysfs directory in which the file is to be found 845 * @val: the string to write 846 * 847 * Returns a value >= 0 on success, otherwise a negative error code. 848 **/ 849 int write_sysfs_string(const char *filename, const char *basedir, 850 const char *val) 851 { 852 return _write_sysfs_string(filename, basedir, val, 0); 853 } 854 855 /** 856 * read_sysfs_posint() - read an integer value from file 857 * @filename: name of file to read from 858 * @basedir: the sysfs directory in which the file is to be found 859 * 860 * Returns the read integer value >= 0 on success, otherwise a negative error 861 * code. 862 **/ 863 int read_sysfs_posint(const char *filename, const char *basedir) 864 { 865 int ret; 866 FILE *sysfsfp; 867 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 868 869 if (!temp) { 870 fprintf(stderr, "Memory allocation failed"); 871 return -ENOMEM; 872 } 873 874 ret = sprintf(temp, "%s/%s", basedir, filename); 875 if (ret < 0) 876 goto error_free; 877 878 sysfsfp = fopen(temp, "r"); 879 if (!sysfsfp) { 880 ret = -errno; 881 goto error_free; 882 } 883 884 errno = 0; 885 if (fscanf(sysfsfp, "%d\n", &ret) != 1) { 886 ret = errno ? -errno : -ENODATA; 887 if (fclose(sysfsfp)) 888 perror("read_sysfs_posint(): Failed to close dir"); 889 890 goto error_free; 891 } 892 893 if (fclose(sysfsfp)) 894 ret = -errno; 895 896 error_free: 897 free(temp); 898 899 return ret; 900 } 901 902 /** 903 * read_sysfs_float() - read a float value from file 904 * @filename: name of file to read from 905 * @basedir: the sysfs directory in which the file is to be found 906 * @val: output the read float value 907 * 908 * Returns a value >= 0 on success, otherwise a negative error code. 909 **/ 910 int read_sysfs_float(const char *filename, const char *basedir, float *val) 911 { 912 int ret = 0; 913 FILE *sysfsfp; 914 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 915 916 if (!temp) { 917 fprintf(stderr, "Memory allocation failed"); 918 return -ENOMEM; 919 } 920 921 ret = sprintf(temp, "%s/%s", basedir, filename); 922 if (ret < 0) 923 goto error_free; 924 925 sysfsfp = fopen(temp, "r"); 926 if (!sysfsfp) { 927 ret = -errno; 928 goto error_free; 929 } 930 931 errno = 0; 932 if (fscanf(sysfsfp, "%f\n", val) != 1) { 933 ret = errno ? -errno : -ENODATA; 934 if (fclose(sysfsfp)) 935 perror("read_sysfs_float(): Failed to close dir"); 936 937 goto error_free; 938 } 939 940 if (fclose(sysfsfp)) 941 ret = -errno; 942 943 error_free: 944 free(temp); 945 946 return ret; 947 } 948 949 /** 950 * read_sysfs_string() - read a string from file 951 * @filename: name of file to read from 952 * @basedir: the sysfs directory in which the file is to be found 953 * @str: output the read string 954 * 955 * Returns a value >= 0 on success, otherwise a negative error code. 956 **/ 957 int read_sysfs_string(const char *filename, const char *basedir, char *str) 958 { 959 int ret = 0; 960 FILE *sysfsfp; 961 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 962 963 if (!temp) { 964 fprintf(stderr, "Memory allocation failed"); 965 return -ENOMEM; 966 } 967 968 ret = sprintf(temp, "%s/%s", basedir, filename); 969 if (ret < 0) 970 goto error_free; 971 972 sysfsfp = fopen(temp, "r"); 973 if (!sysfsfp) { 974 ret = -errno; 975 goto error_free; 976 } 977 978 errno = 0; 979 if (fscanf(sysfsfp, "%s\n", str) != 1) { 980 ret = errno ? -errno : -ENODATA; 981 if (fclose(sysfsfp)) 982 perror("read_sysfs_string(): Failed to close dir"); 983 984 goto error_free; 985 } 986 987 if (fclose(sysfsfp)) 988 ret = -errno; 989 990 error_free: 991 free(temp); 992 993 return ret; 994 } 995