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  **/
size_from_channelarray(struct iio_channel_info * channels,int num_channels)45 int 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 		bytes = channels[i].location + channels[i].bytes;
57 		i++;
58 	}
59 	return bytes;
60 }
61 
print2byte(int input,struct iio_channel_info * info)62 void print2byte(int input, struct iio_channel_info *info)
63 {
64 	/* First swap if incorrect endian */
65 	if (info->be)
66 		input = be16toh((uint16_t)input);
67 	else
68 		input = le16toh((uint16_t)input);
69 
70 	/*
71 	 * Shift before conversion to avoid sign extension
72 	 * of left aligned data
73 	 */
74 	input >>= info->shift;
75 	if (info->is_signed) {
76 		int16_t val = input;
77 
78 		val &= (1 << info->bits_used) - 1;
79 		val = (int16_t)(val << (16 - info->bits_used)) >>
80 			(16 - info->bits_used);
81 		printf("%05f ", ((float)val + info->offset)*info->scale);
82 	} else {
83 		uint16_t val = input;
84 
85 		val &= (1 << info->bits_used) - 1;
86 		printf("%05f ", ((float)val + info->offset)*info->scale);
87 	}
88 }
89 /**
90  * process_scan() - print out the values in SI units
91  * @data:		pointer to the start of the scan
92  * @channels:		information about the channels. Note
93  *  size_from_channelarray must have been called first to fill the
94  *  location offsets.
95  * @num_channels:	number of channels
96  **/
process_scan(char * data,struct iio_channel_info * channels,int num_channels)97 void process_scan(char *data,
98 		  struct iio_channel_info *channels,
99 		  int num_channels)
100 {
101 	int k;
102 
103 	for (k = 0; k < num_channels; k++)
104 		switch (channels[k].bytes) {
105 			/* only a few cases implemented so far */
106 		case 2:
107 			print2byte(*(uint16_t *)(data + channels[k].location),
108 				   &channels[k]);
109 			break;
110 		case 4:
111 			if (!channels[k].is_signed) {
112 				uint32_t val = *(uint32_t *)
113 					(data + channels[k].location);
114 				printf("%05f ", ((float)val +
115 						 channels[k].offset)*
116 				       channels[k].scale);
117 
118 			}
119 			break;
120 		case 8:
121 			if (channels[k].is_signed) {
122 				int64_t val = *(int64_t *)
123 					(data +
124 					 channels[k].location);
125 				if ((val >> channels[k].bits_used) & 1)
126 					val = (val & channels[k].mask) |
127 						~channels[k].mask;
128 				/* special case for timestamp */
129 				if (channels[k].scale == 1.0f &&
130 				    channels[k].offset == 0.0f)
131 					printf("%" PRId64 " ", val);
132 				else
133 					printf("%05f ", ((float)val +
134 							 channels[k].offset)*
135 					       channels[k].scale);
136 			}
137 			break;
138 		default:
139 			break;
140 		}
141 	printf("\n");
142 }
143 
main(int argc,char ** argv)144 int main(int argc, char **argv)
145 {
146 	unsigned long num_loops = 2;
147 	unsigned long timedelay = 1000000;
148 	unsigned long buf_len = 128;
149 
150 	int ret, c, i, j, toread;
151 	int fp;
152 
153 	int num_channels;
154 	char *trigger_name = NULL, *device_name = NULL;
155 	char *dev_dir_name, *buf_dir_name;
156 
157 	int datardytrigger = 1;
158 	char *data;
159 	ssize_t read_size;
160 	int dev_num, trig_num;
161 	char *buffer_access;
162 	int scan_size;
163 	int noevents = 0;
164 	int notrigger = 0;
165 	char *dummy;
166 
167 	struct iio_channel_info *channels;
168 
169 	while ((c = getopt(argc, argv, "l:w:c:et:n:g")) != -1) {
170 		switch (c) {
171 		case 'n':
172 			device_name = optarg;
173 			break;
174 		case 't':
175 			trigger_name = optarg;
176 			datardytrigger = 0;
177 			break;
178 		case 'e':
179 			noevents = 1;
180 			break;
181 		case 'c':
182 			num_loops = strtoul(optarg, &dummy, 10);
183 			break;
184 		case 'w':
185 			timedelay = strtoul(optarg, &dummy, 10);
186 			break;
187 		case 'l':
188 			buf_len = strtoul(optarg, &dummy, 10);
189 			break;
190 		case 'g':
191 			notrigger = 1;
192 			break;
193 		case '?':
194 			return -1;
195 		}
196 	}
197 
198 	if (device_name == NULL)
199 		return -1;
200 
201 	/* Find the device requested */
202 	dev_num = find_type_by_name(device_name, "iio:device");
203 	if (dev_num < 0) {
204 		printf("Failed to find the %s\n", device_name);
205 		ret = -ENODEV;
206 		goto error_ret;
207 	}
208 	printf("iio device number being used is %d\n", dev_num);
209 
210 	asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
211 
212 	if (!notrigger) {
213 		if (trigger_name == NULL) {
214 			/*
215 			 * Build the trigger name. If it is device associated
216 			 * its name is <device_name>_dev[n] where n matches
217 			 * the device number found above.
218 			 */
219 			ret = asprintf(&trigger_name,
220 				       "%s-dev%d", device_name, dev_num);
221 			if (ret < 0) {
222 				ret = -ENOMEM;
223 				goto error_ret;
224 			}
225 		}
226 
227 		/* Verify the trigger exists */
228 		trig_num = find_type_by_name(trigger_name, "trigger");
229 		if (trig_num < 0) {
230 			printf("Failed to find the trigger %s\n", trigger_name);
231 			ret = -ENODEV;
232 			goto error_free_triggername;
233 		}
234 		printf("iio trigger number being used is %d\n", trig_num);
235 	} else
236 		printf("trigger-less mode selected\n");
237 
238 	/*
239 	 * Parse the files in scan_elements to identify what channels are
240 	 * present
241 	 */
242 	ret = build_channel_array(dev_dir_name, &channels, &num_channels);
243 	if (ret) {
244 		printf("Problem reading scan element information\n");
245 		printf("diag %s\n", dev_dir_name);
246 		goto error_free_triggername;
247 	}
248 
249 	/*
250 	 * Construct the directory name for the associated buffer.
251 	 * As we know that the lis3l02dq has only one buffer this may
252 	 * be built rather than found.
253 	 */
254 	ret = asprintf(&buf_dir_name,
255 		       "%siio:device%d/buffer", iio_dir, dev_num);
256 	if (ret < 0) {
257 		ret = -ENOMEM;
258 		goto error_free_triggername;
259 	}
260 
261 	if (!notrigger) {
262 		printf("%s %s\n", dev_dir_name, trigger_name);
263 		/* Set the device trigger to be the data ready trigger found
264 		 * above */
265 		ret = write_sysfs_string_and_verify("trigger/current_trigger",
266 						    dev_dir_name,
267 						    trigger_name);
268 		if (ret < 0) {
269 			printf("Failed to write current_trigger file\n");
270 			goto error_free_buf_dir_name;
271 		}
272 	}
273 
274 	/* Setup ring buffer parameters */
275 	ret = write_sysfs_int("length", buf_dir_name, buf_len);
276 	if (ret < 0)
277 		goto error_free_buf_dir_name;
278 
279 	/* Enable the buffer */
280 	ret = write_sysfs_int("enable", buf_dir_name, 1);
281 	if (ret < 0)
282 		goto error_free_buf_dir_name;
283 	scan_size = size_from_channelarray(channels, num_channels);
284 	data = malloc(scan_size*buf_len);
285 	if (!data) {
286 		ret = -ENOMEM;
287 		goto error_free_buf_dir_name;
288 	}
289 
290 	ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
291 	if (ret < 0) {
292 		ret = -ENOMEM;
293 		goto error_free_data;
294 	}
295 
296 	/* Attempt to open non blocking the access dev */
297 	fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
298 	if (fp == -1) { /* If it isn't there make the node */
299 		printf("Failed to open %s\n", buffer_access);
300 		ret = -errno;
301 		goto error_free_buffer_access;
302 	}
303 
304 	/* Wait for events 10 times */
305 	for (j = 0; j < num_loops; j++) {
306 		if (!noevents) {
307 			struct pollfd pfd = {
308 				.fd = fp,
309 				.events = POLLIN,
310 			};
311 
312 			poll(&pfd, 1, -1);
313 			toread = buf_len;
314 
315 		} else {
316 			usleep(timedelay);
317 			toread = 64;
318 		}
319 
320 		read_size = read(fp,
321 				 data,
322 				 toread*scan_size);
323 		if (read_size < 0) {
324 			if (errno == -EAGAIN) {
325 				printf("nothing available\n");
326 				continue;
327 			} else
328 				break;
329 		}
330 		for (i = 0; i < read_size/scan_size; i++)
331 			process_scan(data + scan_size*i,
332 				     channels,
333 				     num_channels);
334 	}
335 
336 	/* Stop the buffer */
337 	ret = write_sysfs_int("enable", buf_dir_name, 0);
338 	if (ret < 0)
339 		goto error_close_buffer_access;
340 
341 	if (!notrigger)
342 		/* Disconnect the trigger - just write a dummy name. */
343 		write_sysfs_string("trigger/current_trigger",
344 				   dev_dir_name, "NULL");
345 
346 error_close_buffer_access:
347 	close(fp);
348 error_free_data:
349 	free(data);
350 error_free_buffer_access:
351 	free(buffer_access);
352 error_free_buf_dir_name:
353 	free(buf_dir_name);
354 error_free_triggername:
355 	if (datardytrigger)
356 		free(trigger_name);
357 error_ret:
358 	return ret;
359 }
360