root/tools/iio/iio_generic_buffer.c

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

DEFINITIONS

This source file includes following definitions.
  1. size_from_channelarray
  2. print1byte
  3. print2byte
  4. print4byte
  5. print8byte
  6. process_scan
  7. enable_disable_all_channels
  8. print_usage
  9. cleanup
  10. sig_handler
  11. register_cleanup
  12. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Industrialio buffer test code.
   3  *
   4  * Copyright (c) 2008 Jonathan Cameron
   5  *
   6  * This program is primarily intended as an example application.
   7  * Reads the current buffer setup from sysfs and starts a short capture
   8  * from the specified device, pretty printing the result after appropriate
   9  * conversion.
  10  *
  11  * Command line parameters
  12  * generic_buffer -n <device_name> -t <trigger_name>
  13  * If trigger name is not specified the program assumes you want a dataready
  14  * trigger associated with the device and goes looking for it.
  15  */
  16 
  17 #include <unistd.h>
  18 #include <stdlib.h>
  19 #include <dirent.h>
  20 #include <fcntl.h>
  21 #include <stdio.h>
  22 #include <errno.h>
  23 #include <sys/stat.h>
  24 #include <sys/dir.h>
  25 #include <linux/types.h>
  26 #include <string.h>
  27 #include <poll.h>
  28 #include <endian.h>
  29 #include <getopt.h>
  30 #include <inttypes.h>
  31 #include <stdbool.h>
  32 #include <signal.h>
  33 #include "iio_utils.h"
  34 
  35 /**
  36  * enum autochan - state for the automatic channel enabling mechanism
  37  */
  38 enum autochan {
  39         AUTOCHANNELS_DISABLED,
  40         AUTOCHANNELS_ENABLED,
  41         AUTOCHANNELS_ACTIVE,
  42 };
  43 
  44 /**
  45  * size_from_channelarray() - calculate the storage size of a scan
  46  * @channels:           the channel info array
  47  * @num_channels:       number of channels
  48  *
  49  * Has the side effect of filling the channels[i].location values used
  50  * in processing the buffer output.
  51  **/
  52 int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
  53 {
  54         int bytes = 0;
  55         int i = 0;
  56 
  57         while (i < num_channels) {
  58                 if (bytes % channels[i].bytes == 0)
  59                         channels[i].location = bytes;
  60                 else
  61                         channels[i].location = bytes - bytes % channels[i].bytes
  62                                                + channels[i].bytes;
  63 
  64                 bytes = channels[i].location + channels[i].bytes;
  65                 i++;
  66         }
  67 
  68         return bytes;
  69 }
  70 
  71 void print1byte(uint8_t input, struct iio_channel_info *info)
  72 {
  73         /*
  74          * Shift before conversion to avoid sign extension
  75          * of left aligned data
  76          */
  77         input >>= info->shift;
  78         input &= info->mask;
  79         if (info->is_signed) {
  80                 int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
  81                              (8 - info->bits_used);
  82                 printf("%05f ", ((float)val + info->offset) * info->scale);
  83         } else {
  84                 printf("%05f ", ((float)input + info->offset) * info->scale);
  85         }
  86 }
  87 
  88 void print2byte(uint16_t input, struct iio_channel_info *info)
  89 {
  90         /* First swap if incorrect endian */
  91         if (info->be)
  92                 input = be16toh(input);
  93         else
  94                 input = le16toh(input);
  95 
  96         /*
  97          * Shift before conversion to avoid sign extension
  98          * of left aligned data
  99          */
 100         input >>= info->shift;
 101         input &= info->mask;
 102         if (info->is_signed) {
 103                 int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
 104                               (16 - info->bits_used);
 105                 printf("%05f ", ((float)val + info->offset) * info->scale);
 106         } else {
 107                 printf("%05f ", ((float)input + info->offset) * info->scale);
 108         }
 109 }
 110 
 111 void print4byte(uint32_t input, struct iio_channel_info *info)
 112 {
 113         /* First swap if incorrect endian */
 114         if (info->be)
 115                 input = be32toh(input);
 116         else
 117                 input = le32toh(input);
 118 
 119         /*
 120          * Shift before conversion to avoid sign extension
 121          * of left aligned data
 122          */
 123         input >>= info->shift;
 124         input &= info->mask;
 125         if (info->is_signed) {
 126                 int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
 127                               (32 - info->bits_used);
 128                 printf("%05f ", ((float)val + info->offset) * info->scale);
 129         } else {
 130                 printf("%05f ", ((float)input + info->offset) * info->scale);
 131         }
 132 }
 133 
 134 void print8byte(uint64_t input, struct iio_channel_info *info)
 135 {
 136         /* First swap if incorrect endian */
 137         if (info->be)
 138                 input = be64toh(input);
 139         else
 140                 input = le64toh(input);
 141 
 142         /*
 143          * Shift before conversion to avoid sign extension
 144          * of left aligned data
 145          */
 146         input >>= info->shift;
 147         input &= info->mask;
 148         if (info->is_signed) {
 149                 int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
 150                               (64 - info->bits_used);
 151                 /* special case for timestamp */
 152                 if (info->scale == 1.0f && info->offset == 0.0f)
 153                         printf("%" PRId64 " ", val);
 154                 else
 155                         printf("%05f ",
 156                                ((float)val + info->offset) * info->scale);
 157         } else {
 158                 printf("%05f ", ((float)input + info->offset) * info->scale);
 159         }
 160 }
 161 
 162 /**
 163  * process_scan() - print out the values in SI units
 164  * @data:               pointer to the start of the scan
 165  * @channels:           information about the channels.
 166  *                      Note: size_from_channelarray must have been called first
 167  *                            to fill the location offsets.
 168  * @num_channels:       number of channels
 169  **/
 170 void process_scan(char *data,
 171                   struct iio_channel_info *channels,
 172                   int num_channels)
 173 {
 174         int k;
 175 
 176         for (k = 0; k < num_channels; k++)
 177                 switch (channels[k].bytes) {
 178                         /* only a few cases implemented so far */
 179                 case 1:
 180                         print1byte(*(uint8_t *)(data + channels[k].location),
 181                                    &channels[k]);
 182                         break;
 183                 case 2:
 184                         print2byte(*(uint16_t *)(data + channels[k].location),
 185                                    &channels[k]);
 186                         break;
 187                 case 4:
 188                         print4byte(*(uint32_t *)(data + channels[k].location),
 189                                    &channels[k]);
 190                         break;
 191                 case 8:
 192                         print8byte(*(uint64_t *)(data + channels[k].location),
 193                                    &channels[k]);
 194                         break;
 195                 default:
 196                         break;
 197                 }
 198         printf("\n");
 199 }
 200 
 201 static int enable_disable_all_channels(char *dev_dir_name, int enable)
 202 {
 203         const struct dirent *ent;
 204         char scanelemdir[256];
 205         DIR *dp;
 206         int ret;
 207 
 208         snprintf(scanelemdir, sizeof(scanelemdir),
 209                  FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
 210         scanelemdir[sizeof(scanelemdir)-1] = '\0';
 211 
 212         dp = opendir(scanelemdir);
 213         if (!dp) {
 214                 fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
 215                         scanelemdir);
 216                 return -EIO;
 217         }
 218 
 219         ret = -ENOENT;
 220         while (ent = readdir(dp), ent) {
 221                 if (iioutils_check_suffix(ent->d_name, "_en")) {
 222                         printf("%sabling: %s\n",
 223                                enable ? "En" : "Dis",
 224                                ent->d_name);
 225                         ret = write_sysfs_int(ent->d_name, scanelemdir,
 226                                               enable);
 227                         if (ret < 0)
 228                                 fprintf(stderr, "Failed to enable/disable %s\n",
 229                                         ent->d_name);
 230                 }
 231         }
 232 
 233         if (closedir(dp) == -1) {
 234                 perror("Enabling/disabling channels: "
 235                        "Failed to close directory");
 236                 return -errno;
 237         }
 238         return 0;
 239 }
 240 
 241 void print_usage(void)
 242 {
 243         fprintf(stderr, "Usage: generic_buffer [options]...\n"
 244                 "Capture, convert and output data from IIO device buffer\n"
 245                 "  -a         Auto-activate all available channels\n"
 246                 "  -A         Force-activate ALL channels\n"
 247                 "  -c <n>     Do n conversions, or loop forever if n < 0\n"
 248                 "  -e         Disable wait for event (new data)\n"
 249                 "  -g         Use trigger-less mode\n"
 250                 "  -l <n>     Set buffer length to n samples\n"
 251                 "  --device-name -n <name>\n"
 252                 "  --device-num -N <num>\n"
 253                 "        Set device by name or number (mandatory)\n"
 254                 "  --trigger-name -t <name>\n"
 255                 "  --trigger-num -T <num>\n"
 256                 "        Set trigger by name or number\n"
 257                 "  -w <n>     Set delay between reads in us (event-less mode)\n");
 258 }
 259 
 260 enum autochan autochannels = AUTOCHANNELS_DISABLED;
 261 char *dev_dir_name = NULL;
 262 char *buf_dir_name = NULL;
 263 bool current_trigger_set = false;
 264 
 265 void cleanup(void)
 266 {
 267         int ret;
 268 
 269         /* Disable trigger */
 270         if (dev_dir_name && current_trigger_set) {
 271                 /* Disconnect the trigger - just write a dummy name. */
 272                 ret = write_sysfs_string("trigger/current_trigger",
 273                                          dev_dir_name, "NULL");
 274                 if (ret < 0)
 275                         fprintf(stderr, "Failed to disable trigger: %s\n",
 276                                 strerror(-ret));
 277                 current_trigger_set = false;
 278         }
 279 
 280         /* Disable buffer */
 281         if (buf_dir_name) {
 282                 ret = write_sysfs_int("enable", buf_dir_name, 0);
 283                 if (ret < 0)
 284                         fprintf(stderr, "Failed to disable buffer: %s\n",
 285                                 strerror(-ret));
 286         }
 287 
 288         /* Disable channels if auto-enabled */
 289         if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
 290                 ret = enable_disable_all_channels(dev_dir_name, 0);
 291                 if (ret)
 292                         fprintf(stderr, "Failed to disable all channels\n");
 293                 autochannels = AUTOCHANNELS_DISABLED;
 294         }
 295 }
 296 
 297 void sig_handler(int signum)
 298 {
 299         fprintf(stderr, "Caught signal %d\n", signum);
 300         cleanup();
 301         exit(-signum);
 302 }
 303 
 304 void register_cleanup(void)
 305 {
 306         struct sigaction sa = { .sa_handler = sig_handler };
 307         const int signums[] = { SIGINT, SIGTERM, SIGABRT };
 308         int ret, i;
 309 
 310         for (i = 0; i < ARRAY_SIZE(signums); ++i) {
 311                 ret = sigaction(signums[i], &sa, NULL);
 312                 if (ret) {
 313                         perror("Failed to register signal handler");
 314                         exit(-1);
 315                 }
 316         }
 317 }
 318 
 319 static const struct option longopts[] = {
 320         { "device-name",        1, 0, 'n' },
 321         { "device-num",         1, 0, 'N' },
 322         { "trigger-name",       1, 0, 't' },
 323         { "trigger-num",        1, 0, 'T' },
 324         { },
 325 };
 326 
 327 int main(int argc, char **argv)
 328 {
 329         long long num_loops = 2;
 330         unsigned long timedelay = 1000000;
 331         unsigned long buf_len = 128;
 332 
 333         ssize_t i;
 334         unsigned long long j;
 335         unsigned long toread;
 336         int ret, c;
 337         int fp = -1;
 338 
 339         int num_channels = 0;
 340         char *trigger_name = NULL, *device_name = NULL;
 341 
 342         char *data = NULL;
 343         ssize_t read_size;
 344         int dev_num = -1, trig_num = -1;
 345         char *buffer_access = NULL;
 346         int scan_size;
 347         int noevents = 0;
 348         int notrigger = 0;
 349         char *dummy;
 350         bool force_autochannels = false;
 351 
 352         struct iio_channel_info *channels = NULL;
 353 
 354         register_cleanup();
 355 
 356         while ((c = getopt_long(argc, argv, "aAc:egl:n:N:t:T:w:?", longopts,
 357                                 NULL)) != -1) {
 358                 switch (c) {
 359                 case 'a':
 360                         autochannels = AUTOCHANNELS_ENABLED;
 361                         break;
 362                 case 'A':
 363                         autochannels = AUTOCHANNELS_ENABLED;
 364                         force_autochannels = true;
 365                         break;  
 366                 case 'c':
 367                         errno = 0;
 368                         num_loops = strtoll(optarg, &dummy, 10);
 369                         if (errno) {
 370                                 ret = -errno;
 371                                 goto error;
 372                         }
 373 
 374                         break;
 375                 case 'e':
 376                         noevents = 1;
 377                         break;
 378                 case 'g':
 379                         notrigger = 1;
 380                         break;
 381                 case 'l':
 382                         errno = 0;
 383                         buf_len = strtoul(optarg, &dummy, 10);
 384                         if (errno) {
 385                                 ret = -errno;
 386                                 goto error;
 387                         }
 388 
 389                         break;
 390                 case 'n':
 391                         device_name = strdup(optarg);
 392                         break;
 393                 case 'N':
 394                         errno = 0;
 395                         dev_num = strtoul(optarg, &dummy, 10);
 396                         if (errno) {
 397                                 ret = -errno;
 398                                 goto error;
 399                         }
 400                         break;
 401                 case 't':
 402                         trigger_name = strdup(optarg);
 403                         break;
 404                 case 'T':
 405                         errno = 0;
 406                         trig_num = strtoul(optarg, &dummy, 10);
 407                         if (errno)
 408                                 return -errno;
 409                         break;
 410                 case 'w':
 411                         errno = 0;
 412                         timedelay = strtoul(optarg, &dummy, 10);
 413                         if (errno) {
 414                                 ret = -errno;
 415                                 goto error;
 416                         }
 417                         break;
 418                 case '?':
 419                         print_usage();
 420                         ret = -1;
 421                         goto error;
 422                 }
 423         }
 424 
 425         /* Find the device requested */
 426         if (dev_num < 0 && !device_name) {
 427                 fprintf(stderr, "Device not set\n");
 428                 print_usage();
 429                 ret = -1;
 430                 goto error;
 431         } else if (dev_num >= 0 && device_name) {
 432                 fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n");
 433                 print_usage();
 434                 ret = -1;
 435                 goto error;
 436         } else if (dev_num < 0) {
 437                 dev_num = find_type_by_name(device_name, "iio:device");
 438                 if (dev_num < 0) {
 439                         fprintf(stderr, "Failed to find the %s\n", device_name);
 440                         ret = dev_num;
 441                         goto error;
 442                 }
 443         }
 444         printf("iio device number being used is %d\n", dev_num);
 445 
 446         ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
 447         if (ret < 0)
 448                 return -ENOMEM;
 449         /* Fetch device_name if specified by number */
 450         if (!device_name) {
 451                 device_name = malloc(IIO_MAX_NAME_LENGTH);
 452                 if (!device_name) {
 453                         ret = -ENOMEM;
 454                         goto error;
 455                 }
 456                 ret = read_sysfs_string("name", dev_dir_name, device_name);
 457                 if (ret < 0) {
 458                         fprintf(stderr, "Failed to read name of device %d\n", dev_num);
 459                         goto error;
 460                 }
 461         }
 462 
 463         if (notrigger) {
 464                 printf("trigger-less mode selected\n");
 465         } else if (trig_num >= 0) {
 466                 char *trig_dev_name;
 467                 ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
 468                 if (ret < 0) {
 469                         return -ENOMEM;
 470                 }
 471                 trigger_name = malloc(IIO_MAX_NAME_LENGTH);
 472                 ret = read_sysfs_string("name", trig_dev_name, trigger_name);
 473                 free(trig_dev_name);
 474                 if (ret < 0) {
 475                         fprintf(stderr, "Failed to read trigger%d name from\n", trig_num);
 476                         return ret;
 477                 }
 478                 printf("iio trigger number being used is %d\n", trig_num);
 479         } else {
 480                 if (!trigger_name) {
 481                         /*
 482                          * Build the trigger name. If it is device associated
 483                          * its name is <device_name>_dev[n] where n matches
 484                          * the device number found above.
 485                          */
 486                         ret = asprintf(&trigger_name,
 487                                        "%s-dev%d", device_name, dev_num);
 488                         if (ret < 0) {
 489                                 ret = -ENOMEM;
 490                                 goto error;
 491                         }
 492                 }
 493 
 494                 /* Look for this "-devN" trigger */
 495                 trig_num = find_type_by_name(trigger_name, "trigger");
 496                 if (trig_num < 0) {
 497                         /* OK try the simpler "-trigger" suffix instead */
 498                         free(trigger_name);
 499                         ret = asprintf(&trigger_name,
 500                                        "%s-trigger", device_name);
 501                         if (ret < 0) {
 502                                 ret = -ENOMEM;
 503                                 goto error;
 504                         }
 505                 }
 506 
 507                 trig_num = find_type_by_name(trigger_name, "trigger");
 508                 if (trig_num < 0) {
 509                         fprintf(stderr, "Failed to find the trigger %s\n",
 510                                 trigger_name);
 511                         ret = trig_num;
 512                         goto error;
 513                 }
 514 
 515                 printf("iio trigger number being used is %d\n", trig_num);
 516         }
 517 
 518         /*
 519          * Parse the files in scan_elements to identify what channels are
 520          * present
 521          */
 522         ret = build_channel_array(dev_dir_name, &channels, &num_channels);
 523         if (ret) {
 524                 fprintf(stderr, "Problem reading scan element information\n"
 525                         "diag %s\n", dev_dir_name);
 526                 goto error;
 527         }
 528         if (num_channels && autochannels == AUTOCHANNELS_ENABLED &&
 529             !force_autochannels) {
 530                 fprintf(stderr, "Auto-channels selected but some channels "
 531                         "are already activated in sysfs\n");
 532                 fprintf(stderr, "Proceeding without activating any channels\n");
 533         }
 534 
 535         if ((!num_channels && autochannels == AUTOCHANNELS_ENABLED) ||
 536             (autochannels == AUTOCHANNELS_ENABLED && force_autochannels)) {
 537                 fprintf(stderr, "Enabling all channels\n");
 538 
 539                 ret = enable_disable_all_channels(dev_dir_name, 1);
 540                 if (ret) {
 541                         fprintf(stderr, "Failed to enable all channels\n");
 542                         goto error;
 543                 }
 544 
 545                 /* This flags that we need to disable the channels again */
 546                 autochannels = AUTOCHANNELS_ACTIVE;
 547 
 548                 ret = build_channel_array(dev_dir_name, &channels,
 549                                           &num_channels);
 550                 if (ret) {
 551                         fprintf(stderr, "Problem reading scan element "
 552                                 "information\n"
 553                                 "diag %s\n", dev_dir_name);
 554                         goto error;
 555                 }
 556                 if (!num_channels) {
 557                         fprintf(stderr, "Still no channels after "
 558                                 "auto-enabling, giving up\n");
 559                         goto error;
 560                 }
 561         }
 562 
 563         if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
 564                 fprintf(stderr,
 565                         "No channels are enabled, we have nothing to scan.\n");
 566                 fprintf(stderr, "Enable channels manually in "
 567                         FORMAT_SCAN_ELEMENTS_DIR
 568                         "/*_en or pass -a to autoenable channels and "
 569                         "try again.\n", dev_dir_name);
 570                 ret = -ENOENT;
 571                 goto error;
 572         }
 573 
 574         /*
 575          * Construct the directory name for the associated buffer.
 576          * As we know that the lis3l02dq has only one buffer this may
 577          * be built rather than found.
 578          */
 579         ret = asprintf(&buf_dir_name,
 580                        "%siio:device%d/buffer", iio_dir, dev_num);
 581         if (ret < 0) {
 582                 ret = -ENOMEM;
 583                 goto error;
 584         }
 585 
 586         if (!notrigger) {
 587                 printf("%s %s\n", dev_dir_name, trigger_name);
 588                 /*
 589                  * Set the device trigger to be the data ready trigger found
 590                  * above
 591                  */
 592                 ret = write_sysfs_string_and_verify("trigger/current_trigger",
 593                                                     dev_dir_name,
 594                                                     trigger_name);
 595                 if (ret < 0) {
 596                         fprintf(stderr,
 597                                 "Failed to write current_trigger file\n");
 598                         goto error;
 599                 }
 600         }
 601 
 602         /* Setup ring buffer parameters */
 603         ret = write_sysfs_int("length", buf_dir_name, buf_len);
 604         if (ret < 0)
 605                 goto error;
 606 
 607         /* Enable the buffer */
 608         ret = write_sysfs_int("enable", buf_dir_name, 1);
 609         if (ret < 0) {
 610                 fprintf(stderr,
 611                         "Failed to enable buffer: %s\n", strerror(-ret));
 612                 goto error;
 613         }
 614 
 615         scan_size = size_from_channelarray(channels, num_channels);
 616         data = malloc(scan_size * buf_len);
 617         if (!data) {
 618                 ret = -ENOMEM;
 619                 goto error;
 620         }
 621 
 622         ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
 623         if (ret < 0) {
 624                 ret = -ENOMEM;
 625                 goto error;
 626         }
 627 
 628         /* Attempt to open non blocking the access dev */
 629         fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
 630         if (fp == -1) { /* TODO: If it isn't there make the node */
 631                 ret = -errno;
 632                 fprintf(stderr, "Failed to open %s\n", buffer_access);
 633                 goto error;
 634         }
 635 
 636         for (j = 0; j < num_loops || num_loops < 0; j++) {
 637                 if (!noevents) {
 638                         struct pollfd pfd = {
 639                                 .fd = fp,
 640                                 .events = POLLIN,
 641                         };
 642 
 643                         ret = poll(&pfd, 1, -1);
 644                         if (ret < 0) {
 645                                 ret = -errno;
 646                                 goto error;
 647                         } else if (ret == 0) {
 648                                 continue;
 649                         }
 650 
 651                         toread = buf_len;
 652                 } else {
 653                         usleep(timedelay);
 654                         toread = 64;
 655                 }
 656 
 657                 read_size = read(fp, data, toread * scan_size);
 658                 if (read_size < 0) {
 659                         if (errno == EAGAIN) {
 660                                 fprintf(stderr, "nothing available\n");
 661                                 continue;
 662                         } else {
 663                                 break;
 664                         }
 665                 }
 666                 for (i = 0; i < read_size / scan_size; i++)
 667                         process_scan(data + scan_size * i, channels,
 668                                      num_channels);
 669         }
 670 
 671 error:
 672         cleanup();
 673 
 674         if (fp >= 0 && close(fp) == -1)
 675                 perror("Failed to close buffer");
 676         free(buffer_access);
 677         free(data);
 678         free(buf_dir_name);
 679         for (i = num_channels - 1; i >= 0; i--) {
 680                 free(channels[i].name);
 681                 free(channels[i].generic_name);
 682         }
 683         free(channels);
 684         free(trigger_name);
 685         free(device_name);
 686         free(dev_dir_name);
 687 
 688         return ret;
 689 }

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