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