• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libiio - Library for interfacing industrial I/O (IIO) devices
3  *
4  * Copyright (C) 2014-2018 Analog Devices, Inc.
5  * Author: Paul Cercueil <paul.cercueil@analog.com>
6  *         that Michael Hennerich <michael.hennerich@analog.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * */
19 
20 #include <errno.h>
21 #include <getopt.h>
22 #include <iio.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <errno.h>
27 
28 #ifdef _WIN32
29 #include <windows.h>
30 #include <fcntl.h>
31 #include <io.h>
32 #else
33 #include <unistd.h>
34 #endif
35 
36 #define MY_NAME "iio_writedev"
37 
38 #define SAMPLES_PER_READ 256
39 #define DEFAULT_FREQ_HZ  100
40 
41 static const struct option options[] = {
42 	  {"help", no_argument, 0, 'h'},
43 	  {"network", required_argument, 0, 'n'},
44 	  {"uri", required_argument, 0, 'u'},
45 	  {"trigger", required_argument, 0, 't'},
46 	  {"buffer-size", required_argument, 0, 'b'},
47 	  {"samples", required_argument, 0, 's' },
48 	  {"timeout", required_argument, 0, 'T'},
49 	  {"auto", no_argument, 0, 'a'},
50 	  {"cyclic", no_argument, 0, 'c'},
51 	  {0, 0, 0, 0},
52 };
53 
54 static const char *options_descriptions[] = {
55 	"Show this help and quit.",
56 	"Use the network backend with the provided hostname.",
57 	"Use the context with the provided URI.",
58 	"Use the specified trigger.",
59 	"Size of the capture buffer. Default is 256.",
60 	"Number of samples to write, 0 = infinite. Default is 0.",
61 	"Buffer timeout in milliseconds. 0 = no timeout",
62 	"Scan for available contexts and if only one is available use it.",
63 	"Use cyclic buffer mode.",
64 };
65 
usage(void)66 static void usage(void)
67 {
68 	unsigned int i;
69 
70 	printf("Usage:\n\t" MY_NAME " [-n <hostname>] [-t <trigger>] "
71 			"[-T <timeout-ms>] [-b <buffer-size>] [-s <samples>] "
72 			"<iio_device> [<channel> ...]\n\nOptions:\n");
73 	for (i = 0; options[i].name; i++)
74 		printf("\t-%c, --%s\n\t\t\t%s\n",
75 					options[i].val, options[i].name,
76 					options_descriptions[i]);
77 }
78 
79 static struct iio_context *ctx;
80 static struct iio_buffer *buffer;
81 static const char *trigger_name = NULL;
82 static size_t num_samples;
83 
84 static volatile sig_atomic_t app_running = true;
85 static int exit_code = EXIT_SUCCESS;
86 
quit_all(int sig)87 static void quit_all(int sig)
88 {
89 	exit_code = sig;
90 	app_running = false;
91 	if (buffer)
92 		iio_buffer_cancel(buffer);
93 }
94 
95 #ifdef _WIN32
96 
97 #include <windows.h>
98 
sig_handler_fn(DWORD dwCtrlType)99 BOOL WINAPI sig_handler_fn(DWORD dwCtrlType)
100 {
101 	/* Runs in its own thread */
102 
103 	switch (dwCtrlType) {
104 	case CTRL_C_EVENT:
105 	case CTRL_CLOSE_EVENT:
106 		quit_all(SIGTERM);
107 		return TRUE;
108 	default:
109 		return FALSE;
110 	}
111 }
112 
setup_sig_handler(void)113 static void setup_sig_handler(void)
114 {
115 	SetConsoleCtrlHandler(sig_handler_fn, TRUE);
116 }
117 
118 #elif NO_THREADS
119 
sig_handler(int sig)120 static void sig_handler(int sig)
121 {
122 	/*
123 	 * If the main function is stuck waiting for data it will not abort. If the
124 	 * user presses Ctrl+C a second time we abort without cleaning up.
125 	 */
126 	if (!app_running)
127 		exit(sig);
128 	app_running = false;
129 }
130 
set_handler(int sig)131 static void set_handler(int sig)
132 {
133 	struct sigaction action;
134 
135 	sigaction(sig, NULL, &action);
136 	action.sa_handler = sig_handler;
137 	sigaction(sig, &action, NULL);
138 }
139 
setup_sig_handler(void)140 static void setup_sig_handler(void)
141 {
142 	set_handler(SIGHUP);
143 	set_handler(SIGPIPE);
144 	set_handler(SIGINT);
145 	set_handler(SIGSEGV);
146 	set_handler(SIGTERM);
147 }
148 
149 #else
150 
151 #include <pthread.h>
152 
sig_handler_thd(void * data)153 static void * sig_handler_thd(void *data)
154 {
155 	sigset_t *mask = data;
156 	int ret, sig;
157 
158 	/* Blocks until one of the termination signals is received */
159 	do {
160 		ret = sigwait(mask, &sig);
161 	} while (ret == EINTR);
162 
163 	quit_all(ret);
164 
165 	return NULL;
166 }
167 
setup_sig_handler(void)168 static void setup_sig_handler(void)
169 {
170 	sigset_t mask, oldmask;
171 	pthread_t thd;
172 	int ret;
173 
174 	/*
175 	 * Async signals are difficult to handle and the IIO API is not signal
176 	 * safe. Use a seperate thread and handle the signals synchronous so we
177 	 * can call iio_buffer_cancel().
178 	 */
179 
180 	sigemptyset(&mask);
181 	sigaddset(&mask, SIGHUP);
182 	sigaddset(&mask, SIGPIPE);
183 	sigaddset(&mask, SIGINT);
184 	sigaddset(&mask, SIGSEGV);
185 	sigaddset(&mask, SIGTERM);
186 
187 	pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
188 
189 	ret = pthread_create(&thd, NULL, sig_handler_thd, &mask);
190 	if (ret) {
191 		fprintf(stderr, "Failed to create signal handler thread: %d\n", ret);
192 		pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
193 	}
194 }
195 
196 #endif
197 
read_sample(const struct iio_channel * chn,void * buf,size_t len,void * d)198 static ssize_t read_sample(const struct iio_channel *chn,
199 		void *buf, size_t len, void *d)
200 {
201 	size_t nb = fread(buf, 1, len, stdin);
202 	if (num_samples != 0) {
203 		num_samples--;
204 		if (num_samples == 0) {
205 			quit_all(EXIT_SUCCESS);
206 			return -1;
207 		}
208 	}
209 	return (ssize_t) nb;
210 }
211 
scan(void)212 static struct iio_context *scan(void)
213 {
214 	struct iio_scan_context *scan_ctx;
215 	struct iio_context_info **info;
216 	struct iio_context *ctx = NULL;
217 	unsigned int i;
218 	ssize_t ret;
219 
220 	scan_ctx = iio_create_scan_context(NULL, 0);
221 	if (!scan_ctx) {
222 		fprintf(stderr, "Unable to create scan context\n");
223 		return NULL;
224 	}
225 
226 	ret = iio_scan_context_get_info_list(scan_ctx, &info);
227 	if (ret < 0) {
228 		char err_str[1024];
229 		iio_strerror(-ret, err_str, sizeof(err_str));
230 		fprintf(stderr, "Scanning for IIO contexts failed: %s\n", err_str);
231 		goto err_free_ctx;
232 	}
233 
234 	if (ret == 0) {
235 		printf("No IIO context found.\n");
236 		goto err_free_info_list;
237 	}
238 
239 	if (ret == 1) {
240 		ctx = iio_create_context_from_uri(iio_context_info_get_uri(info[0]));
241 	} else {
242 		fprintf(stderr, "Multiple contexts found. Please select one using --uri:\n");
243 
244 		for (i = 0; i < (size_t) ret; i++) {
245 			fprintf(stderr, "\t%d: %s [%s]\n", i,
246 				iio_context_info_get_description(info[i]),
247 				iio_context_info_get_uri(info[i]));
248 		}
249 	}
250 
251 err_free_info_list:
252 	iio_context_info_list_free(info);
253 err_free_ctx:
254 	iio_scan_context_destroy(scan_ctx);
255 
256 	return ctx;
257 }
258 
main(int argc,char ** argv)259 int main(int argc, char **argv)
260 {
261 	unsigned int i, nb_channels;
262 	unsigned int buffer_size = SAMPLES_PER_READ;
263 	const char *arg_uri = NULL;
264 	const char *arg_ip = NULL;
265 	int c, option_index = 0;
266 	struct iio_device *dev;
267 	size_t sample_size;
268 	int timeout = -1;
269 	bool scan_for_context = false;
270 	bool cyclic_buffer = false;
271 
272 	while ((c = getopt_long(argc, argv, "+hn:u:t:b:s:T:ac",
273 					options, &option_index)) != -1) {
274 		switch (c) {
275 		case 'h':
276 			usage();
277 			return EXIT_SUCCESS;
278 		case 'n':
279 			arg_ip = optarg;
280 			break;
281 		case 'u':
282 			arg_uri = optarg;
283 			break;
284 		case 'a':
285 			scan_for_context = true;
286 			break;
287 		case 't':
288 			trigger_name = optarg;
289 			break;
290 		case 'b':
291 			buffer_size = atoi(optarg);
292 			break;
293 		case 's':
294 			num_samples = atoi(optarg);
295 			break;
296 		case 'T':
297 			timeout = atoi(optarg);
298 			break;
299 		case 'c':
300 			cyclic_buffer = true;
301 			break;
302 		case '?':
303 			return EXIT_FAILURE;
304 		}
305 	}
306 
307 	if (argc == optind) {
308 		fprintf(stderr, "Incorrect number of arguments.\n\n");
309 		usage();
310 		return EXIT_FAILURE;
311 	}
312 
313 	setup_sig_handler();
314 
315 	if (scan_for_context)
316 		ctx = scan();
317 	else if (arg_uri)
318 		ctx = iio_create_context_from_uri(arg_uri);
319 	else if (arg_ip)
320 		ctx = iio_create_network_context(arg_ip);
321 	else
322 		ctx = iio_create_default_context();
323 
324 	if (!ctx) {
325 		fprintf(stderr, "Unable to create IIO context\n");
326 		return EXIT_FAILURE;
327 	}
328 
329 	if (timeout >= 0)
330 		iio_context_set_timeout(ctx, timeout);
331 
332 	dev = iio_context_find_device(ctx, argv[optind]);
333 	if (!dev) {
334 		fprintf(stderr, "Device %s not found\n", argv[optind]);
335 		iio_context_destroy(ctx);
336 		return EXIT_FAILURE;
337 	}
338 
339 	if (trigger_name) {
340 		struct iio_device *trigger = iio_context_find_device(
341 				ctx, trigger_name);
342 		if (!trigger) {
343 			fprintf(stderr, "Trigger %s not found\n", trigger_name);
344 			iio_context_destroy(ctx);
345 			return EXIT_FAILURE;
346 		}
347 
348 		if (!iio_device_is_trigger(trigger)) {
349 			fprintf(stderr, "Specified device is not a trigger\n");
350 			iio_context_destroy(ctx);
351 			return EXIT_FAILURE;
352 		}
353 
354 		/*
355 		 * Fixed rate for now. Try new ABI first,
356 		 * fail gracefully to remain compatible.
357 		 */
358 		if (iio_device_attr_write_longlong(trigger,
359 				"sampling_frequency", DEFAULT_FREQ_HZ) < 0)
360 			iio_device_attr_write_longlong(trigger,
361 				"frequency", DEFAULT_FREQ_HZ);
362 
363 		iio_device_set_trigger(dev, trigger);
364 	}
365 
366 	nb_channels = iio_device_get_channels_count(dev);
367 
368 	if (argc == optind + 1) {
369 		/* Enable all channels */
370 		for (i = 0; i < nb_channels; i++)
371 			iio_channel_enable(iio_device_get_channel(dev, i));
372 	} else {
373 		for (i = 0; i < nb_channels; i++) {
374 			unsigned int j;
375 			struct iio_channel *ch = iio_device_get_channel(dev, i);
376 			for (j = optind + 1; j < (unsigned int) argc; j++) {
377 				const char *n = iio_channel_get_name(ch);
378 				if (!strcmp(argv[j], iio_channel_get_id(ch)) ||
379 						(n && !strcmp(n, argv[j])))
380 					iio_channel_enable(ch);
381 			}
382 		}
383 	}
384 
385 	sample_size = iio_device_get_sample_size(dev);
386 
387 	buffer = iio_device_create_buffer(dev, buffer_size, cyclic_buffer);
388 	if (!buffer) {
389 		char buf[256];
390 		iio_strerror(errno, buf, sizeof(buf));
391 		fprintf(stderr, "Unable to allocate buffer: %s\n", buf);
392 		iio_context_destroy(ctx);
393 		return EXIT_FAILURE;
394 	}
395 
396 #ifdef _WIN32
397 	_setmode(_fileno( stdin ), _O_BINARY);
398 #endif
399 
400 	while (app_running) {
401 		/* If there are only the samples we requested, we don't need to
402 		 * demux */
403 		if (iio_buffer_step(buffer) == sample_size) {
404 			void *start = iio_buffer_start(buffer);
405 			size_t write_len, len = (intptr_t) iio_buffer_end(buffer)
406 				- (intptr_t) start;
407 
408 			if (num_samples && len > num_samples * sample_size)
409 				len = num_samples * sample_size;
410 
411 			for (write_len = len; len; ) {
412 				size_t nb = fread(start, 1, len, stdin);
413 				if (!nb)
414 					goto err_destroy_buffer;
415 
416 				len -= nb;
417 				start = (void *)((intptr_t) start + nb);
418 			}
419 
420 			if (num_samples) {
421 				num_samples -= write_len / sample_size;
422 				if (!num_samples)
423 					quit_all(EXIT_SUCCESS);
424 			}
425 		} else {
426 			iio_buffer_foreach_sample(buffer, read_sample, NULL);
427 		}
428 
429 		int ret = iio_buffer_push(buffer);
430 		if (ret < 0) {
431 			if (app_running) {
432 				char buf[256];
433 				iio_strerror(-ret, buf, sizeof(buf));
434 				fprintf(stderr, "Unable to push buffer: %s\n", buf);
435 			}
436 			break;
437 		}
438 
439 		while(cyclic_buffer && app_running) {
440 #ifdef _WIN32
441 			Sleep(1000);
442 #else
443 			sleep(1);
444 #endif
445 		}
446 	}
447 
448 
449 err_destroy_buffer:
450 	iio_buffer_destroy(buffer);
451 	iio_context_destroy(ctx);
452 	return exit_code;
453 }
454