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