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 break; 268 } 269 error_free_filename: 270 if (filename) 271 free(filename); 272 273 error_closedir: 274 if (closedir(dp) == -1) 275 perror("iioutils_get_param_float(): Failed to close directory"); 276 277 error_free_builtname_generic: 278 free(builtname_generic); 279 error_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 291 void 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 **/ 314 int 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 527 error_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; 535 error_close_dir: 536 if (dp) 537 if (closedir(dp) == -1) 538 perror("build_channel_array(): Failed to close dir"); 539 540 error_free_name: 541 free(scan_el_dir); 542 543 return ret; 544 } 545 546 static int calc_digits(int num) 547 { 548 int count = 0; 549 550 /* It takes a digit to represent zero */ 551 if (!num) 552 return 1; 553 554 while (num != 0) { 555 num /= 10; 556 count++; 557 } 558 559 return count; 560 } 561 562 /** 563 * find_type_by_name() - function to match top level types by name 564 * @name: top level type instance name 565 * @type: the type of top level instance being searched 566 * 567 * Returns the device number of a matched IIO device on success, otherwise a 568 * negative error code. 569 * Typical types this is used for are device and trigger. 570 **/ 571 int find_type_by_name(const char *name, const char *type) 572 { 573 const struct dirent *ent; 574 int number, numstrlen, ret; 575 576 FILE *namefp; 577 DIR *dp; 578 char thisname[IIO_MAX_NAME_LENGTH]; 579 char *filename; 580 581 dp = opendir(iio_dir); 582 if (!dp) { 583 fprintf(stderr, "No industrialio devices available\n"); 584 return -ENODEV; 585 } 586 587 while (ent = readdir(dp), ent) { 588 if (strcmp(ent->d_name, ".") != 0 && 589 strcmp(ent->d_name, "..") != 0 && 590 strlen(ent->d_name) > strlen(type) && 591 strncmp(ent->d_name, type, strlen(type)) == 0) { 592 errno = 0; 593 ret = sscanf(ent->d_name + strlen(type), "%d", &number); 594 if (ret < 0) { 595 ret = -errno; 596 fprintf(stderr, 597 "failed to read element number\n"); 598 goto error_close_dir; 599 } else if (ret != 1) { 600 ret = -EIO; 601 fprintf(stderr, 602 "failed to match element number\n"); 603 goto error_close_dir; 604 } 605 606 numstrlen = calc_digits(number); 607 /* verify the next character is not a colon */ 608 if (strncmp(ent->d_name + strlen(type) + numstrlen, 609 ":", 1) != 0) { 610 filename = malloc(strlen(iio_dir) + strlen(type) 611 + numstrlen + 6); 612 if (!filename) { 613 ret = -ENOMEM; 614 goto error_close_dir; 615 } 616 617 ret = sprintf(filename, "%s%s%d/name", iio_dir, 618 type, number); 619 if (ret < 0) { 620 free(filename); 621 goto error_close_dir; 622 } 623 624 namefp = fopen(filename, "r"); 625 if (!namefp) { 626 free(filename); 627 continue; 628 } 629 630 free(filename); 631 errno = 0; 632 if (fscanf(namefp, "%s", thisname) != 1) { 633 ret = errno ? -errno : -ENODATA; 634 goto error_close_dir; 635 } 636 637 if (fclose(namefp)) { 638 ret = -errno; 639 goto error_close_dir; 640 } 641 642 if (strcmp(name, thisname) == 0) { 643 if (closedir(dp) == -1) 644 return -errno; 645 646 return number; 647 } 648 } 649 } 650 } 651 if (closedir(dp) == -1) 652 return -errno; 653 654 return -ENODEV; 655 656 error_close_dir: 657 if (closedir(dp) == -1) 658 perror("find_type_by_name(): Failed to close directory"); 659 660 return ret; 661 } 662 663 static int _write_sysfs_int(const char *filename, const char *basedir, int val, 664 int verify) 665 { 666 int ret = 0; 667 FILE *sysfsfp; 668 int test; 669 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 670 671 if (!temp) 672 return -ENOMEM; 673 674 ret = sprintf(temp, "%s/%s", basedir, filename); 675 if (ret < 0) 676 goto error_free; 677 678 sysfsfp = fopen(temp, "w"); 679 if (!sysfsfp) { 680 ret = -errno; 681 fprintf(stderr, "failed to open %s\n", temp); 682 goto error_free; 683 } 684 685 ret = fprintf(sysfsfp, "%d", val); 686 if (ret < 0) { 687 if (fclose(sysfsfp)) 688 perror("_write_sysfs_int(): Failed to close dir"); 689 690 goto error_free; 691 } 692 693 if (fclose(sysfsfp)) { 694 ret = -errno; 695 goto error_free; 696 } 697 698 if (verify) { 699 sysfsfp = fopen(temp, "r"); 700 if (!sysfsfp) { 701 ret = -errno; 702 fprintf(stderr, "failed to open %s\n", temp); 703 goto error_free; 704 } 705 706 if (fscanf(sysfsfp, "%d", &test) != 1) { 707 ret = errno ? -errno : -ENODATA; 708 if (fclose(sysfsfp)) 709 perror("_write_sysfs_int(): Failed to close dir"); 710 711 goto error_free; 712 } 713 714 if (fclose(sysfsfp)) { 715 ret = -errno; 716 goto error_free; 717 } 718 719 if (test != val) { 720 fprintf(stderr, 721 "Possible failure in int write %d to %s/%s\n", 722 val, basedir, filename); 723 ret = -1; 724 } 725 } 726 727 error_free: 728 free(temp); 729 return ret; 730 } 731 732 /** 733 * write_sysfs_int() - write an integer value to a sysfs file 734 * @filename: name of the file to write to 735 * @basedir: the sysfs directory in which the file is to be found 736 * @val: integer value to write to file 737 * 738 * Returns a value >= 0 on success, otherwise a negative error code. 739 **/ 740 int write_sysfs_int(const char *filename, const char *basedir, int val) 741 { 742 return _write_sysfs_int(filename, basedir, val, 0); 743 } 744 745 /** 746 * write_sysfs_int_and_verify() - write an integer value to a sysfs file 747 * and verify 748 * @filename: name of the file to write to 749 * @basedir: the sysfs directory in which the file is to be found 750 * @val: integer value to write to file 751 * 752 * Returns a value >= 0 on success, otherwise a negative error code. 753 **/ 754 int write_sysfs_int_and_verify(const char *filename, const char *basedir, 755 int val) 756 { 757 return _write_sysfs_int(filename, basedir, val, 1); 758 } 759 760 static int _write_sysfs_string(const char *filename, const char *basedir, 761 const char *val, int verify) 762 { 763 int ret = 0; 764 FILE *sysfsfp; 765 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 766 767 if (!temp) { 768 fprintf(stderr, "Memory allocation failed\n"); 769 return -ENOMEM; 770 } 771 772 ret = sprintf(temp, "%s/%s", basedir, filename); 773 if (ret < 0) 774 goto error_free; 775 776 sysfsfp = fopen(temp, "w"); 777 if (!sysfsfp) { 778 ret = -errno; 779 fprintf(stderr, "Could not open %s\n", temp); 780 goto error_free; 781 } 782 783 ret = fprintf(sysfsfp, "%s", val); 784 if (ret < 0) { 785 if (fclose(sysfsfp)) 786 perror("_write_sysfs_string(): Failed to close dir"); 787 788 goto error_free; 789 } 790 791 if (fclose(sysfsfp)) { 792 ret = -errno; 793 goto error_free; 794 } 795 796 if (verify) { 797 sysfsfp = fopen(temp, "r"); 798 if (!sysfsfp) { 799 ret = -errno; 800 fprintf(stderr, "Could not open file to verify\n"); 801 goto error_free; 802 } 803 804 if (fscanf(sysfsfp, "%s", temp) != 1) { 805 ret = errno ? -errno : -ENODATA; 806 if (fclose(sysfsfp)) 807 perror("_write_sysfs_string(): Failed to close dir"); 808 809 goto error_free; 810 } 811 812 if (fclose(sysfsfp)) { 813 ret = -errno; 814 goto error_free; 815 } 816 817 if (strcmp(temp, val) != 0) { 818 fprintf(stderr, 819 "Possible failure in string write of %s " 820 "Should be %s written to %s/%s\n", temp, val, 821 basedir, filename); 822 ret = -1; 823 } 824 } 825 826 error_free: 827 free(temp); 828 829 return ret; 830 } 831 832 /** 833 * write_sysfs_string_and_verify() - string write, readback and verify 834 * @filename: name of file to write to 835 * @basedir: the sysfs directory in which the file is to be found 836 * @val: the string to write 837 * 838 * Returns a value >= 0 on success, otherwise a negative error code. 839 **/ 840 int write_sysfs_string_and_verify(const char *filename, const char *basedir, 841 const char *val) 842 { 843 return _write_sysfs_string(filename, basedir, val, 1); 844 } 845 846 /** 847 * write_sysfs_string() - write string to a sysfs file 848 * @filename: name of file to write to 849 * @basedir: the sysfs directory in which the file is to be found 850 * @val: the string to write 851 * 852 * Returns a value >= 0 on success, otherwise a negative error code. 853 **/ 854 int write_sysfs_string(const char *filename, const char *basedir, 855 const char *val) 856 { 857 return _write_sysfs_string(filename, basedir, val, 0); 858 } 859 860 /** 861 * read_sysfs_posint() - read an integer value from file 862 * @filename: name of file to read from 863 * @basedir: the sysfs directory in which the file is to be found 864 * 865 * Returns the read integer value >= 0 on success, otherwise a negative error 866 * code. 867 **/ 868 int read_sysfs_posint(const char *filename, const char *basedir) 869 { 870 int ret; 871 FILE *sysfsfp; 872 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 873 874 if (!temp) { 875 fprintf(stderr, "Memory allocation failed"); 876 return -ENOMEM; 877 } 878 879 ret = sprintf(temp, "%s/%s", basedir, filename); 880 if (ret < 0) 881 goto error_free; 882 883 sysfsfp = fopen(temp, "r"); 884 if (!sysfsfp) { 885 ret = -errno; 886 goto error_free; 887 } 888 889 errno = 0; 890 if (fscanf(sysfsfp, "%d\n", &ret) != 1) { 891 ret = errno ? -errno : -ENODATA; 892 if (fclose(sysfsfp)) 893 perror("read_sysfs_posint(): Failed to close dir"); 894 895 goto error_free; 896 } 897 898 if (fclose(sysfsfp)) 899 ret = -errno; 900 901 error_free: 902 free(temp); 903 904 return ret; 905 } 906 907 /** 908 * read_sysfs_float() - read a float value from file 909 * @filename: name of file to read from 910 * @basedir: the sysfs directory in which the file is to be found 911 * @val: output the read float value 912 * 913 * Returns a value >= 0 on success, otherwise a negative error code. 914 **/ 915 int read_sysfs_float(const char *filename, const char *basedir, float *val) 916 { 917 int ret = 0; 918 FILE *sysfsfp; 919 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 920 921 if (!temp) { 922 fprintf(stderr, "Memory allocation failed"); 923 return -ENOMEM; 924 } 925 926 ret = sprintf(temp, "%s/%s", basedir, filename); 927 if (ret < 0) 928 goto error_free; 929 930 sysfsfp = fopen(temp, "r"); 931 if (!sysfsfp) { 932 ret = -errno; 933 goto error_free; 934 } 935 936 errno = 0; 937 if (fscanf(sysfsfp, "%f\n", val) != 1) { 938 ret = errno ? -errno : -ENODATA; 939 if (fclose(sysfsfp)) 940 perror("read_sysfs_float(): Failed to close dir"); 941 942 goto error_free; 943 } 944 945 if (fclose(sysfsfp)) 946 ret = -errno; 947 948 error_free: 949 free(temp); 950 951 return ret; 952 } 953 954 /** 955 * read_sysfs_string() - read a string from file 956 * @filename: name of file to read from 957 * @basedir: the sysfs directory in which the file is to be found 958 * @str: output the read string 959 * 960 * Returns a value >= 0 on success, otherwise a negative error code. 961 **/ 962 int read_sysfs_string(const char *filename, const char *basedir, char *str) 963 { 964 int ret = 0; 965 FILE *sysfsfp; 966 char *temp = malloc(strlen(basedir) + strlen(filename) + 2); 967 968 if (!temp) { 969 fprintf(stderr, "Memory allocation failed"); 970 return -ENOMEM; 971 } 972 973 ret = sprintf(temp, "%s/%s", basedir, filename); 974 if (ret < 0) 975 goto error_free; 976 977 sysfsfp = fopen(temp, "r"); 978 if (!sysfsfp) { 979 ret = -errno; 980 goto error_free; 981 } 982 983 errno = 0; 984 if (fscanf(sysfsfp, "%s\n", str) != 1) { 985 ret = errno ? -errno : -ENODATA; 986 if (fclose(sysfsfp)) 987 perror("read_sysfs_string(): Failed to close dir"); 988 989 goto error_free; 990 } 991 992 if (fclose(sysfsfp)) 993 ret = -errno; 994 995 error_free: 996 free(temp); 997 998 return ret; 999 } 1000