linux/tools/iio/iio_utils.c
<<
>>
Prefs
   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
  18const char *iio_dir = "/sys/bus/iio/devices/";
  19
  20static 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 **/
  32int 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 **/
  88int 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
 186error_close_sysfsfp:
 187        if (sysfsfp)
 188                if (fclose(sysfsfp))
 189                        perror("iioutils_get_type(): Failed to close file");
 190
 191error_free_filename:
 192        if (filename)
 193                free(filename);
 194
 195error_closedir:
 196        if (closedir(dp) == -1)
 197                perror("iioutils_get_type(): Failed to close directory");
 198
 199error_free_builtname_generic:
 200        free(builtname_generic);
 201error_free_builtname:
 202        free(builtname);
 203error_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 **/
 219int 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                }
 270error_free_filename:
 271        if (filename)
 272                free(filename);
 273
 274error_closedir:
 275        if (closedir(dp) == -1)
 276                perror("iioutils_get_param_float(): Failed to close directory");
 277
 278error_free_builtname_generic:
 279        free(builtname_generic);
 280error_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
 292void 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 **/
 314int 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", &current_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                                                     &current->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", &current->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(&current->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(&current->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(&current->is_signed,
 502                                                &current->bytes,
 503                                                &current->bits_used,
 504                                                &current->shift,
 505                                                &current->mask,
 506                                                &current->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
 526error_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;
 534error_close_dir:
 535        if (dp)
 536                if (closedir(dp) == -1)
 537                        perror("build_channel_array(): Failed to close dir");
 538
 539error_free_name:
 540        free(scan_el_dir);
 541
 542        return ret;
 543}
 544
 545static 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 **/
 566int 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
 651error_close_dir:
 652        if (closedir(dp) == -1)
 653                perror("find_type_by_name(): Failed to close directory");
 654
 655        return ret;
 656}
 657
 658static 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
 722error_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 **/
 735int 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 **/
 749int 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
 755static 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
 821error_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 **/
 835int 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 **/
 849int 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 **/
 863int 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
 896error_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 **/
 910int 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
 943error_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 **/
 957int 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
 990error_free:
 991        free(temp);
 992
 993        return ret;
 994}
 995