linux/drivers/staging/iio/Documentation/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 <dirent.h>
  23#include <fcntl.h>
  24#include <stdio.h>
  25#include <errno.h>
  26#include <sys/stat.h>
  27#include <sys/dir.h>
  28#include <linux/types.h>
  29#include <string.h>
  30#include <poll.h>
  31#include <endian.h>
  32#include "iio_utils.h"
  33
  34/**
  35 * size_from_channelarray() - calculate the storage size of a scan
  36 * @channels: the channel info array
  37 * @num_channels: size of the channel info array
  38 *
  39 * Has the side effect of filling the channels[i].location values used
  40 * in processing the buffer output.
  41 **/
  42int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
  43{
  44        int bytes = 0;
  45        int i = 0;
  46        while (i < num_channels) {
  47                if (bytes % channels[i].bytes == 0)
  48                        channels[i].location = bytes;
  49                else
  50                        channels[i].location = bytes - bytes%channels[i].bytes
  51                                + channels[i].bytes;
  52                bytes = channels[i].location + channels[i].bytes;
  53                i++;
  54        }
  55        return bytes;
  56}
  57
  58void print2byte(int input, struct iio_channel_info *info)
  59{
  60        /* First swap if incorrect endian */
  61
  62        if (info->be)
  63                input = be16toh((uint_16t)input);
  64        else
  65                input = le16toh((uint_16t)input);
  66
  67        /* shift before conversion to avoid sign extension
  68           of left aligned data */
  69        input = input >> info->shift;
  70        if (info->is_signed) {
  71                int16_t val = input;
  72                val &= (1 << info->bits_used) - 1;
  73                val = (int16_t)(val << (16 - info->bits_used)) >>
  74                        (16 - info->bits_used);
  75                printf("%05f  ", val,
  76                       (float)(val + info->offset)*info->scale);
  77        } else {
  78                uint16_t val = input;
  79                val &= (1 << info->bits_used) - 1;
  80                printf("%05f ", ((float)val + info->offset)*info->scale);
  81        }
  82}
  83/**
  84 * process_scan() - print out the values in SI units
  85 * @data:               pointer to the start of the scan
  86 * @infoarray:          information about the channels. Note
  87 *  size_from_channelarray must have been called first to fill the
  88 *  location offsets.
  89 * @num_channels:       the number of active channels
  90 **/
  91void process_scan(char *data,
  92                  struct iio_channel_info *infoarray,
  93                  int num_channels)
  94{
  95        int k;
  96        for (k = 0; k < num_channels; k++)
  97                switch (infoarray[k].bytes) {
  98                        /* only a few cases implemented so far */
  99                case 2:
 100                        print2byte(*(uint16_t *)(data + infoarray[k].location),
 101                                   &infoarray[k]);
 102                        break;
 103                case 8:
 104                        if (infoarray[k].is_signed) {
 105                                int64_t val = *(int64_t *)
 106                                        (data +
 107                                         infoarray[k].location);
 108                                if ((val >> infoarray[k].bits_used) & 1)
 109                                        val = (val & infoarray[k].mask) |
 110                                                ~infoarray[k].mask;
 111                                /* special case for timestamp */
 112                                if (infoarray[k].scale == 1.0f &&
 113                                    infoarray[k].offset == 0.0f)
 114                                        printf(" %lld", val);
 115                                else
 116                                        printf("%05f ", ((float)val +
 117                                                         infoarray[k].offset)*
 118                                               infoarray[k].scale);
 119                        }
 120                        break;
 121                default:
 122                        break;
 123                }
 124        printf("\n");
 125}
 126
 127int main(int argc, char **argv)
 128{
 129        unsigned long num_loops = 2;
 130        unsigned long timedelay = 1000000;
 131        unsigned long buf_len = 128;
 132
 133
 134        int ret, c, i, j, toread;
 135
 136        FILE *fp_ev;
 137        int fp;
 138
 139        int num_channels;
 140        char *trigger_name = NULL, *device_name = NULL;
 141        char *dev_dir_name, *buf_dir_name;
 142
 143        int datardytrigger = 1;
 144        char *data;
 145        ssize_t read_size;
 146        int dev_num, trig_num;
 147        char *buffer_access;
 148        int scan_size;
 149        int noevents = 0;
 150        char *dummy;
 151
 152        struct iio_channel_info *infoarray;
 153
 154        while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) {
 155                switch (c) {
 156                case 'n':
 157                        device_name = optarg;
 158                        break;
 159                case 't':
 160                        trigger_name = optarg;
 161                        datardytrigger = 0;
 162                        break;
 163                case 'e':
 164                        noevents = 1;
 165                        break;
 166                case 'c':
 167                        num_loops = strtoul(optarg, &dummy, 10);
 168                        break;
 169                case 'w':
 170                        timedelay = strtoul(optarg, &dummy, 10);
 171                        break;
 172                case 'l':
 173                        buf_len = strtoul(optarg, &dummy, 10);
 174                        break;
 175                case '?':
 176                        return -1;
 177                }
 178        }
 179
 180        if (device_name == NULL)
 181                return -1;
 182
 183        /* Find the device requested */
 184        dev_num = find_type_by_name(device_name, "iio:device");
 185        if (dev_num < 0) {
 186                printf("Failed to find the %s\n", device_name);
 187                ret = -ENODEV;
 188                goto error_ret;
 189        }
 190        printf("iio device number being used is %d\n", dev_num);
 191
 192        asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
 193        if (trigger_name == NULL) {
 194                /*
 195                 * Build the trigger name. If it is device associated it's
 196                 * name is <device_name>_dev[n] where n matches the device
 197                 * number found above
 198                 */
 199                ret = asprintf(&trigger_name,
 200                               "%s-dev%d", device_name, dev_num);
 201                if (ret < 0) {
 202                        ret = -ENOMEM;
 203                        goto error_ret;
 204                }
 205        }
 206
 207        /* Verify the trigger exists */
 208        trig_num = find_type_by_name(trigger_name, "trigger");
 209        if (trig_num < 0) {
 210                printf("Failed to find the trigger %s\n", trigger_name);
 211                ret = -ENODEV;
 212                goto error_free_triggername;
 213        }
 214        printf("iio trigger number being used is %d\n", trig_num);
 215
 216        /*
 217         * Parse the files in scan_elements to identify what channels are
 218         * present
 219         */
 220        ret = build_channel_array(dev_dir_name, &infoarray, &num_channels);
 221        if (ret) {
 222                printf("Problem reading scan element information\n");
 223                printf("diag %s\n", dev_dir_name);
 224                goto error_free_triggername;
 225        }
 226
 227        /*
 228         * Construct the directory name for the associated buffer.
 229         * As we know that the lis3l02dq has only one buffer this may
 230         * be built rather than found.
 231         */
 232        ret = asprintf(&buf_dir_name,
 233                       "%siio:device%d/buffer", iio_dir, dev_num);
 234        if (ret < 0) {
 235                ret = -ENOMEM;
 236                goto error_free_triggername;
 237        }
 238        printf("%s %s\n", dev_dir_name, trigger_name);
 239        /* Set the device trigger to be the data rdy trigger found above */
 240        ret = write_sysfs_string_and_verify("trigger/current_trigger",
 241                                        dev_dir_name,
 242                                        trigger_name);
 243        if (ret < 0) {
 244                printf("Failed to write current_trigger file\n");
 245                goto error_free_buf_dir_name;
 246        }
 247
 248        /* Setup ring buffer parameters */
 249        ret = write_sysfs_int("length", buf_dir_name, buf_len);
 250        if (ret < 0)
 251                goto error_free_buf_dir_name;
 252
 253        /* Enable the buffer */
 254        ret = write_sysfs_int("enable", buf_dir_name, 1);
 255        if (ret < 0)
 256                goto error_free_buf_dir_name;
 257        scan_size = size_from_channelarray(infoarray, num_channels);
 258        data = malloc(scan_size*buf_len);
 259        if (!data) {
 260                ret = -ENOMEM;
 261                goto error_free_buf_dir_name;
 262        }
 263
 264        ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
 265        if (ret < 0) {
 266                ret = -ENOMEM;
 267                goto error_free_data;
 268        }
 269
 270        /* Attempt to open non blocking the access dev */
 271        fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
 272        if (fp == -1) { /*If it isn't there make the node */
 273                printf("Failed to open %s\n", buffer_access);
 274                ret = -errno;
 275                goto error_free_buffer_access;
 276        }
 277
 278        /* Wait for events 10 times */
 279        for (j = 0; j < num_loops; j++) {
 280                if (!noevents) {
 281                        struct pollfd pfd = {
 282                                .fd = fp,
 283                                .events = POLLIN,
 284                        };
 285
 286                        poll(&pfd, 1, -1);
 287                        toread = buf_len;
 288
 289                } else {
 290                        usleep(timedelay);
 291                        toread = 64;
 292                }
 293
 294                read_size = read(fp,
 295                                 data,
 296                                 toread*scan_size);
 297                if (read_size == -EAGAIN) {
 298                        printf("nothing available\n");
 299                        continue;
 300                }
 301                for (i = 0; i < read_size/scan_size; i++)
 302                        process_scan(data + scan_size*i,
 303                                     infoarray,
 304                                     num_channels);
 305        }
 306
 307        /* Stop the ring buffer */
 308        ret = write_sysfs_int("enable", buf_dir_name, 0);
 309        if (ret < 0)
 310                goto error_close_buffer_access;
 311
 312        /* Disconnect from the trigger - just write a dummy name.*/
 313        write_sysfs_string("trigger/current_trigger",
 314                        dev_dir_name, "NULL");
 315
 316error_close_buffer_access:
 317        close(fp);
 318error_free_data:
 319        free(data);
 320error_free_buffer_access:
 321        free(buffer_access);
 322error_free_buf_dir_name:
 323        free(buf_dir_name);
 324error_free_triggername:
 325        if (datardytrigger)
 326                free(trigger_name);
 327error_ret:
 328        return ret;
 329}
 330