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