~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/staging/iio/Documentation/generic_buffer.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 **/
 
41
int 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
 
 
57
void 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
 **/
 
83
void 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
 
 
119
int 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, "iio: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, "%siio:device%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
                printf("diag %s\n", dev_dir_name);
 
216
                goto error_free_triggername;
 
217
        }
 
218
 
 
219
        /*
 
220
         * Construct the directory name for the associated buffer.
 
221
         * As we know that the lis3l02dq has only one buffer this may
 
222
         * be built rather than found.
 
223
         */
 
224
        ret = asprintf(&buf_dir_name,
 
225
                       "%siio:device%d/buffer", iio_dir, dev_num);
 
226
        if (ret < 0) {
 
227
                ret = -ENOMEM;
 
228
                goto error_free_triggername;
 
229
        }
 
230
        printf("%s %s\n", dev_dir_name, trigger_name);
 
231
        /* Set the device trigger to be the data rdy trigger found above */
 
232
        ret = write_sysfs_string_and_verify("trigger/current_trigger",
 
233
                                        dev_dir_name,
 
234
                                        trigger_name);
 
235
        if (ret < 0) {
 
236
                printf("Failed to write current_trigger file\n");
 
237
                goto error_free_buf_dir_name;
 
238
        }
 
239
 
 
240
        /* Setup ring buffer parameters */
 
241
        ret = write_sysfs_int("length", buf_dir_name, buf_len);
 
242
        if (ret < 0)
 
243
                goto error_free_buf_dir_name;
 
244
 
 
245
        /* Enable the buffer */
 
246
        ret = write_sysfs_int("enable", buf_dir_name, 1);
 
247
        if (ret < 0)
 
248
                goto error_free_buf_dir_name;
 
249
        scan_size = size_from_channelarray(infoarray, num_channels);
 
250
        data = malloc(scan_size*buf_len);
 
251
        if (!data) {
 
252
                ret = -ENOMEM;
 
253
                goto error_free_buf_dir_name;
 
254
        }
 
255
 
 
256
        ret = asprintf(&buffer_access, "/dev/iio:device%d", 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
 
 
308
error_close_buffer_access:
 
309
        close(fp);
 
310
error_free_data:
 
311
        free(data);
 
312
error_free_buffer_access:
 
313
        free(buffer_access);
 
314
error_free_buf_dir_name:
 
315
        free(buf_dir_name);
 
316
error_free_triggername:
 
317
        if (datardytrigger)
 
318
                free(trigger_name);
 
319
error_ret:
 
320
        return ret;
 
321
}