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