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