aboutsummaryrefslogtreecommitdiffstats
path: root/tools/iio
diff options
context:
space:
mode:
Diffstat (limited to 'tools/iio')
-rw-r--r--tools/iio/Makefile16
-rw-r--r--tools/iio/generic_buffer.c361
-rw-r--r--tools/iio/iio_event_monitor.c310
-rw-r--r--tools/iio/iio_utils.c651
-rw-r--r--tools/iio/iio_utils.h71
-rw-r--r--tools/iio/lsiio.c163
6 files changed, 1572 insertions, 0 deletions
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
new file mode 100644
index 000000000000..83813ad379f9
--- /dev/null
+++ b/tools/iio/Makefile
@@ -0,0 +1,16 @@
1CC = gcc
2CFLAGS = -Wall -g
3
4all: iio_event_monitor lsiio generic_buffer
5
6iio_event_monitor: iio_event_monitor.o iio_utils.o
7
8lsiio: lsiio.o iio_utils.o
9
10generic_buffer: generic_buffer.o iio_utils.o
11
12%.o: %.c iio_utils.h
13
14.PHONY: clean
15clean:
16 rm -f *.o iio_event_monitor lsiio generic_buffer
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
new file mode 100644
index 000000000000..01266c2556da
--- /dev/null
+++ b/tools/iio/generic_buffer.c
@@ -0,0 +1,361 @@
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#define _GNU_SOURCE
22
23#include <unistd.h>
24#include <stdlib.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <stdio.h>
28#include <errno.h>
29#include <sys/stat.h>
30#include <sys/dir.h>
31#include <linux/types.h>
32#include <string.h>
33#include <poll.h>
34#include <endian.h>
35#include <getopt.h>
36#include <inttypes.h>
37#include "iio_utils.h"
38
39/**
40 * size_from_channelarray() - calculate the storage size of a scan
41 * @channels: the channel info array
42 * @num_channels: number of channels
43 *
44 * Has the side effect of filling the channels[i].location values used
45 * in processing the buffer output.
46 **/
47int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
48{
49 int bytes = 0;
50 int i = 0;
51
52 while (i < num_channels) {
53 if (bytes % channels[i].bytes == 0)
54 channels[i].location = bytes;
55 else
56 channels[i].location = bytes - bytes%channels[i].bytes
57 + channels[i].bytes;
58 bytes = channels[i].location + channels[i].bytes;
59 i++;
60 }
61 return bytes;
62}
63
64void print2byte(int input, struct iio_channel_info *info)
65{
66 /* First swap if incorrect endian */
67 if (info->be)
68 input = be16toh((uint16_t)input);
69 else
70 input = le16toh((uint16_t)input);
71
72 /*
73 * Shift before conversion to avoid sign extension
74 * of left aligned data
75 */
76 input = input >> info->shift;
77 if (info->is_signed) {
78 int16_t val = input;
79
80 val &= (1 << info->bits_used) - 1;
81 val = (int16_t)(val << (16 - info->bits_used)) >>
82 (16 - info->bits_used);
83 printf("%05f ", ((float)val + info->offset)*info->scale);
84 } else {
85 uint16_t val = input;
86
87 val &= (1 << info->bits_used) - 1;
88 printf("%05f ", ((float)val + info->offset)*info->scale);
89 }
90}
91/**
92 * process_scan() - print out the values in SI units
93 * @data: pointer to the start of the scan
94 * @channels: information about the channels. Note
95 * size_from_channelarray must have been called first to fill the
96 * location offsets.
97 * @num_channels: number of channels
98 **/
99void process_scan(char *data,
100 struct iio_channel_info *channels,
101 int num_channels)
102{
103 int k;
104
105 for (k = 0; k < num_channels; k++)
106 switch (channels[k].bytes) {
107 /* only a few cases implemented so far */
108 case 2:
109 print2byte(*(uint16_t *)(data + channels[k].location),
110 &channels[k]);
111 break;
112 case 4:
113 if (!channels[k].is_signed) {
114 uint32_t val = *(uint32_t *)
115 (data + channels[k].location);
116 printf("%05f ", ((float)val +
117 channels[k].offset)*
118 channels[k].scale);
119
120 }
121 break;
122 case 8:
123 if (channels[k].is_signed) {
124 int64_t val = *(int64_t *)
125 (data +
126 channels[k].location);
127 if ((val >> channels[k].bits_used) & 1)
128 val = (val & channels[k].mask) |
129 ~channels[k].mask;
130 /* special case for timestamp */
131 if (channels[k].scale == 1.0f &&
132 channels[k].offset == 0.0f)
133 printf("%" PRId64 " ", val);
134 else
135 printf("%05f ", ((float)val +
136 channels[k].offset)*
137 channels[k].scale);
138 }
139 break;
140 default:
141 break;
142 }
143 printf("\n");
144}
145
146int main(int argc, char **argv)
147{
148 unsigned long num_loops = 2;
149 unsigned long timedelay = 1000000;
150 unsigned long buf_len = 128;
151
152 int ret, c, i, j, toread;
153 int fp;
154
155 int num_channels;
156 char *trigger_name = NULL, *device_name = NULL;
157 char *dev_dir_name, *buf_dir_name;
158
159 int datardytrigger = 1;
160 char *data;
161 ssize_t read_size;
162 int dev_num, trig_num;
163 char *buffer_access;
164 int scan_size;
165 int noevents = 0;
166 int notrigger = 0;
167 char *dummy;
168
169 struct iio_channel_info *channels;
170
171 while ((c = getopt(argc, argv, "l:w:c:et:n:g")) != -1) {
172 switch (c) {
173 case 'n':
174 device_name = optarg;
175 break;
176 case 't':
177 trigger_name = optarg;
178 datardytrigger = 0;
179 break;
180 case 'e':
181 noevents = 1;
182 break;
183 case 'c':
184 num_loops = strtoul(optarg, &dummy, 10);
185 break;
186 case 'w':
187 timedelay = strtoul(optarg, &dummy, 10);
188 break;
189 case 'l':
190 buf_len = strtoul(optarg, &dummy, 10);
191 break;
192 case 'g':
193 notrigger = 1;
194 break;
195 case '?':
196 return -1;
197 }
198 }
199
200 if (device_name == NULL)
201 return -1;
202
203 /* Find the device requested */
204 dev_num = find_type_by_name(device_name, "iio:device");
205 if (dev_num < 0) {
206 printf("Failed to find the %s\n", device_name);
207 ret = -ENODEV;
208 goto error_ret;
209 }
210 printf("iio device number being used is %d\n", dev_num);
211
212 asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
213
214 if (!notrigger) {
215 if (trigger_name == NULL) {
216 /*
217 * Build the trigger name. If it is device associated
218 * its name is <device_name>_dev[n] where n matches
219 * the device number found above.
220 */
221 ret = asprintf(&trigger_name,
222 "%s-dev%d", device_name, dev_num);
223 if (ret < 0) {
224 ret = -ENOMEM;
225 goto error_ret;
226 }
227 }
228
229 /* Verify the trigger exists */
230 trig_num = find_type_by_name(trigger_name, "trigger");
231 if (trig_num < 0) {
232 printf("Failed to find the trigger %s\n", trigger_name);
233 ret = -ENODEV;
234 goto error_free_triggername;
235 }
236 printf("iio trigger number being used is %d\n", trig_num);
237 } else
238 printf("trigger-less mode selected\n");
239
240 /*
241 * Parse the files in scan_elements to identify what channels are
242 * present
243 */
244 ret = build_channel_array(dev_dir_name, &channels, &num_channels);
245 if (ret) {
246 printf("Problem reading scan element information\n");
247 printf("diag %s\n", dev_dir_name);
248 goto error_free_triggername;
249 }
250
251 /*
252 * Construct the directory name for the associated buffer.
253 * As we know that the lis3l02dq has only one buffer this may
254 * be built rather than found.
255 */
256 ret = asprintf(&buf_dir_name,
257 "%siio:device%d/buffer", iio_dir, dev_num);
258 if (ret < 0) {
259 ret = -ENOMEM;
260 goto error_free_triggername;
261 }
262
263 if (!notrigger) {
264 printf("%s %s\n", dev_dir_name, trigger_name);
265 /* Set the device trigger to be the data ready trigger found
266 * above */
267 ret = write_sysfs_string_and_verify("trigger/current_trigger",
268 dev_dir_name,
269 trigger_name);
270 if (ret < 0) {
271 printf("Failed to write current_trigger file\n");
272 goto error_free_buf_dir_name;
273 }
274 }
275
276 /* Setup ring buffer parameters */
277 ret = write_sysfs_int("length", buf_dir_name, buf_len);
278 if (ret < 0)
279 goto error_free_buf_dir_name;
280
281 /* Enable the buffer */
282 ret = write_sysfs_int("enable", buf_dir_name, 1);
283 if (ret < 0)
284 goto error_free_buf_dir_name;
285 scan_size = size_from_channelarray(channels, num_channels);
286 data = malloc(scan_size*buf_len);
287 if (!data) {
288 ret = -ENOMEM;
289 goto error_free_buf_dir_name;
290 }
291
292 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
293 if (ret < 0) {
294 ret = -ENOMEM;
295 goto error_free_data;
296 }
297
298 /* Attempt to open non blocking the access dev */
299 fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
300 if (fp == -1) { /* If it isn't there make the node */
301 printf("Failed to open %s\n", buffer_access);
302 ret = -errno;
303 goto error_free_buffer_access;
304 }
305
306 /* Wait for events 10 times */
307 for (j = 0; j < num_loops; j++) {
308 if (!noevents) {
309 struct pollfd pfd = {
310 .fd = fp,
311 .events = POLLIN,
312 };
313
314 poll(&pfd, 1, -1);
315 toread = buf_len;
316
317 } else {
318 usleep(timedelay);
319 toread = 64;
320 }
321
322 read_size = read(fp,
323 data,
324 toread*scan_size);
325 if (read_size < 0) {
326 if (errno == -EAGAIN) {
327 printf("nothing available\n");
328 continue;
329 } else
330 break;
331 }
332 for (i = 0; i < read_size/scan_size; i++)
333 process_scan(data + scan_size*i,
334 channels,
335 num_channels);
336 }
337
338 /* Stop the buffer */
339 ret = write_sysfs_int("enable", buf_dir_name, 0);
340 if (ret < 0)
341 goto error_close_buffer_access;
342
343 if (!notrigger)
344 /* Disconnect the trigger - just write a dummy name. */
345 write_sysfs_string("trigger/current_trigger",
346 dev_dir_name, "NULL");
347
348error_close_buffer_access:
349 close(fp);
350error_free_data:
351 free(data);
352error_free_buffer_access:
353 free(buffer_access);
354error_free_buf_dir_name:
355 free(buf_dir_name);
356error_free_triggername:
357 if (datardytrigger)
358 free(trigger_name);
359error_ret:
360 return ret;
361}
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
new file mode 100644
index 000000000000..f19cff19900e
--- /dev/null
+++ b/tools/iio/iio_event_monitor.c
@@ -0,0 +1,310 @@
1/* Industrialio event test code.
2 *
3 * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.de>
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 * Usage:
15 * iio_event_monitor <device_name>
16 *
17 */
18
19#define _GNU_SOURCE
20
21#include <unistd.h>
22#include <stdlib.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <errno.h>
26#include <string.h>
27#include <poll.h>
28#include <fcntl.h>
29#include <sys/ioctl.h>
30#include "iio_utils.h"
31#include <linux/iio/events.h>
32#include <linux/iio/types.h>
33
34static const char * const iio_chan_type_name_spec[] = {
35 [IIO_VOLTAGE] = "voltage",
36 [IIO_CURRENT] = "current",
37 [IIO_POWER] = "power",
38 [IIO_ACCEL] = "accel",
39 [IIO_ANGL_VEL] = "anglvel",
40 [IIO_MAGN] = "magn",
41 [IIO_LIGHT] = "illuminance",
42 [IIO_INTENSITY] = "intensity",
43 [IIO_PROXIMITY] = "proximity",
44 [IIO_TEMP] = "temp",
45 [IIO_INCLI] = "incli",
46 [IIO_ROT] = "rot",
47 [IIO_ANGL] = "angl",
48 [IIO_TIMESTAMP] = "timestamp",
49 [IIO_CAPACITANCE] = "capacitance",
50 [IIO_ALTVOLTAGE] = "altvoltage",
51 [IIO_CCT] = "cct",
52 [IIO_PRESSURE] = "pressure",
53 [IIO_HUMIDITYRELATIVE] = "humidityrelative",
54 [IIO_ACTIVITY] = "activity",
55 [IIO_STEPS] = "steps",
56};
57
58static const char * const iio_ev_type_text[] = {
59 [IIO_EV_TYPE_THRESH] = "thresh",
60 [IIO_EV_TYPE_MAG] = "mag",
61 [IIO_EV_TYPE_ROC] = "roc",
62 [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
63 [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
64 [IIO_EV_TYPE_CHANGE] = "change",
65};
66
67static const char * const iio_ev_dir_text[] = {
68 [IIO_EV_DIR_EITHER] = "either",
69 [IIO_EV_DIR_RISING] = "rising",
70 [IIO_EV_DIR_FALLING] = "falling"
71};
72
73static const char * const iio_modifier_names[] = {
74 [IIO_MOD_X] = "x",
75 [IIO_MOD_Y] = "y",
76 [IIO_MOD_Z] = "z",
77 [IIO_MOD_X_AND_Y] = "x&y",
78 [IIO_MOD_X_AND_Z] = "x&z",
79 [IIO_MOD_Y_AND_Z] = "y&z",
80 [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
81 [IIO_MOD_X_OR_Y] = "x|y",
82 [IIO_MOD_X_OR_Z] = "x|z",
83 [IIO_MOD_Y_OR_Z] = "y|z",
84 [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
85 [IIO_MOD_LIGHT_BOTH] = "both",
86 [IIO_MOD_LIGHT_IR] = "ir",
87 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
88 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
89 [IIO_MOD_LIGHT_CLEAR] = "clear",
90 [IIO_MOD_LIGHT_RED] = "red",
91 [IIO_MOD_LIGHT_GREEN] = "green",
92 [IIO_MOD_LIGHT_BLUE] = "blue",
93 [IIO_MOD_QUATERNION] = "quaternion",
94 [IIO_MOD_TEMP_AMBIENT] = "ambient",
95 [IIO_MOD_TEMP_OBJECT] = "object",
96 [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
97 [IIO_MOD_NORTH_TRUE] = "from_north_true",
98 [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
99 [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
100 [IIO_MOD_RUNNING] = "running",
101 [IIO_MOD_JOGGING] = "jogging",
102 [IIO_MOD_WALKING] = "walking",
103 [IIO_MOD_STILL] = "still",
104};
105
106static bool event_is_known(struct iio_event_data *event)
107{
108 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
109 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
110 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
111 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
112
113 switch (type) {
114 case IIO_VOLTAGE:
115 case IIO_CURRENT:
116 case IIO_POWER:
117 case IIO_ACCEL:
118 case IIO_ANGL_VEL:
119 case IIO_MAGN:
120 case IIO_LIGHT:
121 case IIO_INTENSITY:
122 case IIO_PROXIMITY:
123 case IIO_TEMP:
124 case IIO_INCLI:
125 case IIO_ROT:
126 case IIO_ANGL:
127 case IIO_TIMESTAMP:
128 case IIO_CAPACITANCE:
129 case IIO_ALTVOLTAGE:
130 case IIO_CCT:
131 case IIO_PRESSURE:
132 case IIO_HUMIDITYRELATIVE:
133 case IIO_ACTIVITY:
134 case IIO_STEPS:
135 break;
136 default:
137 return false;
138 }
139
140 switch (mod) {
141 case IIO_NO_MOD:
142 case IIO_MOD_X:
143 case IIO_MOD_Y:
144 case IIO_MOD_Z:
145 case IIO_MOD_X_AND_Y:
146 case IIO_MOD_X_AND_Z:
147 case IIO_MOD_Y_AND_Z:
148 case IIO_MOD_X_AND_Y_AND_Z:
149 case IIO_MOD_X_OR_Y:
150 case IIO_MOD_X_OR_Z:
151 case IIO_MOD_Y_OR_Z:
152 case IIO_MOD_X_OR_Y_OR_Z:
153 case IIO_MOD_LIGHT_BOTH:
154 case IIO_MOD_LIGHT_IR:
155 case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
156 case IIO_MOD_SUM_SQUARED_X_Y_Z:
157 case IIO_MOD_LIGHT_CLEAR:
158 case IIO_MOD_LIGHT_RED:
159 case IIO_MOD_LIGHT_GREEN:
160 case IIO_MOD_LIGHT_BLUE:
161 case IIO_MOD_QUATERNION:
162 case IIO_MOD_TEMP_AMBIENT:
163 case IIO_MOD_TEMP_OBJECT:
164 case IIO_MOD_NORTH_MAGN:
165 case IIO_MOD_NORTH_TRUE:
166 case IIO_MOD_NORTH_MAGN_TILT_COMP:
167 case IIO_MOD_NORTH_TRUE_TILT_COMP:
168 case IIO_MOD_RUNNING:
169 case IIO_MOD_JOGGING:
170 case IIO_MOD_WALKING:
171 case IIO_MOD_STILL:
172 break;
173 default:
174 return false;
175 }
176
177 switch (ev_type) {
178 case IIO_EV_TYPE_THRESH:
179 case IIO_EV_TYPE_MAG:
180 case IIO_EV_TYPE_ROC:
181 case IIO_EV_TYPE_THRESH_ADAPTIVE:
182 case IIO_EV_TYPE_MAG_ADAPTIVE:
183 case IIO_EV_TYPE_CHANGE:
184 break;
185 default:
186 return false;
187 }
188
189 switch (dir) {
190 case IIO_EV_DIR_EITHER:
191 case IIO_EV_DIR_RISING:
192 case IIO_EV_DIR_FALLING:
193 case IIO_EV_DIR_NONE:
194 break;
195 default:
196 return false;
197 }
198
199 return true;
200}
201
202static void print_event(struct iio_event_data *event)
203{
204 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
205 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
206 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
207 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
208 int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
209 int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
210 bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
211
212 if (!event_is_known(event)) {
213 printf("Unknown event: time: %lld, id: %llx\n",
214 event->timestamp, event->id);
215 return;
216 }
217
218 printf("Event: time: %lld, ", event->timestamp);
219
220 if (mod != IIO_NO_MOD) {
221 printf("type: %s(%s), ",
222 iio_chan_type_name_spec[type],
223 iio_modifier_names[mod]);
224 } else {
225 printf("type: %s, ",
226 iio_chan_type_name_spec[type]);
227 }
228
229 if (diff && chan >= 0 && chan2 >= 0)
230 printf("channel: %d-%d, ", chan, chan2);
231 else if (chan >= 0)
232 printf("channel: %d, ", chan);
233
234 printf("evtype: %s", iio_ev_type_text[ev_type]);
235
236 if (dir != IIO_EV_DIR_NONE)
237 printf(", direction: %s", iio_ev_dir_text[dir]);
238 printf("\n");
239}
240
241int main(int argc, char **argv)
242{
243 struct iio_event_data event;
244 const char *device_name;
245 char *chrdev_name;
246 int ret;
247 int dev_num;
248 int fd, event_fd;
249
250 if (argc <= 1) {
251 printf("Usage: %s <device_name>\n", argv[0]);
252 return -1;
253 }
254
255 device_name = argv[1];
256
257 dev_num = find_type_by_name(device_name, "iio:device");
258 if (dev_num >= 0) {
259 printf("Found IIO device with name %s with device number %d\n",
260 device_name, dev_num);
261 ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
262 if (ret < 0) {
263 ret = -ENOMEM;
264 goto error_ret;
265 }
266 } else {
267 /* If we can't find a IIO device by name assume device_name is a
268 IIO chrdev */
269 chrdev_name = strdup(device_name);
270 }
271
272 fd = open(chrdev_name, 0);
273 if (fd == -1) {
274 fprintf(stdout, "Failed to open %s\n", chrdev_name);
275 ret = -errno;
276 goto error_free_chrdev_name;
277 }
278
279 ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
280
281 close(fd);
282
283 if (ret == -1 || event_fd == -1) {
284 fprintf(stdout, "Failed to retrieve event fd\n");
285 ret = -errno;
286 goto error_free_chrdev_name;
287 }
288
289 while (true) {
290 ret = read(event_fd, &event, sizeof(event));
291 if (ret == -1) {
292 if (errno == EAGAIN) {
293 printf("nothing available\n");
294 continue;
295 } else {
296 perror("Failed to read event from device");
297 ret = -errno;
298 break;
299 }
300 }
301
302 print_event(&event);
303 }
304
305 close(event_fd);
306error_free_chrdev_name:
307 free(chrdev_name);
308error_ret:
309 return ret;
310}
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
new file mode 100644
index 000000000000..aea928210187
--- /dev/null
+++ b/tools/iio/iio_utils.c
@@ -0,0 +1,651 @@
1/* IIO - useful set of util functionality
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
10#include <string.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <stdint.h>
14#include <dirent.h>
15#include <errno.h>
16#include <ctype.h>
17#include "iio_utils.h"
18
19const char *iio_dir = "/sys/bus/iio/devices/";
20
21/**
22 * iioutils_break_up_name() - extract generic name from full channel name
23 * @full_name: the full channel name
24 * @generic_name: the output generic channel name
25 **/
26int iioutils_break_up_name(const char *full_name,
27 char **generic_name)
28{
29 char *current;
30 char *w, *r;
31 char *working;
32
33 current = strdup(full_name);
34 working = strtok(current, "_\0");
35 w = working;
36 r = working;
37
38 while (*r != '\0') {
39 if (!isdigit(*r)) {
40 *w = *r;
41 w++;
42 }
43 r++;
44 }
45 *w = '\0';
46 *generic_name = strdup(working);
47 free(current);
48
49 return 0;
50}
51
52/**
53 * iioutils_get_type() - find and process _type attribute data
54 * @is_signed: output whether channel is signed
55 * @bytes: output how many bytes the channel storage occupies
56 * @mask: output a bit mask for the raw data
57 * @be: big endian
58 * @device_dir: the iio device directory
59 * @name: the channel name
60 * @generic_name: the channel type name
61 **/
62int iioutils_get_type(unsigned *is_signed,
63 unsigned *bytes,
64 unsigned *bits_used,
65 unsigned *shift,
66 uint64_t *mask,
67 unsigned *be,
68 const char *device_dir,
69 const char *name,
70 const char *generic_name)
71{
72 FILE *sysfsfp;
73 int ret;
74 DIR *dp;
75 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
76 char signchar, endianchar;
77 unsigned padint;
78 const struct dirent *ent;
79
80 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
81 if (ret < 0) {
82 ret = -ENOMEM;
83 goto error_ret;
84 }
85 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
86 if (ret < 0) {
87 ret = -ENOMEM;
88 goto error_free_scan_el_dir;
89 }
90 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
91 if (ret < 0) {
92 ret = -ENOMEM;
93 goto error_free_builtname;
94 }
95
96 dp = opendir(scan_el_dir);
97 if (dp == NULL) {
98 ret = -errno;
99 goto error_free_builtname_generic;
100 }
101 while (ent = readdir(dp), ent != NULL)
102 /*
103 * Do we allow devices to override a generic name with
104 * a specific one?
105 */
106 if ((strcmp(builtname, ent->d_name) == 0) ||
107 (strcmp(builtname_generic, ent->d_name) == 0)) {
108 ret = asprintf(&filename,
109 "%s/%s", scan_el_dir, ent->d_name);
110 if (ret < 0) {
111 ret = -ENOMEM;
112 goto error_closedir;
113 }
114 sysfsfp = fopen(filename, "r");
115 if (sysfsfp == NULL) {
116 printf("failed to open %s\n", filename);
117 ret = -errno;
118 goto error_free_filename;
119 }
120
121 ret = fscanf(sysfsfp,
122 "%ce:%c%u/%u>>%u",
123 &endianchar,
124 &signchar,
125 bits_used,
126 &padint, shift);
127 if (ret < 0) {
128 printf("failed to pass scan type description\n");
129 ret = -errno;
130 goto error_close_sysfsfp;
131 }
132 *be = (endianchar == 'b');
133 *bytes = padint / 8;
134 if (*bits_used == 64)
135 *mask = ~0;
136 else
137 *mask = (1 << *bits_used) - 1;
138 if (signchar == 's')
139 *is_signed = 1;
140 else
141 *is_signed = 0;
142 fclose(sysfsfp);
143 free(filename);
144
145 filename = 0;
146 sysfsfp = 0;
147 }
148error_close_sysfsfp:
149 if (sysfsfp)
150 fclose(sysfsfp);
151error_free_filename:
152 if (filename)
153 free(filename);
154error_closedir:
155 closedir(dp);
156error_free_builtname_generic:
157 free(builtname_generic);
158error_free_builtname:
159 free(builtname);
160error_free_scan_el_dir:
161 free(scan_el_dir);
162error_ret:
163 return ret;
164}
165
166int iioutils_get_param_float(float *output,
167 const char *param_name,
168 const char *device_dir,
169 const char *name,
170 const char *generic_name)
171{
172 FILE *sysfsfp;
173 int ret;
174 DIR *dp;
175 char *builtname, *builtname_generic;
176 char *filename = NULL;
177 const struct dirent *ent;
178
179 ret = asprintf(&builtname, "%s_%s", name, param_name);
180 if (ret < 0) {
181 ret = -ENOMEM;
182 goto error_ret;
183 }
184 ret = asprintf(&builtname_generic,
185 "%s_%s", generic_name, param_name);
186 if (ret < 0) {
187 ret = -ENOMEM;
188 goto error_free_builtname;
189 }
190 dp = opendir(device_dir);
191 if (dp == NULL) {
192 ret = -errno;
193 goto error_free_builtname_generic;
194 }
195 while (ent = readdir(dp), ent != NULL)
196 if ((strcmp(builtname, ent->d_name) == 0) ||
197 (strcmp(builtname_generic, ent->d_name) == 0)) {
198 ret = asprintf(&filename,
199 "%s/%s", device_dir, ent->d_name);
200 if (ret < 0) {
201 ret = -ENOMEM;
202 goto error_closedir;
203 }
204 sysfsfp = fopen(filename, "r");
205 if (!sysfsfp) {
206 ret = -errno;
207 goto error_free_filename;
208 }
209 fscanf(sysfsfp, "%f", output);
210 break;
211 }
212error_free_filename:
213 if (filename)
214 free(filename);
215error_closedir:
216 closedir(dp);
217error_free_builtname_generic:
218 free(builtname_generic);
219error_free_builtname:
220 free(builtname);
221error_ret:
222 return ret;
223}
224
225/**
226 * bsort_channel_array_by_index() - reorder so that the array is in index order
227 *
228 **/
229
230void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
231 int cnt)
232{
233
234 struct iio_channel_info temp;
235 int x, y;
236
237 for (x = 0; x < cnt; x++)
238 for (y = 0; y < (cnt - 1); y++)
239 if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
240 temp = (*ci_array)[y + 1];
241 (*ci_array)[y + 1] = (*ci_array)[y];
242 (*ci_array)[y] = temp;
243 }
244}
245
246/**
247 * build_channel_array() - function to figure out what channels are present
248 * @device_dir: the IIO device directory in sysfs
249 * @
250 **/
251int build_channel_array(const char *device_dir,
252 struct iio_channel_info **ci_array,
253 int *counter)
254{
255 DIR *dp;
256 FILE *sysfsfp;
257 int count, i;
258 struct iio_channel_info *current;
259 int ret;
260 const struct dirent *ent;
261 char *scan_el_dir;
262 char *filename;
263
264 *counter = 0;
265 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
266 if (ret < 0) {
267 ret = -ENOMEM;
268 goto error_ret;
269 }
270 dp = opendir(scan_el_dir);
271 if (dp == NULL) {
272 ret = -errno;
273 goto error_free_name;
274 }
275 while (ent = readdir(dp), ent != NULL)
276 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
277 "_en") == 0) {
278 ret = asprintf(&filename,
279 "%s/%s", scan_el_dir, ent->d_name);
280 if (ret < 0) {
281 ret = -ENOMEM;
282 goto error_close_dir;
283 }
284 sysfsfp = fopen(filename, "r");
285 if (sysfsfp == NULL) {
286 ret = -errno;
287 free(filename);
288 goto error_close_dir;
289 }
290 fscanf(sysfsfp, "%i", &ret);
291 if (ret == 1)
292 (*counter)++;
293 fclose(sysfsfp);
294 free(filename);
295 }
296 *ci_array = malloc(sizeof(**ci_array) * (*counter));
297 if (*ci_array == NULL) {
298 ret = -ENOMEM;
299 goto error_close_dir;
300 }
301 seekdir(dp, 0);
302 count = 0;
303 while (ent = readdir(dp), ent != NULL) {
304 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
305 "_en") == 0) {
306 int current_enabled = 0;
307
308 current = &(*ci_array)[count++];
309 ret = asprintf(&filename,
310 "%s/%s", scan_el_dir, ent->d_name);
311 if (ret < 0) {
312 ret = -ENOMEM;
313 /* decrement count to avoid freeing name */
314 count--;
315 goto error_cleanup_array;
316 }
317 sysfsfp = fopen(filename, "r");
318 if (sysfsfp == NULL) {
319 free(filename);
320 ret = -errno;
321 goto error_cleanup_array;
322 }
323 fscanf(sysfsfp, "%i", &current_enabled);
324 fclose(sysfsfp);
325
326 if (!current_enabled) {
327 free(filename);
328 count--;
329 continue;
330 }
331
332 current->scale = 1.0;
333 current->offset = 0;
334 current->name = strndup(ent->d_name,
335 strlen(ent->d_name) -
336 strlen("_en"));
337 if (current->name == NULL) {
338 free(filename);
339 ret = -ENOMEM;
340 goto error_cleanup_array;
341 }
342 /* Get the generic and specific name elements */
343 ret = iioutils_break_up_name(current->name,
344 &current->generic_name);
345 if (ret) {
346 free(filename);
347 goto error_cleanup_array;
348 }
349 ret = asprintf(&filename,
350 "%s/%s_index",
351 scan_el_dir,
352 current->name);
353 if (ret < 0) {
354 free(filename);
355 ret = -ENOMEM;
356 goto error_cleanup_array;
357 }
358 sysfsfp = fopen(filename, "r");
359 fscanf(sysfsfp, "%u", &current->index);
360 fclose(sysfsfp);
361 free(filename);
362 /* Find the scale */
363 ret = iioutils_get_param_float(&current->scale,
364 "scale",
365 device_dir,
366 current->name,
367 current->generic_name);
368 if (ret < 0)
369 goto error_cleanup_array;
370 ret = iioutils_get_param_float(&current->offset,
371 "offset",
372 device_dir,
373 current->name,
374 current->generic_name);
375 if (ret < 0)
376 goto error_cleanup_array;
377 ret = iioutils_get_type(&current->is_signed,
378 &current->bytes,
379 &current->bits_used,
380 &current->shift,
381 &current->mask,
382 &current->be,
383 device_dir,
384 current->name,
385 current->generic_name);
386 }
387 }
388
389 closedir(dp);
390 /* reorder so that the array is in index order */
391 bsort_channel_array_by_index(ci_array, *counter);
392
393 return 0;
394
395error_cleanup_array:
396 for (i = count - 1; i >= 0; i--)
397 free((*ci_array)[i].name);
398 free(*ci_array);
399error_close_dir:
400 closedir(dp);
401error_free_name:
402 free(scan_el_dir);
403error_ret:
404 return ret;
405}
406
407/**
408 * find_type_by_name() - function to match top level types by name
409 * @name: top level type instance name
410 * @type: the type of top level instance being sort
411 *
412 * Typical types this is used for are device and trigger.
413 **/
414int find_type_by_name(const char *name, const char *type)
415{
416 const struct dirent *ent;
417 int number, numstrlen;
418
419 FILE *nameFile;
420 DIR *dp;
421 char thisname[IIO_MAX_NAME_LENGTH];
422 char *filename;
423
424 dp = opendir(iio_dir);
425 if (dp == NULL) {
426 printf("No industrialio devices available\n");
427 return -ENODEV;
428 }
429
430 while (ent = readdir(dp), ent != NULL) {
431 if (strcmp(ent->d_name, ".") != 0 &&
432 strcmp(ent->d_name, "..") != 0 &&
433 strlen(ent->d_name) > strlen(type) &&
434 strncmp(ent->d_name, type, strlen(type)) == 0) {
435 numstrlen = sscanf(ent->d_name + strlen(type),
436 "%d",
437 &number);
438 /* verify the next character is not a colon */
439 if (strncmp(ent->d_name + strlen(type) + numstrlen,
440 ":",
441 1) != 0) {
442 filename = malloc(strlen(iio_dir)
443 + strlen(type)
444 + numstrlen
445 + 6);
446 if (filename == NULL) {
447 closedir(dp);
448 return -ENOMEM;
449 }
450 sprintf(filename, "%s%s%d/name",
451 iio_dir,
452 type,
453 number);
454 nameFile = fopen(filename, "r");
455 if (!nameFile) {
456 free(filename);
457 continue;
458 }
459 free(filename);
460 fscanf(nameFile, "%s", thisname);
461 fclose(nameFile);
462 if (strcmp(name, thisname) == 0) {
463 closedir(dp);
464 return number;
465 }
466 }
467 }
468 }
469 closedir(dp);
470 return -ENODEV;
471}
472
473int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
474{
475 int ret = 0;
476 FILE *sysfsfp;
477 int test;
478 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
479
480 if (temp == NULL)
481 return -ENOMEM;
482 sprintf(temp, "%s/%s", basedir, filename);
483 sysfsfp = fopen(temp, "w");
484 if (sysfsfp == NULL) {
485 printf("failed to open %s\n", temp);
486 ret = -errno;
487 goto error_free;
488 }
489 fprintf(sysfsfp, "%d", val);
490 fclose(sysfsfp);
491 if (verify) {
492 sysfsfp = fopen(temp, "r");
493 if (sysfsfp == NULL) {
494 printf("failed to open %s\n", temp);
495 ret = -errno;
496 goto error_free;
497 }
498 fscanf(sysfsfp, "%d", &test);
499 fclose(sysfsfp);
500 if (test != val) {
501 printf("Possible failure in int write %d to %s%s\n",
502 val,
503 basedir,
504 filename);
505 ret = -1;
506 }
507 }
508error_free:
509 free(temp);
510 return ret;
511}
512
513int write_sysfs_int(char *filename, char *basedir, int val)
514{
515 return _write_sysfs_int(filename, basedir, val, 0);
516}
517
518int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
519{
520 return _write_sysfs_int(filename, basedir, val, 1);
521}
522
523int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
524{
525 int ret = 0;
526 FILE *sysfsfp;
527 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
528
529 if (temp == NULL) {
530 printf("Memory allocation failed\n");
531 return -ENOMEM;
532 }
533 sprintf(temp, "%s/%s", basedir, filename);
534 sysfsfp = fopen(temp, "w");
535 if (sysfsfp == NULL) {
536 printf("Could not open %s\n", temp);
537 ret = -errno;
538 goto error_free;
539 }
540 fprintf(sysfsfp, "%s", val);
541 fclose(sysfsfp);
542 if (verify) {
543 sysfsfp = fopen(temp, "r");
544 if (sysfsfp == NULL) {
545 printf("could not open file to verify\n");
546 ret = -errno;
547 goto error_free;
548 }
549 fscanf(sysfsfp, "%s", temp);
550 fclose(sysfsfp);
551 if (strcmp(temp, val) != 0) {
552 printf("Possible failure in string write of %s "
553 "Should be %s "
554 "written to %s\%s\n",
555 temp,
556 val,
557 basedir,
558 filename);
559 ret = -1;
560 }
561 }
562error_free:
563 free(temp);
564
565 return ret;
566}
567
568/**
569 * write_sysfs_string_and_verify() - string write, readback and verify
570 * @filename: name of file to write to
571 * @basedir: the sysfs directory in which the file is to be found
572 * @val: the string to write
573 **/
574int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
575{
576 return _write_sysfs_string(filename, basedir, val, 1);
577}
578
579int write_sysfs_string(char *filename, char *basedir, char *val)
580{
581 return _write_sysfs_string(filename, basedir, val, 0);
582}
583
584int read_sysfs_posint(char *filename, char *basedir)
585{
586 int ret;
587 FILE *sysfsfp;
588 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
589
590 if (temp == NULL) {
591 printf("Memory allocation failed");
592 return -ENOMEM;
593 }
594 sprintf(temp, "%s/%s", basedir, filename);
595 sysfsfp = fopen(temp, "r");
596 if (sysfsfp == NULL) {
597 ret = -errno;
598 goto error_free;
599 }
600 fscanf(sysfsfp, "%d\n", &ret);
601 fclose(sysfsfp);
602error_free:
603 free(temp);
604 return ret;
605}
606
607int read_sysfs_float(char *filename, char *basedir, float *val)
608{
609 int ret = 0;
610 FILE *sysfsfp;
611 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
612
613 if (temp == NULL) {
614 printf("Memory allocation failed");
615 return -ENOMEM;
616 }
617 sprintf(temp, "%s/%s", basedir, filename);
618 sysfsfp = fopen(temp, "r");
619 if (sysfsfp == NULL) {
620 ret = -errno;
621 goto error_free;
622 }
623 fscanf(sysfsfp, "%f\n", val);
624 fclose(sysfsfp);
625error_free:
626 free(temp);
627 return ret;
628}
629
630int read_sysfs_string(const char *filename, const char *basedir, char *str)
631{
632 int ret = 0;
633 FILE *sysfsfp;
634 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
635
636 if (temp == NULL) {
637 printf("Memory allocation failed");
638 return -ENOMEM;
639 }
640 sprintf(temp, "%s/%s", basedir, filename);
641 sysfsfp = fopen(temp, "r");
642 if (sysfsfp == NULL) {
643 ret = -errno;
644 goto error_free;
645 }
646 fscanf(sysfsfp, "%s\n", str);
647 fclose(sysfsfp);
648error_free:
649 free(temp);
650 return ret;
651}
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
new file mode 100644
index 000000000000..1bc837b2d769
--- /dev/null
+++ b/tools/iio/iio_utils.h
@@ -0,0 +1,71 @@
1#ifndef _IIO_UTILS_H_
2#define _IIO_UTILS_H_
3
4/* IIO - useful set of util functionality
5 *
6 * Copyright (c) 2008 Jonathan Cameron
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <stdint.h>
14
15/* Made up value to limit allocation sizes */
16#define IIO_MAX_NAME_LENGTH 30
17
18#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
19#define FORMAT_TYPE_FILE "%s_type"
20
21extern const char *iio_dir;
22
23/**
24 * struct iio_channel_info - information about a given channel
25 * @name: channel name
26 * @generic_name: general name for channel type
27 * @scale: scale factor to be applied for conversion to si units
28 * @offset: offset to be applied for conversion to si units
29 * @index: the channel index in the buffer output
30 * @bytes: number of bytes occupied in buffer output
31 * @mask: a bit mask for the raw output
32 * @is_signed: is the raw value stored signed
33 * @enabled: is this channel enabled
34 **/
35struct iio_channel_info {
36 char *name;
37 char *generic_name;
38 float scale;
39 float offset;
40 unsigned index;
41 unsigned bytes;
42 unsigned bits_used;
43 unsigned shift;
44 uint64_t mask;
45 unsigned be;
46 unsigned is_signed;
47 unsigned location;
48};
49
50int iioutils_break_up_name(const char *full_name, char **generic_name);
51int iioutils_get_type(unsigned *is_signed, unsigned *bytes,
52 unsigned *bits_used, unsigned *shift,
53 uint64_t *mask, unsigned *be,
54 const char *device_dir, const char *name,
55 const char *generic_name);
56int iioutils_get_param_float(float *output, const char *param_name,
57 const char *device_dir, const char *name,
58 const char *generic_name);
59void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
60int build_channel_array(const char *device_dir,
61 struct iio_channel_info **ci_array, int *counter);
62int find_type_by_name(const char *name, const char *type);
63int write_sysfs_int(char *filename, char *basedir, int val);
64int write_sysfs_int_and_verify(char *filename, char *basedir, int val);
65int write_sysfs_string_and_verify(char *filename, char *basedir, char *val);
66int write_sysfs_string(char *filename, char *basedir, char *val);
67int read_sysfs_posint(char *filename, char *basedir);
68int read_sysfs_float(char *filename, char *basedir, float *val);
69int read_sysfs_string(const char *filename, const char *basedir, char *str);
70
71#endif /* _IIO_UTILS_H_ */
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
new file mode 100644
index 000000000000..98a0de098130
--- /dev/null
+++ b/tools/iio/lsiio.c
@@ -0,0 +1,163 @@
1/*
2 * Industrial I/O utilities - lsiio.c
3 *
4 * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#include <string.h>
12#include <dirent.h>
13#include <stdio.h>
14#include <errno.h>
15#include <stdint.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/dir.h>
21#include "iio_utils.h"
22
23
24static enum verbosity {
25 VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */
26 VERBLEVEL_SENSORS, /* 1 lists sensors */
27} verblevel = VERBLEVEL_DEFAULT;
28
29const char *type_device = "iio:device";
30const char *type_trigger = "trigger";
31
32
33static inline int check_prefix(const char *str, const char *prefix)
34{
35 return strlen(str) > strlen(prefix) &&
36 strncmp(str, prefix, strlen(prefix)) == 0;
37}
38
39static inline int check_postfix(const char *str, const char *postfix)
40{
41 return strlen(str) > strlen(postfix) &&
42 strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
43}
44
45static int dump_channels(const char *dev_dir_name)
46{
47 DIR *dp;
48 const struct dirent *ent;
49
50 dp = opendir(dev_dir_name);
51 if (dp == NULL)
52 return -errno;
53 while (ent = readdir(dp), ent != NULL)
54 if (check_prefix(ent->d_name, "in_") &&
55 check_postfix(ent->d_name, "_raw")) {
56 printf(" %-10s\n", ent->d_name);
57 }
58
59 return 0;
60}
61
62static int dump_one_device(const char *dev_dir_name)
63{
64 char name[IIO_MAX_NAME_LENGTH];
65 int dev_idx;
66 int retval;
67
68 retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
69 "%i", &dev_idx);
70 if (retval != 1)
71 return -EINVAL;
72 read_sysfs_string("name", dev_dir_name, name);
73 printf("Device %03d: %s\n", dev_idx, name);
74
75 if (verblevel >= VERBLEVEL_SENSORS)
76 return dump_channels(dev_dir_name);
77 return 0;
78}
79
80static int dump_one_trigger(const char *dev_dir_name)
81{
82 char name[IIO_MAX_NAME_LENGTH];
83 int dev_idx;
84 int retval;
85
86 retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
87 "%i", &dev_idx);
88 if (retval != 1)
89 return -EINVAL;
90 read_sysfs_string("name", dev_dir_name, name);
91 printf("Trigger %03d: %s\n", dev_idx, name);
92 return 0;
93}
94
95static void dump_devices(void)
96{
97 const struct dirent *ent;
98 int number, numstrlen;
99
100 FILE *nameFile;
101 DIR *dp;
102 char thisname[IIO_MAX_NAME_LENGTH];
103 char *filename;
104
105 dp = opendir(iio_dir);
106 if (dp == NULL) {
107 printf("No industrial I/O devices available\n");
108 return;
109 }
110
111 while (ent = readdir(dp), ent != NULL) {
112 if (check_prefix(ent->d_name, type_device)) {
113 char *dev_dir_name;
114
115 asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
116 dump_one_device(dev_dir_name);
117 free(dev_dir_name);
118 if (verblevel >= VERBLEVEL_SENSORS)
119 printf("\n");
120 }
121 }
122 rewinddir(dp);
123 while (ent = readdir(dp), ent != NULL) {
124 if (check_prefix(ent->d_name, type_trigger)) {
125 char *dev_dir_name;
126
127 asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
128 dump_one_trigger(dev_dir_name);
129 free(dev_dir_name);
130 }
131 }
132 closedir(dp);
133}
134
135int main(int argc, char **argv)
136{
137 int c, err = 0;
138
139 while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
140 switch (c) {
141 case 'v':
142 verblevel++;
143 break;
144
145 case '?':
146 default:
147 err++;
148 break;
149 }
150 }
151 if (err || argc > optind) {
152 fprintf(stderr, "Usage: lsiio [options]...\n"
153 "List industrial I/O devices\n"
154 " -v, --verbose\n"
155 " Increase verbosity (may be given multiple times)\n"
156 );
157 exit(1);
158 }
159
160 dump_devices();
161
162 return 0;
163}