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", ¤t_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 ¤t->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", ¤t->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(¤t->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(¤t->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(¤t->is_signed, 491 ¤t->bytes, 492 ¤t->bits_used, 493 ¤t->shift, 494 ¤t->mask, 495 ¤t->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