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