• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #define MY_NAME "iio_info"
27 
28 #ifdef _WIN32
29 #define snprintf sprintf_s
30 #endif
31 
32 enum backend {
33 	LOCAL,
34 	XML,
35 	NETWORK,
36 	AUTO,
37 };
38 
39 static const struct option options[] = {
40 	  {"help", no_argument, 0, 'h'},
41 	  {"xml", required_argument, 0, 'x'},
42 	  {"network", required_argument, 0, 'n'},
43 	  {"uri", required_argument, 0, 'u'},
44 	  {"scan", no_argument, 0, 's'},
45 	  {"auto", no_argument, 0, 'a'},
46 	  {0, 0, 0, 0},
47 };
48 
49 static const char *options_descriptions[] = {
50 	"Show this help and quit.",
51 	"Use the XML backend with the provided XML file.",
52 	"Use the network backend with the provided hostname.",
53 	"Use the context at the provided URI.",
54 	"Scan for available backends.",
55 	"Scan for available contexts and if only one is available use it.",
56 };
57 
usage(void)58 static void usage(void)
59 {
60 	unsigned int i;
61 
62 	printf("Usage:\n\t" MY_NAME " [-x <xml_file>]\n\t"
63 			MY_NAME " [-n <hostname>]\n\t"
64 			MY_NAME " [-u <uri>]\n\nOptions:\n");
65 	for (i = 0; options[i].name; i++)
66 		printf("\t-%c, --%s\n\t\t\t%s\n",
67 					options[i].val, options[i].name,
68 					options_descriptions[i]);
69 }
70 
scan(void)71 static void scan(void)
72 {
73 	struct iio_scan_context *ctx;
74 	struct iio_context_info **info;
75 	unsigned int i;
76 	ssize_t ret;
77 
78 	ctx = iio_create_scan_context(NULL, 0);
79 	if (!ctx) {
80 		fprintf(stderr, "Unable to create scan context\n");
81 		return;
82 	}
83 
84 	ret = iio_scan_context_get_info_list(ctx, &info);
85 	if (ret < 0) {
86 		fprintf(stderr, "Unable to scan: %li\n", (long) ret);
87 		goto err_free_ctx;
88 	}
89 
90 	if (ret == 0) {
91 		printf("No contexts found.\n");
92 		goto err_free_info_list;
93 	}
94 
95 	printf("Available contexts:\n");
96 
97 	for (i = 0; i < (size_t) ret; i++) {
98 		printf("\t%d: %s [%s]\n", i,
99 			iio_context_info_get_description(info[i]),
100 			iio_context_info_get_uri(info[i]));
101 	}
102 
103 err_free_info_list:
104 	iio_context_info_list_free(info);
105 err_free_ctx:
106 	iio_scan_context_destroy(ctx);
107 }
108 
autodetect_context(void)109 static struct iio_context * autodetect_context(void)
110 {
111 	struct iio_scan_context *scan_ctx;
112 	struct iio_context_info **info;
113 	struct iio_context *ctx = NULL;
114 	unsigned int i;
115 	ssize_t ret;
116 
117 	scan_ctx = iio_create_scan_context(NULL, 0);
118 	if (!scan_ctx) {
119 		fprintf(stderr, "Unable to create scan context\n");
120 		return NULL;
121 	}
122 
123 	ret = iio_scan_context_get_info_list(scan_ctx, &info);
124 	if (ret < 0) {
125 		char err_str[1024];
126 		iio_strerror(-ret, err_str, sizeof(err_str));
127 		fprintf(stderr, "Scanning for IIO contexts failed: %s\n", err_str);
128 		goto err_free_ctx;
129 	}
130 
131 	if (ret == 0) {
132 		printf("No IIO context found.\n");
133 		goto err_free_info_list;
134 	}
135 
136 	if (ret == 1) {
137 		printf("Using auto-detected IIO context at URI \"%s\"\n",
138 				iio_context_info_get_uri(info[0]));
139 		ctx = iio_create_context_from_uri(iio_context_info_get_uri(info[0]));
140 	} else {
141 		fprintf(stderr, "Multiple contexts found. Please select one using --uri:\n");
142 
143 		for (i = 0; i < (size_t) ret; i++) {
144 			fprintf(stderr, "\t%d: %s [%s]\n", i,
145 				iio_context_info_get_description(info[i]),
146 				iio_context_info_get_uri(info[i]));
147 		}
148 	}
149 
150 err_free_info_list:
151 	iio_context_info_list_free(info);
152 err_free_ctx:
153 	iio_scan_context_destroy(scan_ctx);
154 
155 	return ctx;
156 }
157 
dev_is_buffer_capable(const struct iio_device * dev)158 static int dev_is_buffer_capable(const struct iio_device *dev)
159 {
160 	unsigned int i;
161 
162 	for (i = 0; i < iio_device_get_channels_count(dev); i++) {
163 		struct iio_channel *chn = iio_device_get_channel(dev, i);
164 
165 		if (iio_channel_is_scan_element(chn))
166 			return true;
167 	}
168 
169 	return false;
170 }
171 
main(int argc,char ** argv)172 int main(int argc, char **argv)
173 {
174 	struct iio_context *ctx;
175 	int c, option_index = 0;
176 	const char *arg_uri = NULL;
177 	const char *arg_ip = NULL;
178 	const char *arg_xml = NULL;
179 	enum backend backend = LOCAL;
180 	bool do_scan = false, detect_context = false;
181 	unsigned int i, major, minor;
182 	char git_tag[8];
183 	int ret;
184 
185 	while ((c = getopt_long(argc, argv, "+hn:x:u:sa",
186 					options, &option_index)) != -1) {
187 		switch (c) {
188 		case 'h':
189 			usage();
190 			return EXIT_SUCCESS;
191 		case 'n':
192 			if (backend != LOCAL) {
193 				fprintf(stderr, "-x, -n and -u are mutually exclusive\n");
194 				return EXIT_FAILURE;
195 			}
196 			backend = NETWORK;
197 			arg_ip = optarg;
198 			break;
199 		case 'x':
200 			if (backend != LOCAL) {
201 				fprintf(stderr, "-x, -n and -u are mutually exclusive\n");
202 				return EXIT_FAILURE;
203 			}
204 			backend = XML;
205 			arg_xml = optarg;
206 			break;
207 		case 's':
208 			do_scan = true;
209 			break;
210 		case 'u':
211 			if (backend != LOCAL) {
212 				fprintf(stderr, "-x, -n and -u are mutually exclusive\n");
213 				return EXIT_FAILURE;
214 			}
215 			backend = AUTO;
216 			arg_uri = optarg;
217 			break;
218 		case 'a':
219 			detect_context = true;
220 			break;
221 		case '?':
222 			return EXIT_FAILURE;
223 		}
224 	}
225 
226 	if (optind != argc) {
227 		fprintf(stderr, "Incorrect number of arguments.\n\n");
228 		usage();
229 		return EXIT_FAILURE;
230 	}
231 
232 	iio_library_get_version(&major, &minor, git_tag);
233 	printf("Library version: %u.%u (git tag: %s)\n", major, minor, git_tag);
234 
235 	printf("Compiled with backends:");
236 	for (i = 0; i < iio_get_backends_count(); i++)
237 		printf(" %s", iio_get_backend(i));
238 	printf("\n");
239 
240 	if (do_scan) {
241 		scan();
242 		return EXIT_SUCCESS;
243 	}
244 
245 	if (detect_context)
246 		ctx = autodetect_context();
247 	else if (backend == XML)
248 		ctx = iio_create_xml_context(arg_xml);
249 	else if (backend == NETWORK)
250 		ctx = iio_create_network_context(arg_ip);
251 	else if (backend == AUTO)
252 		ctx = iio_create_context_from_uri(arg_uri);
253 	else
254 		ctx = iio_create_default_context();
255 
256 	if (!ctx) {
257 		if (!detect_context) {
258 			char buf[1024];
259 
260 			iio_strerror(errno, buf, sizeof(buf));
261 			fprintf(stderr, "Unable to create IIO context: %s\n",
262 					buf);
263 		}
264 
265 		return EXIT_FAILURE;
266 	}
267 
268 	printf("IIO context created with %s backend.\n",
269 			iio_context_get_name(ctx));
270 
271 	ret = iio_context_get_version(ctx, &major, &minor, git_tag);
272 	if (!ret)
273 		printf("Backend version: %u.%u (git tag: %s)\n",
274 				major, minor, git_tag);
275 	else
276 		fprintf(stderr, "Unable to get backend version: %i\n", ret);
277 
278 	printf("Backend description string: %s\n",
279 			iio_context_get_description(ctx));
280 
281 	unsigned int nb_ctx_attrs = iio_context_get_attrs_count(ctx);
282 	if (nb_ctx_attrs > 0)
283 		printf("IIO context has %u attributes:\n", nb_ctx_attrs);
284 
285 	for (i = 0; i < nb_ctx_attrs; i++) {
286 		const char *key, *value;
287 
288 		iio_context_get_attr(ctx, i, &key, &value);
289 		printf("\t%s: %s\n", key, value);
290 	}
291 
292 	unsigned int nb_devices = iio_context_get_devices_count(ctx);
293 	printf("IIO context has %u devices:\n", nb_devices);
294 
295 	for (i = 0; i < nb_devices; i++) {
296 		const struct iio_device *dev = iio_context_get_device(ctx, i);
297 		const char *name = iio_device_get_name(dev);
298 		printf("\t%s:", iio_device_get_id(dev));
299 		if (name)
300 			printf(" %s", name);
301 		if (dev_is_buffer_capable(dev))
302 			printf(" (buffer capable)");
303 		printf("\n");
304 
305 		unsigned int nb_channels = iio_device_get_channels_count(dev);
306 		printf("\t\t%u channels found:\n", nb_channels);
307 
308 		unsigned int j;
309 		for (j = 0; j < nb_channels; j++) {
310 			struct iio_channel *ch = iio_device_get_channel(dev, j);
311 			const char *type_name;
312 
313 			if (iio_channel_is_output(ch))
314 				type_name = "output";
315 			else
316 				type_name = "input";
317 
318 			name = iio_channel_get_name(ch);
319 			printf("\t\t\t%s: %s (%s",
320 					iio_channel_get_id(ch),
321 					name ? name : "", type_name);
322 
323 			if (iio_channel_is_scan_element(ch)) {
324 				const struct iio_data_format *format =
325 					iio_channel_get_data_format(ch);
326 				char sign = format->is_signed ? 's' : 'u';
327 				char repeat[12] = "";
328 
329 				if (format->is_fully_defined)
330 					sign += 'A' - 'a';
331 
332 				if (format->repeat > 1)
333 					snprintf(repeat, sizeof(repeat), "X%u",
334 						format->repeat);
335 
336 				printf(", index: %lu, format: %ce:%c%u/%u%s>>%u)\n",
337 					iio_channel_get_index(ch),
338 					format->is_be ? 'b' : 'l',
339 					sign, format->bits,
340 					format->length, repeat,
341 					format->shift);
342 			} else {
343 				printf(")\n");
344 			}
345 
346 			unsigned int nb_attrs = iio_channel_get_attrs_count(ch);
347 			if (!nb_attrs)
348 				continue;
349 
350 			printf("\t\t\t%u channel-specific attributes found:\n",
351 					nb_attrs);
352 
353 			unsigned int k;
354 			for (k = 0; k < nb_attrs; k++) {
355 				const char *attr = iio_channel_get_attr(ch, k);
356 				char buf[1024];
357 				ret = (int) iio_channel_attr_read(ch,
358 						attr, buf, sizeof(buf));
359 
360 				printf("\t\t\t\tattr %2u: %s ", k, attr);
361 
362 				if (ret > 0) {
363 					printf("value: %s\n", buf);
364 				} else {
365 					iio_strerror(-ret, buf, sizeof(buf));
366 					printf("ERROR: %s (%i)\n", buf, ret);
367 				}
368 			}
369 		}
370 
371 		unsigned int nb_attrs = iio_device_get_attrs_count(dev);
372 		if (nb_attrs) {
373 			printf("\t\t%u device-specific attributes found:\n",
374 					nb_attrs);
375 			for (j = 0; j < nb_attrs; j++) {
376 				const char *attr = iio_device_get_attr(dev, j);
377 				char buf[1024];
378 				ret = (int) iio_device_attr_read(dev,
379 						attr, buf, sizeof(buf));
380 
381 				printf("\t\t\t\tattr %2u: %s ",
382 						j, attr);
383 
384 				if (ret > 0) {
385 					printf("value: %s\n", buf);
386 				} else {
387 					iio_strerror(-ret, buf, sizeof(buf));
388 					printf("ERROR: %s (%i)\n", buf, ret);
389 				}
390 			}
391 		}
392 
393 		nb_attrs = iio_device_get_buffer_attrs_count(dev);
394 		if (nb_attrs) {
395 			printf("\t\t%u buffer-specific attributes found:\n",
396 					nb_attrs);
397 			for (j = 0; j < nb_attrs; j++) {
398 				const char *attr = iio_device_get_buffer_attr(dev, j);
399 				char buf[1024];
400 				ret = (int) iio_device_buffer_attr_read(dev,
401 						attr, buf, sizeof(buf));
402 
403 				printf("\t\t\t\tattr %2u: %s ",
404 						j, attr);
405 
406 				if (ret > 0) {
407 					printf("value: %s\n", buf);
408 				} else {
409 					iio_strerror(-ret, buf, sizeof(buf));
410 					printf("ERROR: %s (%i)\n", buf, ret);
411 				}
412 			}
413 		}
414 
415 		nb_attrs = iio_device_get_debug_attrs_count(dev);
416 		if (nb_attrs) {
417 			printf("\t\t%u debug attributes found:\n", nb_attrs);
418 			for (j = 0; j < nb_attrs; j++) {
419 				const char *attr =
420 					iio_device_get_debug_attr(dev, j);
421 				char buf[1024];
422 
423 				ret = (int) iio_device_debug_attr_read(dev,
424 						attr, buf, sizeof(buf));
425 				printf("\t\t\t\tdebug attr %2u: %s ",
426 						j, attr);
427 				if (ret > 0) {
428 					printf("value: %s\n", buf);
429 				} else {
430 					iio_strerror(-ret, buf, sizeof(buf));
431 					printf("ERROR: %s (%i)\n", buf, ret);
432 				}
433 			}
434 		}
435 
436 		const struct iio_device *trig;
437 		ret = iio_device_get_trigger(dev, &trig);
438 		if (ret == 0) {
439 			if (trig == NULL) {
440 				printf("\t\tNo trigger assigned to device\n");
441 			} else {
442 				name = iio_device_get_name(trig);
443 				printf("\t\tCurrent trigger: %s(%s)\n",
444 						iio_device_get_id(trig),
445 						name ? name : "");
446 			}
447 		}
448 	}
449 
450 	iio_context_destroy(ctx);
451 	return EXIT_SUCCESS;
452 }
453