]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - tools/iio/generic_buffer.c
iio:adc:Kconfig: rework help descriptions
[mirror_ubuntu-hirsute-kernel.git] / tools / iio / generic_buffer.c
CommitLineData
e58537cc
JC
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>
bdcb31d0 22#include <stdlib.h>
e58537cc
JC
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>
30268a3d 30#include <string.h>
52615d47 31#include <poll.h>
117cf8b7 32#include <endian.h>
bb23378c 33#include <getopt.h>
1bcdfbcf 34#include <inttypes.h>
e58537cc
JC
35#include "iio_utils.h"
36
e58537cc
JC
37/**
38 * size_from_channelarray() - calculate the storage size of a scan
d8da0eee
PM
39 * @channels: the channel info array
40 * @num_channels: number of channels
e58537cc
JC
41 *
42 * Has the side effect of filling the channels[i].location values used
43 * in processing the buffer output.
44 **/
45int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
46{
47 int bytes = 0;
48 int i = 0;
ff39a252 49
e58537cc
JC
50 while (i < num_channels) {
51 if (bytes % channels[i].bytes == 0)
52 channels[i].location = bytes;
53 else
7663a4aa
HK
54 channels[i].location = bytes - bytes % channels[i].bytes
55 + channels[i].bytes;
56
e58537cc
JC
57 bytes = channels[i].location + channels[i].bytes;
58 i++;
59 }
7663a4aa 60
e58537cc
JC
61 return bytes;
62}
63
8e926134 64void print2byte(uint16_t input, struct iio_channel_info *info)
52615d47 65{
117cf8b7 66 /* First swap if incorrect endian */
117cf8b7 67 if (info->be)
8e926134 68 input = be16toh(input);
117cf8b7 69 else
8e926134 70 input = le16toh(input);
117cf8b7 71
d8da0eee
PM
72 /*
73 * Shift before conversion to avoid sign extension
74 * of left aligned data
75 */
1525ecfc 76 input >>= info->shift;
8e926134 77 input &= info->mask;
52615d47 78 if (info->is_signed) {
8e926134
HK
79 int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
80 (16 - info->bits_used);
81 printf("%05f ", ((float)val + info->offset) * info->scale);
82 } else {
83 printf("%05f ", ((float)input + info->offset) * info->scale);
84 }
85}
ff39a252 86
8e926134
HK
87void print4byte(uint32_t input, struct iio_channel_info *info)
88{
89 /* First swap if incorrect endian */
90 if (info->be)
91 input = be32toh(input);
92 else
93 input = le32toh(input);
94
95 /*
96 * Shift before conversion to avoid sign extension
97 * of left aligned data
98 */
99 input >>= info->shift;
100 input &= info->mask;
101 if (info->is_signed) {
102 int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
103 (32 - info->bits_used);
104 printf("%05f ", ((float)val + info->offset) * info->scale);
52615d47 105 } else {
8e926134
HK
106 printf("%05f ", ((float)input + info->offset) * info->scale);
107 }
108}
ff39a252 109
8e926134
HK
110void print8byte(uint64_t input, struct iio_channel_info *info)
111{
112 /* First swap if incorrect endian */
113 if (info->be)
114 input = be64toh(input);
115 else
116 input = le64toh(input);
117
118 /*
119 * Shift before conversion to avoid sign extension
120 * of left aligned data
121 */
122 input >>= info->shift;
123 input &= info->mask;
124 if (info->is_signed) {
125 int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
126 (64 - info->bits_used);
127 /* special case for timestamp */
128 if (info->scale == 1.0f && info->offset == 0.0f)
129 printf("%" PRId64 " ", val);
130 else
131 printf("%05f ",
132 ((float)val + info->offset) * info->scale);
133 } else {
134 printf("%05f ", ((float)input + info->offset) * info->scale);
52615d47
JC
135 }
136}
8e926134 137
e58537cc
JC
138/**
139 * process_scan() - print out the values in SI units
140 * @data: pointer to the start of the scan
7663a4aa
HK
141 * @channels: information about the channels.
142 * Note: size_from_channelarray must have been called first
143 * to fill the location offsets.
d8da0eee 144 * @num_channels: number of channels
e58537cc
JC
145 **/
146void process_scan(char *data,
d8da0eee 147 struct iio_channel_info *channels,
e58537cc
JC
148 int num_channels)
149{
150 int k;
ff39a252 151
e58537cc 152 for (k = 0; k < num_channels; k++)
d8da0eee 153 switch (channels[k].bytes) {
e58537cc
JC
154 /* only a few cases implemented so far */
155 case 2:
d8da0eee
PM
156 print2byte(*(uint16_t *)(data + channels[k].location),
157 &channels[k]);
e58537cc 158 break;
6cffc1f8 159 case 4:
8e926134
HK
160 print4byte(*(uint32_t *)(data + channels[k].location),
161 &channels[k]);
6cffc1f8 162 break;
e58537cc 163 case 8:
8e926134
HK
164 print8byte(*(uint64_t *)(data + channels[k].location),
165 &channels[k]);
e58537cc
JC
166 break;
167 default:
168 break;
169 }
170 printf("\n");
171}
172
e06e3d71
HK
173void print_usage(void)
174{
175 printf("Usage: generic_buffer [options]...\n"
176 "Capture, convert and output data from IIO device buffer\n"
177 " -c <n> Do n conversions\n"
178 " -e Disable wait for event (new data)\n"
179 " -g Use trigger-less mode\n"
180 " -l <n> Set buffer length to n samples\n"
181 " -n <name> Set device name (mandatory)\n"
182 " -t <name> Set trigger name\n"
183 " -w <n> Set delay between reads in us (event-less mode)\n");
184}
185
e58537cc
JC
186int main(int argc, char **argv)
187{
96df9799
JC
188 unsigned long num_loops = 2;
189 unsigned long timedelay = 1000000;
190 unsigned long buf_len = 128;
191
e58537cc 192 int ret, c, i, j, toread;
e58537cc
JC
193 int fp;
194
195 int num_channels;
196 char *trigger_name = NULL, *device_name = NULL;
197 char *dev_dir_name, *buf_dir_name;
198
199 int datardytrigger = 1;
200 char *data;
c77b3810 201 ssize_t read_size;
e58537cc 202 int dev_num, trig_num;
52615d47 203 char *buffer_access;
e58537cc 204 int scan_size;
30268a3d 205 int noevents = 0;
b6d5be57 206 int notrigger = 0;
96df9799 207 char *dummy;
e58537cc 208
d8da0eee 209 struct iio_channel_info *channels;
e58537cc 210
e06e3d71 211 while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) {
e58537cc 212 switch (c) {
96df9799 213 case 'c':
c8ce9903 214 errno = 0;
96df9799 215 num_loops = strtoul(optarg, &dummy, 10);
c8ce9903
HK
216 if (errno)
217 return -errno;
7663a4aa 218
96df9799 219 break;
e06e3d71
HK
220 case 'e':
221 noevents = 1;
222 break;
223 case 'g':
224 notrigger = 1;
96df9799
JC
225 break;
226 case 'l':
c8ce9903 227 errno = 0;
96df9799 228 buf_len = strtoul(optarg, &dummy, 10);
c8ce9903
HK
229 if (errno)
230 return -errno;
7663a4aa 231
96df9799 232 break;
e06e3d71
HK
233 case 'n':
234 device_name = optarg;
235 break;
236 case 't':
237 trigger_name = optarg;
238 datardytrigger = 0;
239 break;
240 case 'w':
241 errno = 0;
242 timedelay = strtoul(optarg, &dummy, 10);
243 if (errno)
244 return -errno;
b6d5be57 245 break;
e58537cc 246 case '?':
e06e3d71 247 print_usage();
e58537cc
JC
248 return -1;
249 }
250 }
251
e06e3d71
HK
252 if (device_name == NULL) {
253 printf("Device name not set\n");
254 print_usage();
065896e9 255 return -1;
e06e3d71 256 }
065896e9 257
e58537cc 258 /* Find the device requested */
1aa04278 259 dev_num = find_type_by_name(device_name, "iio:device");
e58537cc
JC
260 if (dev_num < 0) {
261 printf("Failed to find the %s\n", device_name);
0e799878 262 return dev_num;
e58537cc 263 }
7663a4aa 264
e58537cc
JC
265 printf("iio device number being used is %d\n", dev_num);
266
e9e45b43
HK
267 ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
268 if (ret < 0)
269 return -ENOMEM;
b6d5be57
KW
270
271 if (!notrigger) {
272 if (trigger_name == NULL) {
273 /*
274 * Build the trigger name. If it is device associated
275 * its name is <device_name>_dev[n] where n matches
276 * the device number found above.
277 */
278 ret = asprintf(&trigger_name,
279 "%s-dev%d", device_name, dev_num);
280 if (ret < 0) {
281 ret = -ENOMEM;
d3ccfc41 282 goto error_free_dev_dir_name;
b6d5be57 283 }
e58537cc 284 }
e58537cc 285
b6d5be57
KW
286 /* Verify the trigger exists */
287 trig_num = find_type_by_name(trigger_name, "trigger");
288 if (trig_num < 0) {
289 printf("Failed to find the trigger %s\n", trigger_name);
e83a47cf 290 ret = trig_num;
b6d5be57
KW
291 goto error_free_triggername;
292 }
7663a4aa 293
b6d5be57 294 printf("iio trigger number being used is %d\n", trig_num);
7663a4aa 295 } else {
b6d5be57 296 printf("trigger-less mode selected\n");
7663a4aa 297 }
e58537cc
JC
298
299 /*
300 * Parse the files in scan_elements to identify what channels are
301 * present
302 */
d8da0eee 303 ret = build_channel_array(dev_dir_name, &channels, &num_channels);
e58537cc 304 if (ret) {
52615d47 305 printf("Problem reading scan element information\n");
1aa04278 306 printf("diag %s\n", dev_dir_name);
e58537cc
JC
307 goto error_free_triggername;
308 }
309
310 /*
311 * Construct the directory name for the associated buffer.
312 * As we know that the lis3l02dq has only one buffer this may
313 * be built rather than found.
314 */
1aa04278
JC
315 ret = asprintf(&buf_dir_name,
316 "%siio:device%d/buffer", iio_dir, dev_num);
e58537cc
JC
317 if (ret < 0) {
318 ret = -ENOMEM;
63f05c85 319 goto error_free_channels;
e58537cc 320 }
b6d5be57
KW
321
322 if (!notrigger) {
323 printf("%s %s\n", dev_dir_name, trigger_name);
7663a4aa
HK
324 /*
325 * Set the device trigger to be the data ready trigger found
326 * above
327 */
b6d5be57
KW
328 ret = write_sysfs_string_and_verify("trigger/current_trigger",
329 dev_dir_name,
330 trigger_name);
331 if (ret < 0) {
332 printf("Failed to write current_trigger file\n");
333 goto error_free_buf_dir_name;
334 }
e58537cc
JC
335 }
336
337 /* Setup ring buffer parameters */
338 ret = write_sysfs_int("length", buf_dir_name, buf_len);
339 if (ret < 0)
340 goto error_free_buf_dir_name;
341
342 /* Enable the buffer */
343 ret = write_sysfs_int("enable", buf_dir_name, 1);
344 if (ret < 0)
345 goto error_free_buf_dir_name;
7663a4aa 346
d8da0eee 347 scan_size = size_from_channelarray(channels, num_channels);
7663a4aa 348 data = malloc(scan_size * buf_len);
e58537cc
JC
349 if (!data) {
350 ret = -ENOMEM;
351 goto error_free_buf_dir_name;
352 }
353
1aa04278 354 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
e58537cc
JC
355 if (ret < 0) {
356 ret = -ENOMEM;
357 goto error_free_data;
358 }
359
e58537cc
JC
360 /* Attempt to open non blocking the access dev */
361 fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
7663a4aa 362 if (fp == -1) { /* TODO: If it isn't there make the node */
e58537cc 363 ret = -errno;
2b6a6e67 364 printf("Failed to open %s\n", buffer_access);
52615d47 365 goto error_free_buffer_access;
e58537cc
JC
366 }
367
e58537cc 368 for (j = 0; j < num_loops; j++) {
30268a3d 369 if (!noevents) {
52615d47
JC
370 struct pollfd pfd = {
371 .fd = fp,
372 .events = POLLIN,
373 };
374
6bb7cac8
HK
375 ret = poll(&pfd, 1, -1);
376 if (ret < 0) {
377 ret = -errno;
378 goto error_close_buffer_access;
379 } else if (ret == 0) {
380 continue;
381 }
382
52615d47 383 toread = buf_len;
30268a3d 384 } else {
96df9799 385 usleep(timedelay);
30268a3d 386 toread = 64;
e58537cc 387 }
30268a3d 388
7663a4aa 389 read_size = read(fp, data, toread * scan_size);
97b603a4 390 if (read_size < 0) {
8749948a 391 if (errno == EAGAIN) {
97b603a4
PM
392 printf("nothing available\n");
393 continue;
7663a4aa 394 } else {
97b603a4 395 break;
7663a4aa 396 }
e58537cc 397 }
7663a4aa
HK
398 for (i = 0; i < read_size / scan_size; i++)
399 process_scan(data + scan_size * i, channels,
e58537cc
JC
400 num_channels);
401 }
402
d8da0eee 403 /* Stop the buffer */
e58537cc
JC
404 ret = write_sysfs_int("enable", buf_dir_name, 0);
405 if (ret < 0)
52615d47 406 goto error_close_buffer_access;
e58537cc 407
b6d5be57
KW
408 if (!notrigger)
409 /* Disconnect the trigger - just write a dummy name. */
6bb7cac8
HK
410 ret = write_sysfs_string("trigger/current_trigger",
411 dev_dir_name, "NULL");
412 if (ret < 0)
413 printf("Failed to write to %s\n", dev_dir_name);
e58537cc 414
e58537cc 415error_close_buffer_access:
6bb7cac8
HK
416 if (close(fp) == -1)
417 perror("Failed to close buffer");
7663a4aa 418
e58537cc
JC
419error_free_buffer_access:
420 free(buffer_access);
a71bfb4a
HK
421error_free_data:
422 free(data);
e58537cc
JC
423error_free_buf_dir_name:
424 free(buf_dir_name);
63f05c85
HK
425error_free_channels:
426 for (i = num_channels - 1; i >= 0; i--) {
427 free(channels[i].name);
428 free(channels[i].generic_name);
429 }
430 free(channels);
e58537cc
JC
431error_free_triggername:
432 if (datardytrigger)
433 free(trigger_name);
7663a4aa 434
d3ccfc41
HK
435error_free_dev_dir_name:
436 free(dev_dir_name);
0e799878 437
e58537cc
JC
438 return ret;
439}