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