Linux Audio

Check our new training course

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