root/tools/iio/iio_utils.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iioutils_break_up_name
  2. iioutils_get_type
  3. iioutils_get_param_float
  4. bsort_channel_array_by_index
  5. build_channel_array
  6. calc_digits
  7. find_type_by_name
  8. _write_sysfs_int
  9. write_sysfs_int
  10. write_sysfs_int_and_verify
  11. _write_sysfs_string
  12. write_sysfs_string_and_verify
  13. write_sysfs_string
  14. read_sysfs_posint
  15. read_sysfs_float
  16. read_sysfs_string

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

/* [<][>][^][v][top][bottom][index][help] */