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