diff options
Diffstat (limited to 'tools/iio/iio_generic_buffer.c')
-rw-r--r-- | tools/iio/iio_generic_buffer.c | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c new file mode 100644 index 000000000000..e8c30521e99c --- /dev/null +++ b/tools/iio/iio_generic_buffer.c | |||
@@ -0,0 +1,682 @@ | |||
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 <stdlib.h> | ||
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> | ||
30 | #include <string.h> | ||
31 | #include <poll.h> | ||
32 | #include <endian.h> | ||
33 | #include <getopt.h> | ||
34 | #include <inttypes.h> | ||
35 | #include <stdbool.h> | ||
36 | #include <signal.h> | ||
37 | #include "iio_utils.h" | ||
38 | |||
39 | /** | ||
40 | * enum autochan - state for the automatic channel enabling mechanism | ||
41 | */ | ||
42 | enum autochan { | ||
43 | AUTOCHANNELS_DISABLED, | ||
44 | AUTOCHANNELS_ENABLED, | ||
45 | AUTOCHANNELS_ACTIVE, | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * size_from_channelarray() - calculate the storage size of a scan | ||
50 | * @channels: the channel info array | ||
51 | * @num_channels: number of channels | ||
52 | * | ||
53 | * Has the side effect of filling the channels[i].location values used | ||
54 | * in processing the buffer output. | ||
55 | **/ | ||
56 | int size_from_channelarray(struct iio_channel_info *channels, int num_channels) | ||
57 | { | ||
58 | int bytes = 0; | ||
59 | int i = 0; | ||
60 | |||
61 | while (i < num_channels) { | ||
62 | if (bytes % channels[i].bytes == 0) | ||
63 | channels[i].location = bytes; | ||
64 | else | ||
65 | channels[i].location = bytes - bytes % channels[i].bytes | ||
66 | + channels[i].bytes; | ||
67 | |||
68 | bytes = channels[i].location + channels[i].bytes; | ||
69 | i++; | ||
70 | } | ||
71 | |||
72 | return bytes; | ||
73 | } | ||
74 | |||
75 | void print1byte(uint8_t input, struct iio_channel_info *info) | ||
76 | { | ||
77 | /* | ||
78 | * Shift before conversion to avoid sign extension | ||
79 | * of left aligned data | ||
80 | */ | ||
81 | input >>= info->shift; | ||
82 | input &= info->mask; | ||
83 | if (info->is_signed) { | ||
84 | int8_t val = (int8_t)(input << (8 - info->bits_used)) >> | ||
85 | (8 - info->bits_used); | ||
86 | printf("%05f ", ((float)val + info->offset) * info->scale); | ||
87 | } else { | ||
88 | printf("%05f ", ((float)input + info->offset) * info->scale); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | void print2byte(uint16_t input, struct iio_channel_info *info) | ||
93 | { | ||
94 | /* First swap if incorrect endian */ | ||
95 | if (info->be) | ||
96 | input = be16toh(input); | ||
97 | else | ||
98 | input = le16toh(input); | ||
99 | |||
100 | /* | ||
101 | * Shift before conversion to avoid sign extension | ||
102 | * of left aligned data | ||
103 | */ | ||
104 | input >>= info->shift; | ||
105 | input &= info->mask; | ||
106 | if (info->is_signed) { | ||
107 | int16_t val = (int16_t)(input << (16 - info->bits_used)) >> | ||
108 | (16 - info->bits_used); | ||
109 | printf("%05f ", ((float)val + info->offset) * info->scale); | ||
110 | } else { | ||
111 | printf("%05f ", ((float)input + info->offset) * info->scale); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | void print4byte(uint32_t input, struct iio_channel_info *info) | ||
116 | { | ||
117 | /* First swap if incorrect endian */ | ||
118 | if (info->be) | ||
119 | input = be32toh(input); | ||
120 | else | ||
121 | input = le32toh(input); | ||
122 | |||
123 | /* | ||
124 | * Shift before conversion to avoid sign extension | ||
125 | * of left aligned data | ||
126 | */ | ||
127 | input >>= info->shift; | ||
128 | input &= info->mask; | ||
129 | if (info->is_signed) { | ||
130 | int32_t val = (int32_t)(input << (32 - info->bits_used)) >> | ||
131 | (32 - info->bits_used); | ||
132 | printf("%05f ", ((float)val + info->offset) * info->scale); | ||
133 | } else { | ||
134 | printf("%05f ", ((float)input + info->offset) * info->scale); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void print8byte(uint64_t input, struct iio_channel_info *info) | ||
139 | { | ||
140 | /* First swap if incorrect endian */ | ||
141 | if (info->be) | ||
142 | input = be64toh(input); | ||
143 | else | ||
144 | input = le64toh(input); | ||
145 | |||
146 | /* | ||
147 | * Shift before conversion to avoid sign extension | ||
148 | * of left aligned data | ||
149 | */ | ||
150 | input >>= info->shift; | ||
151 | input &= info->mask; | ||
152 | if (info->is_signed) { | ||
153 | int64_t val = (int64_t)(input << (64 - info->bits_used)) >> | ||
154 | (64 - info->bits_used); | ||
155 | /* special case for timestamp */ | ||
156 | if (info->scale == 1.0f && info->offset == 0.0f) | ||
157 | printf("%" PRId64 " ", val); | ||
158 | else | ||
159 | printf("%05f ", | ||
160 | ((float)val + info->offset) * info->scale); | ||
161 | } else { | ||
162 | printf("%05f ", ((float)input + info->offset) * info->scale); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * process_scan() - print out the values in SI units | ||
168 | * @data: pointer to the start of the scan | ||
169 | * @channels: information about the channels. | ||
170 | * Note: size_from_channelarray must have been called first | ||
171 | * to fill the location offsets. | ||
172 | * @num_channels: number of channels | ||
173 | **/ | ||
174 | void process_scan(char *data, | ||
175 | struct iio_channel_info *channels, | ||
176 | int num_channels) | ||
177 | { | ||
178 | int k; | ||
179 | |||
180 | for (k = 0; k < num_channels; k++) | ||
181 | switch (channels[k].bytes) { | ||
182 | /* only a few cases implemented so far */ | ||
183 | case 1: | ||
184 | print1byte(*(uint8_t *)(data + channels[k].location), | ||
185 | &channels[k]); | ||
186 | break; | ||
187 | case 2: | ||
188 | print2byte(*(uint16_t *)(data + channels[k].location), | ||
189 | &channels[k]); | ||
190 | break; | ||
191 | case 4: | ||
192 | print4byte(*(uint32_t *)(data + channels[k].location), | ||
193 | &channels[k]); | ||
194 | break; | ||
195 | case 8: | ||
196 | print8byte(*(uint64_t *)(data + channels[k].location), | ||
197 | &channels[k]); | ||
198 | break; | ||
199 | default: | ||
200 | break; | ||
201 | } | ||
202 | printf("\n"); | ||
203 | } | ||
204 | |||
205 | static int enable_disable_all_channels(char *dev_dir_name, int enable) | ||
206 | { | ||
207 | const struct dirent *ent; | ||
208 | char scanelemdir[256]; | ||
209 | DIR *dp; | ||
210 | int ret; | ||
211 | |||
212 | snprintf(scanelemdir, sizeof(scanelemdir), | ||
213 | FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name); | ||
214 | scanelemdir[sizeof(scanelemdir)-1] = '\0'; | ||
215 | |||
216 | dp = opendir(scanelemdir); | ||
217 | if (!dp) { | ||
218 | fprintf(stderr, "Enabling/disabling channels: can't open %s\n", | ||
219 | scanelemdir); | ||
220 | return -EIO; | ||
221 | } | ||
222 | |||
223 | ret = -ENOENT; | ||
224 | while (ent = readdir(dp), ent) { | ||
225 | if (iioutils_check_suffix(ent->d_name, "_en")) { | ||
226 | printf("%sabling: %s\n", | ||
227 | enable ? "En" : "Dis", | ||
228 | ent->d_name); | ||
229 | ret = write_sysfs_int(ent->d_name, scanelemdir, | ||
230 | enable); | ||
231 | if (ret < 0) | ||
232 | fprintf(stderr, "Failed to enable/disable %s\n", | ||
233 | ent->d_name); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if (closedir(dp) == -1) { | ||
238 | perror("Enabling/disabling channels: " | ||
239 | "Failed to close directory"); | ||
240 | return -errno; | ||
241 | } | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | void print_usage(void) | ||
246 | { | ||
247 | fprintf(stderr, "Usage: generic_buffer [options]...\n" | ||
248 | "Capture, convert and output data from IIO device buffer\n" | ||
249 | " -a Auto-activate all available channels\n" | ||
250 | " -c <n> Do n conversions\n" | ||
251 | " -e Disable wait for event (new data)\n" | ||
252 | " -g Use trigger-less mode\n" | ||
253 | " -l <n> Set buffer length to n samples\n" | ||
254 | " --device-name -n <name>\n" | ||
255 | " --device-num -N <num>\n" | ||
256 | " Set device by name or number (mandatory)\n" | ||
257 | " --trigger-name -t <name>\n" | ||
258 | " --trigger-num -T <num>\n" | ||
259 | " Set trigger by name or number\n" | ||
260 | " -w <n> Set delay between reads in us (event-less mode)\n"); | ||
261 | } | ||
262 | |||
263 | enum autochan autochannels = AUTOCHANNELS_DISABLED; | ||
264 | char *dev_dir_name = NULL; | ||
265 | char *buf_dir_name = NULL; | ||
266 | bool current_trigger_set = false; | ||
267 | |||
268 | void cleanup(void) | ||
269 | { | ||
270 | int ret; | ||
271 | |||
272 | /* Disable trigger */ | ||
273 | if (dev_dir_name && current_trigger_set) { | ||
274 | /* Disconnect the trigger - just write a dummy name. */ | ||
275 | ret = write_sysfs_string("trigger/current_trigger", | ||
276 | dev_dir_name, "NULL"); | ||
277 | if (ret < 0) | ||
278 | fprintf(stderr, "Failed to disable trigger: %s\n", | ||
279 | strerror(-ret)); | ||
280 | current_trigger_set = false; | ||
281 | } | ||
282 | |||
283 | /* Disable buffer */ | ||
284 | if (buf_dir_name) { | ||
285 | ret = write_sysfs_int("enable", buf_dir_name, 0); | ||
286 | if (ret < 0) | ||
287 | fprintf(stderr, "Failed to disable buffer: %s\n", | ||
288 | strerror(-ret)); | ||
289 | } | ||
290 | |||
291 | /* Disable channels if auto-enabled */ | ||
292 | if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) { | ||
293 | ret = enable_disable_all_channels(dev_dir_name, 0); | ||
294 | if (ret) | ||
295 | fprintf(stderr, "Failed to disable all channels\n"); | ||
296 | autochannels = AUTOCHANNELS_DISABLED; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | void sig_handler(int signum) | ||
301 | { | ||
302 | fprintf(stderr, "Caught signal %d\n", signum); | ||
303 | cleanup(); | ||
304 | exit(-signum); | ||
305 | } | ||
306 | |||
307 | void register_cleanup(void) | ||
308 | { | ||
309 | struct sigaction sa = { .sa_handler = sig_handler }; | ||
310 | const int signums[] = { SIGINT, SIGTERM, SIGABRT }; | ||
311 | int ret, i; | ||
312 | |||
313 | for (i = 0; i < ARRAY_SIZE(signums); ++i) { | ||
314 | ret = sigaction(signums[i], &sa, NULL); | ||
315 | if (ret) { | ||
316 | perror("Failed to register signal handler"); | ||
317 | exit(-1); | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static const struct option longopts[] = { | ||
323 | { "device-name", 1, 0, 'n' }, | ||
324 | { "device-num", 1, 0, 'N' }, | ||
325 | { "trigger-name", 1, 0, 't' }, | ||
326 | { "trigger-num", 1, 0, 'T' }, | ||
327 | { }, | ||
328 | }; | ||
329 | |||
330 | int main(int argc, char **argv) | ||
331 | { | ||
332 | unsigned long num_loops = 2; | ||
333 | unsigned long timedelay = 1000000; | ||
334 | unsigned long buf_len = 128; | ||
335 | |||
336 | int ret, c, i, j, toread; | ||
337 | int fp = -1; | ||
338 | |||
339 | int num_channels = 0; | ||
340 | char *trigger_name = NULL, *device_name = NULL; | ||
341 | |||
342 | char *data = NULL; | ||
343 | ssize_t read_size; | ||
344 | int dev_num = -1, trig_num; | ||
345 | char *buffer_access = NULL; | ||
346 | int scan_size; | ||
347 | int noevents = 0; | ||
348 | int notrigger = 0; | ||
349 | char *dummy; | ||
350 | |||
351 | struct iio_channel_info *channels; | ||
352 | |||
353 | register_cleanup(); | ||
354 | |||
355 | while ((c = getopt_long(argc, argv, "ac:egl:n:N:t:T:w:", longopts, NULL)) != -1) { | ||
356 | switch (c) { | ||
357 | case 'a': | ||
358 | autochannels = AUTOCHANNELS_ENABLED; | ||
359 | break; | ||
360 | case 'c': | ||
361 | errno = 0; | ||
362 | num_loops = strtoul(optarg, &dummy, 10); | ||
363 | if (errno) { | ||
364 | ret = -errno; | ||
365 | goto error; | ||
366 | } | ||
367 | |||
368 | break; | ||
369 | case 'e': | ||
370 | noevents = 1; | ||
371 | break; | ||
372 | case 'g': | ||
373 | notrigger = 1; | ||
374 | break; | ||
375 | case 'l': | ||
376 | errno = 0; | ||
377 | buf_len = strtoul(optarg, &dummy, 10); | ||
378 | if (errno) { | ||
379 | ret = -errno; | ||
380 | goto error; | ||
381 | } | ||
382 | |||
383 | break; | ||
384 | case 'n': | ||
385 | device_name = strdup(optarg); | ||
386 | break; | ||
387 | case 'N': | ||
388 | errno = 0; | ||
389 | dev_num = strtoul(optarg, &dummy, 10); | ||
390 | if (errno) { | ||
391 | ret = -errno; | ||
392 | goto error; | ||
393 | } | ||
394 | break; | ||
395 | case 't': | ||
396 | trigger_name = strdup(optarg); | ||
397 | break; | ||
398 | case 'T': | ||
399 | errno = 0; | ||
400 | trig_num = strtoul(optarg, &dummy, 10); | ||
401 | if (errno) | ||
402 | return -errno; | ||
403 | break; | ||
404 | case 'w': | ||
405 | errno = 0; | ||
406 | timedelay = strtoul(optarg, &dummy, 10); | ||
407 | if (errno) { | ||
408 | ret = -errno; | ||
409 | goto error; | ||
410 | } | ||
411 | break; | ||
412 | case '?': | ||
413 | print_usage(); | ||
414 | ret = -1; | ||
415 | goto error; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | /* Find the device requested */ | ||
420 | if (dev_num < 0 && !device_name) { | ||
421 | fprintf(stderr, "Device not set\n"); | ||
422 | print_usage(); | ||
423 | ret = -1; | ||
424 | goto error; | ||
425 | } else if (dev_num >= 0 && device_name) { | ||
426 | fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n"); | ||
427 | print_usage(); | ||
428 | ret = -1; | ||
429 | goto error; | ||
430 | } else if (dev_num < 0) { | ||
431 | dev_num = find_type_by_name(device_name, "iio:device"); | ||
432 | if (dev_num < 0) { | ||
433 | fprintf(stderr, "Failed to find the %s\n", device_name); | ||
434 | ret = dev_num; | ||
435 | goto error; | ||
436 | } | ||
437 | } | ||
438 | printf("iio device number being used is %d\n", dev_num); | ||
439 | |||
440 | ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); | ||
441 | if (ret < 0) | ||
442 | return -ENOMEM; | ||
443 | /* Fetch device_name if specified by number */ | ||
444 | if (!device_name) { | ||
445 | device_name = malloc(IIO_MAX_NAME_LENGTH); | ||
446 | if (!device_name) { | ||
447 | ret = -ENOMEM; | ||
448 | goto error; | ||
449 | } | ||
450 | ret = read_sysfs_string("name", dev_dir_name, device_name); | ||
451 | if (ret < 0) { | ||
452 | fprintf(stderr, "Failed to read name of device %d\n", dev_num); | ||
453 | goto error; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | if (notrigger) { | ||
458 | printf("trigger-less mode selected\n"); | ||
459 | } if (trig_num > 0) { | ||
460 | char *trig_dev_name; | ||
461 | ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num); | ||
462 | if (ret < 0) { | ||
463 | return -ENOMEM; | ||
464 | } | ||
465 | trigger_name = malloc(IIO_MAX_NAME_LENGTH); | ||
466 | ret = read_sysfs_string("name", trig_dev_name, trigger_name); | ||
467 | free(trig_dev_name); | ||
468 | if (ret < 0) { | ||
469 | fprintf(stderr, "Failed to read trigger%d name from\n", trig_num); | ||
470 | return ret; | ||
471 | } | ||
472 | printf("iio trigger number being used is %d\n", trig_num); | ||
473 | } else { | ||
474 | if (!trigger_name) { | ||
475 | /* | ||
476 | * Build the trigger name. If it is device associated | ||
477 | * its name is <device_name>_dev[n] where n matches | ||
478 | * the device number found above. | ||
479 | */ | ||
480 | ret = asprintf(&trigger_name, | ||
481 | "%s-dev%d", device_name, dev_num); | ||
482 | if (ret < 0) { | ||
483 | ret = -ENOMEM; | ||
484 | goto error; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | /* Look for this "-devN" trigger */ | ||
489 | trig_num = find_type_by_name(trigger_name, "trigger"); | ||
490 | if (trig_num < 0) { | ||
491 | /* OK try the simpler "-trigger" suffix instead */ | ||
492 | free(trigger_name); | ||
493 | ret = asprintf(&trigger_name, | ||
494 | "%s-trigger", device_name); | ||
495 | if (ret < 0) { | ||
496 | ret = -ENOMEM; | ||
497 | goto error; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | trig_num = find_type_by_name(trigger_name, "trigger"); | ||
502 | if (trig_num < 0) { | ||
503 | fprintf(stderr, "Failed to find the trigger %s\n", | ||
504 | trigger_name); | ||
505 | ret = trig_num; | ||
506 | goto error; | ||
507 | } | ||
508 | |||
509 | printf("iio trigger number being used is %d\n", trig_num); | ||
510 | } | ||
511 | |||
512 | /* | ||
513 | * Parse the files in scan_elements to identify what channels are | ||
514 | * present | ||
515 | */ | ||
516 | ret = build_channel_array(dev_dir_name, &channels, &num_channels); | ||
517 | if (ret) { | ||
518 | fprintf(stderr, "Problem reading scan element information\n" | ||
519 | "diag %s\n", dev_dir_name); | ||
520 | goto error; | ||
521 | } | ||
522 | if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { | ||
523 | fprintf(stderr, "Auto-channels selected but some channels " | ||
524 | "are already activated in sysfs\n"); | ||
525 | fprintf(stderr, "Proceeding without activating any channels\n"); | ||
526 | } | ||
527 | |||
528 | if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) { | ||
529 | fprintf(stderr, | ||
530 | "No channels are enabled, enabling all channels\n"); | ||
531 | |||
532 | ret = enable_disable_all_channels(dev_dir_name, 1); | ||
533 | if (ret) { | ||
534 | fprintf(stderr, "Failed to enable all channels\n"); | ||
535 | goto error; | ||
536 | } | ||
537 | |||
538 | /* This flags that we need to disable the channels again */ | ||
539 | autochannels = AUTOCHANNELS_ACTIVE; | ||
540 | |||
541 | ret = build_channel_array(dev_dir_name, &channels, | ||
542 | &num_channels); | ||
543 | if (ret) { | ||
544 | fprintf(stderr, "Problem reading scan element " | ||
545 | "information\n" | ||
546 | "diag %s\n", dev_dir_name); | ||
547 | goto error; | ||
548 | } | ||
549 | if (!num_channels) { | ||
550 | fprintf(stderr, "Still no channels after " | ||
551 | "auto-enabling, giving up\n"); | ||
552 | goto error; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) { | ||
557 | fprintf(stderr, | ||
558 | "No channels are enabled, we have nothing to scan.\n"); | ||
559 | fprintf(stderr, "Enable channels manually in " | ||
560 | FORMAT_SCAN_ELEMENTS_DIR | ||
561 | "/*_en or pass -a to autoenable channels and " | ||
562 | "try again.\n", dev_dir_name); | ||
563 | ret = -ENOENT; | ||
564 | goto error; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * Construct the directory name for the associated buffer. | ||
569 | * As we know that the lis3l02dq has only one buffer this may | ||
570 | * be built rather than found. | ||
571 | */ | ||
572 | ret = asprintf(&buf_dir_name, | ||
573 | "%siio:device%d/buffer", iio_dir, dev_num); | ||
574 | if (ret < 0) { | ||
575 | ret = -ENOMEM; | ||
576 | goto error; | ||
577 | } | ||
578 | |||
579 | if (!notrigger) { | ||
580 | printf("%s %s\n", dev_dir_name, trigger_name); | ||
581 | /* | ||
582 | * Set the device trigger to be the data ready trigger found | ||
583 | * above | ||
584 | */ | ||
585 | ret = write_sysfs_string_and_verify("trigger/current_trigger", | ||
586 | dev_dir_name, | ||
587 | trigger_name); | ||
588 | if (ret < 0) { | ||
589 | fprintf(stderr, | ||
590 | "Failed to write current_trigger file\n"); | ||
591 | goto error; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /* Setup ring buffer parameters */ | ||
596 | ret = write_sysfs_int("length", buf_dir_name, buf_len); | ||
597 | if (ret < 0) | ||
598 | goto error; | ||
599 | |||
600 | /* Enable the buffer */ | ||
601 | ret = write_sysfs_int("enable", buf_dir_name, 1); | ||
602 | if (ret < 0) { | ||
603 | fprintf(stderr, | ||
604 | "Failed to enable buffer: %s\n", strerror(-ret)); | ||
605 | goto error; | ||
606 | } | ||
607 | |||
608 | scan_size = size_from_channelarray(channels, num_channels); | ||
609 | data = malloc(scan_size * buf_len); | ||
610 | if (!data) { | ||
611 | ret = -ENOMEM; | ||
612 | goto error; | ||
613 | } | ||
614 | |||
615 | ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); | ||
616 | if (ret < 0) { | ||
617 | ret = -ENOMEM; | ||
618 | goto error; | ||
619 | } | ||
620 | |||
621 | /* Attempt to open non blocking the access dev */ | ||
622 | fp = open(buffer_access, O_RDONLY | O_NONBLOCK); | ||
623 | if (fp == -1) { /* TODO: If it isn't there make the node */ | ||
624 | ret = -errno; | ||
625 | fprintf(stderr, "Failed to open %s\n", buffer_access); | ||
626 | goto error; | ||
627 | } | ||
628 | |||
629 | for (j = 0; j < num_loops; j++) { | ||
630 | if (!noevents) { | ||
631 | struct pollfd pfd = { | ||
632 | .fd = fp, | ||
633 | .events = POLLIN, | ||
634 | }; | ||
635 | |||
636 | ret = poll(&pfd, 1, -1); | ||
637 | if (ret < 0) { | ||
638 | ret = -errno; | ||
639 | goto error; | ||
640 | } else if (ret == 0) { | ||
641 | continue; | ||
642 | } | ||
643 | |||
644 | toread = buf_len; | ||
645 | } else { | ||
646 | usleep(timedelay); | ||
647 | toread = 64; | ||
648 | } | ||
649 | |||
650 | read_size = read(fp, data, toread * scan_size); | ||
651 | if (read_size < 0) { | ||
652 | if (errno == EAGAIN) { | ||
653 | fprintf(stderr, "nothing available\n"); | ||
654 | continue; | ||
655 | } else { | ||
656 | break; | ||
657 | } | ||
658 | } | ||
659 | for (i = 0; i < read_size / scan_size; i++) | ||
660 | process_scan(data + scan_size * i, channels, | ||
661 | num_channels); | ||
662 | } | ||
663 | |||
664 | error: | ||
665 | cleanup(); | ||
666 | |||
667 | if (fp >= 0 && close(fp) == -1) | ||
668 | perror("Failed to close buffer"); | ||
669 | free(buffer_access); | ||
670 | free(data); | ||
671 | free(buf_dir_name); | ||
672 | for (i = num_channels - 1; i >= 0; i--) { | ||
673 | free(channels[i].name); | ||
674 | free(channels[i].generic_name); | ||
675 | } | ||
676 | free(channels); | ||
677 | free(trigger_name); | ||
678 | free(device_name); | ||
679 | free(dev_dir_name); | ||
680 | |||
681 | return ret; | ||
682 | } | ||