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