]> sigrok.org Git - libsigrok.git/blob - src/usb.c
sr_usb_find(): Increase the 'bus' limit to 255.
[libsigrok.git] / src / usb.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
6  * Copyright (C) 2015 Daniel Elstner <daniel.kitta@gmail.com>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program 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
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <memory.h>
25 #include <glib.h>
26 #include <libusb.h>
27 #include <libsigrok/libsigrok.h>
28 #include "libsigrok-internal.h"
29
30 /* SR_CONF_CONN takes one of these: */
31 #define CONN_USB_VIDPID  "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
32 #define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
33
34 #define LOG_PREFIX "usb"
35
36 #if !HAVE_LIBUSB_OS_HANDLE
37 typedef int libusb_os_handle;
38 #endif
39
40 /** Custom GLib event source for libusb I/O.
41  * @internal
42  */
43 struct usb_source {
44         GSource base;
45
46         int64_t timeout_us;
47         int64_t due_us;
48
49         /* Needed to keep track of installed sources */
50         struct sr_session *session;
51
52         struct libusb_context *usb_ctx;
53         GPtrArray *pollfds;
54 };
55
56 /** USB event source prepare() method.
57  */
58 static gboolean usb_source_prepare(GSource *source, int *timeout)
59 {
60         int64_t now_us, usb_due_us;
61         struct usb_source *usource;
62         struct timeval usb_timeout;
63         int remaining_ms;
64         int ret;
65
66         usource = (struct usb_source *)source;
67
68         ret = libusb_get_next_timeout(usource->usb_ctx, &usb_timeout);
69         if (G_UNLIKELY(ret < 0)) {
70                 sr_err("Failed to get libusb timeout: %s",
71                         libusb_error_name(ret));
72         }
73         now_us = g_source_get_time(source);
74
75         if (usource->due_us == 0) {
76                 /* First-time initialization of the expiration time */
77                 usource->due_us = now_us + usource->timeout_us;
78         }
79         if (ret == 1) {
80                 usb_due_us = (int64_t)usb_timeout.tv_sec * G_USEC_PER_SEC
81                                 + usb_timeout.tv_usec + now_us;
82                 if (usb_due_us < usource->due_us)
83                         usource->due_us = usb_due_us;
84         }
85         if (usource->due_us != INT64_MAX)
86                 remaining_ms = (MAX(0, usource->due_us - now_us) + 999) / 1000;
87         else
88                 remaining_ms = -1;
89
90         *timeout = remaining_ms;
91
92         return (remaining_ms == 0);
93 }
94
95 /** USB event source check() method.
96  */
97 static gboolean usb_source_check(GSource *source)
98 {
99         struct usb_source *usource;
100         GPollFD *pollfd;
101         unsigned int revents;
102         unsigned int i;
103
104         usource = (struct usb_source *)source;
105         revents = 0;
106
107         for (i = 0; i < usource->pollfds->len; i++) {
108                 pollfd = g_ptr_array_index(usource->pollfds, i);
109                 revents |= pollfd->revents;
110         }
111         return (revents != 0 || (usource->due_us != INT64_MAX
112                         && usource->due_us <= g_source_get_time(source)));
113 }
114
115 /** USB event source dispatch() method.
116  */
117 static gboolean usb_source_dispatch(GSource *source,
118                 GSourceFunc callback, void *user_data)
119 {
120         struct usb_source *usource;
121         GPollFD *pollfd;
122         unsigned int revents;
123         unsigned int i;
124         gboolean keep;
125
126         usource = (struct usb_source *)source;
127         revents = 0;
128         /*
129          * This is somewhat arbitrary, but drivers use revents to distinguish
130          * actual I/O from timeouts. When we remove the user timeout from the
131          * driver API, this will no longer be needed.
132          */
133         for (i = 0; i < usource->pollfds->len; i++) {
134                 pollfd = g_ptr_array_index(usource->pollfds, i);
135                 revents |= pollfd->revents;
136         }
137         if (revents != 0)
138                 sr_spew("%s: revents 0x%.2X", __func__, revents);
139         else
140                 sr_spew("%s: timed out", __func__);
141
142         if (!callback) {
143                 sr_err("Callback not set, cannot dispatch event.");
144                 return G_SOURCE_REMOVE;
145         }
146         keep = (*(sr_receive_data_callback)callback)(-1, revents, user_data);
147
148         if (G_LIKELY(keep) && G_LIKELY(!g_source_is_destroyed(source))) {
149                 if (usource->timeout_us >= 0)
150                         usource->due_us = g_source_get_time(source)
151                                         + usource->timeout_us;
152                 else
153                         usource->due_us = INT64_MAX;
154         }
155         return keep;
156 }
157
158 /** USB event source finalize() method.
159  */
160 static void usb_source_finalize(GSource *source)
161 {
162         struct usb_source *usource;
163
164         usource = (struct usb_source *)source;
165
166         sr_spew("%s", __func__);
167
168         libusb_set_pollfd_notifiers(usource->usb_ctx, NULL, NULL, NULL);
169
170         g_ptr_array_unref(usource->pollfds);
171         usource->pollfds = NULL;
172
173         sr_session_source_destroyed(usource->session,
174                         usource->usb_ctx, source);
175 }
176
177 /** Callback invoked when a new libusb FD should be added to the poll set.
178  */
179 static LIBUSB_CALL void usb_pollfd_added(libusb_os_handle fd,
180                 short events, void *user_data)
181 {
182         struct usb_source *usource;
183         GPollFD *pollfd;
184
185         usource = user_data;
186
187         if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
188                 return;
189
190         pollfd = g_slice_new(GPollFD);
191 #ifdef G_OS_WIN32
192         events = G_IO_IN;
193 #endif
194         pollfd->fd = (gintptr)fd;
195         pollfd->events = events;
196         pollfd->revents = 0;
197
198         g_ptr_array_add(usource->pollfds, pollfd);
199         g_source_add_poll(&usource->base, pollfd);
200 }
201
202 /** Callback invoked when a libusb FD should be removed from the poll set.
203  */
204 static LIBUSB_CALL void usb_pollfd_removed(libusb_os_handle fd, void *user_data)
205 {
206         struct usb_source *usource;
207         GPollFD *pollfd;
208         unsigned int i;
209
210         usource = user_data;
211
212         if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
213                 return;
214
215         /* It's likely that the removed poll FD is at the end.
216          */
217         for (i = usource->pollfds->len; G_LIKELY(i > 0); i--) {
218                 pollfd = g_ptr_array_index(usource->pollfds, i - 1);
219
220                 if ((libusb_os_handle)pollfd->fd == fd) {
221                         g_source_remove_poll(&usource->base, pollfd);
222                         g_ptr_array_remove_index_fast(usource->pollfds, i - 1);
223                         return;
224                 }
225         }
226         sr_err("FD to be removed (%" G_GINTPTR_FORMAT
227                 ") not found in event source poll set.", (gintptr)fd);
228 }
229
230 /** Destroy notify callback for FDs maintained by the USB event source.
231  */
232 static void usb_source_free_pollfd(void *data)
233 {
234         g_slice_free(GPollFD, data);
235 }
236
237 /** Create an event source for libusb I/O.
238  *
239  * TODO: The combination of the USB I/O source with a user timeout is
240  * conceptually broken. The user timeout supplied here is completely
241  * unrelated to I/O -- the actual I/O timeout is set when submitting
242  * a USB transfer.
243  * The sigrok drivers generally use the timeout to poll device state.
244  * Usually, this polling can be sensibly done only when there is no
245  * active USB transfer -- i.e. it's actually mutually exclusive with
246  * waiting for transfer completion.
247  * Thus, the user timeout should be removed from the USB event source
248  * API at some point. Instead, drivers should install separate timer
249  * event sources for their polling needs.
250  *
251  * @param session The session the event source belongs to.
252  * @param usb_ctx The libusb context for which to handle events.
253  * @param timeout_ms The timeout interval in ms, or -1 to wait indefinitely.
254  * @return A new event source object, or NULL on failure.
255  */
256 static GSource *usb_source_new(struct sr_session *session,
257                 struct libusb_context *usb_ctx, int timeout_ms)
258 {
259         static GSourceFuncs usb_source_funcs = {
260                 .prepare  = &usb_source_prepare,
261                 .check    = &usb_source_check,
262                 .dispatch = &usb_source_dispatch,
263                 .finalize = &usb_source_finalize
264         };
265         GSource *source;
266         struct usb_source *usource;
267         const struct libusb_pollfd **upollfds, **upfd;
268
269         upollfds = libusb_get_pollfds(usb_ctx);
270         if (!upollfds) {
271                 sr_err("Failed to get libusb file descriptors.");
272                 return NULL;
273         }
274         source = g_source_new(&usb_source_funcs, sizeof(struct usb_source));
275         usource = (struct usb_source *)source;
276
277         g_source_set_name(source, "usb");
278
279         if (timeout_ms >= 0) {
280                 usource->timeout_us = 1000 * (int64_t)timeout_ms;
281                 usource->due_us = 0;
282         } else {
283                 usource->timeout_us = -1;
284                 usource->due_us = INT64_MAX;
285         }
286         usource->session = session;
287         usource->usb_ctx = usb_ctx;
288         usource->pollfds = g_ptr_array_new_full(8, &usb_source_free_pollfd);
289
290         for (upfd = upollfds; *upfd != NULL; upfd++)
291                 usb_pollfd_added((*upfd)->fd, (*upfd)->events, usource);
292
293 #if (LIBUSB_API_VERSION >= 0x01000104)
294         libusb_free_pollfds(upollfds);
295 #else
296         free(upollfds);
297 #endif
298         libusb_set_pollfd_notifiers(usb_ctx,
299                 &usb_pollfd_added, &usb_pollfd_removed, usource);
300
301         return source;
302 }
303
304 /**
305  * Find USB devices according to a connection string.
306  *
307  * @param usb_ctx libusb context to use while scanning.
308  * @param conn Connection string specifying the device(s) to match. This
309  * can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
310  *
311  * @return A GSList of struct sr_usb_dev_inst, with bus and address fields
312  * matching the device that matched the connection string. The GSList and
313  * its contents must be freed by the caller.
314  */
315 SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
316 {
317         struct sr_usb_dev_inst *usb;
318         struct libusb_device **devlist;
319         struct libusb_device_descriptor des;
320         GSList *devices;
321         GRegex *reg;
322         GMatchInfo *match;
323         int vid, pid, bus, addr, b, a, ret, i;
324         char *mstr;
325
326         vid = pid = bus = addr = 0;
327         reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
328         if (g_regex_match(reg, conn, 0, &match)) {
329                 if ((mstr = g_match_info_fetch(match, 1)))
330                         vid = strtoul(mstr, NULL, 16);
331                 g_free(mstr);
332
333                 if ((mstr = g_match_info_fetch(match, 2)))
334                         pid = strtoul(mstr, NULL, 16);
335                 g_free(mstr);
336                 sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
337                        vid, pid);
338         } else {
339                 g_match_info_unref(match);
340                 g_regex_unref(reg);
341                 reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
342                 if (g_regex_match(reg, conn, 0, &match)) {
343                         if ((mstr = g_match_info_fetch(match, 1)))
344                                 bus = strtoul(mstr, NULL, 10);
345                         g_free(mstr);
346
347                         if ((mstr = g_match_info_fetch(match, 2)))
348                                 addr = strtoul(mstr, NULL, 10);
349                         g_free(mstr);
350                         sr_dbg("Trying to find USB device with bus.address = "
351                                "%d.%d.", bus, addr);
352                 }
353         }
354         g_match_info_unref(match);
355         g_regex_unref(reg);
356
357         if (vid + pid + bus + addr == 0) {
358                 sr_err("Neither VID:PID nor bus.address was specified.");
359                 return NULL;
360         }
361
362         if (bus > 255) {
363                 sr_err("Invalid bus specified: %d.", bus);
364                 return NULL;
365         }
366
367         if (addr > 127) {
368                 sr_err("Invalid address specified: %d.", addr);
369                 return NULL;
370         }
371
372         /* Looks like a valid USB device specification, but is it connected? */
373         devices = NULL;
374         libusb_get_device_list(usb_ctx, &devlist);
375         for (i = 0; devlist[i]; i++) {
376                 if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
377                         sr_err("Failed to get device descriptor: %s.",
378                                libusb_error_name(ret));
379                         continue;
380                 }
381
382                 if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
383                         continue;
384
385                 b = libusb_get_bus_number(devlist[i]);
386                 a = libusb_get_device_address(devlist[i]);
387                 if (bus + addr && (b != bus || a != addr))
388                         continue;
389
390                 sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
391                        "%d.%d).", des.idVendor, des.idProduct, b, a);
392
393                 usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
394                                 libusb_get_device_address(devlist[i]), NULL);
395                 devices = g_slist_append(devices, usb);
396         }
397         libusb_free_device_list(devlist, 1);
398
399         sr_dbg("Found %d device(s).", g_slist_length(devices));
400         
401         return devices;
402 }
403
404 SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
405 {
406         struct libusb_device **devlist;
407         struct libusb_device_descriptor des;
408         int ret, r, cnt, i, a, b;
409
410         sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
411
412         if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
413                 sr_err("Failed to retrieve device list: %s.",
414                        libusb_error_name(cnt));
415                 return SR_ERR;
416         }
417
418         ret = SR_ERR;
419         for (i = 0; i < cnt; i++) {
420                 if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
421                         sr_err("Failed to get device descriptor: %s.",
422                                libusb_error_name(r));
423                         continue;
424                 }
425
426                 b = libusb_get_bus_number(devlist[i]);
427                 a = libusb_get_device_address(devlist[i]);
428                 if (b != usb->bus || a != usb->address)
429                         continue;
430
431                 if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
432                         sr_err("Failed to open device: %s.",
433                                libusb_error_name(r));
434                         break;
435                 }
436
437                 sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
438                        "%d.%d).", des.idVendor, des.idProduct, b, a);
439
440                 ret = SR_OK;
441                 break;
442         }
443
444         libusb_free_device_list(devlist, 1);
445
446         return ret;
447 }
448
449 SR_PRIV void sr_usb_close(struct sr_usb_dev_inst *usb)
450 {
451         libusb_close(usb->devhdl);
452         usb->devhdl = NULL;
453         sr_dbg("Closed USB device %d.%d.", usb->bus, usb->address);
454 }
455
456 SR_PRIV int usb_source_add(struct sr_session *session, struct sr_context *ctx,
457                 int timeout, sr_receive_data_callback cb, void *cb_data)
458 {
459         GSource *source;
460         int ret;
461
462         source = usb_source_new(session, ctx->libusb_ctx, timeout);
463         if (!source)
464                 return SR_ERR;
465
466         g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
467
468         ret = sr_session_source_add_internal(session, ctx->libusb_ctx, source);
469         g_source_unref(source);
470
471         return ret;
472 }
473
474 SR_PRIV int usb_source_remove(struct sr_session *session, struct sr_context *ctx)
475 {
476         return sr_session_source_remove_internal(session, ctx->libusb_ctx);
477 }
478
479 SR_PRIV int usb_get_port_path(libusb_device *dev, char *path, int path_len)
480 {
481         uint8_t port_numbers[8];
482         int i, n, len;
483
484 /*
485  * FreeBSD requires that devices prior to calling libusb_get_port_numbers()
486  * have been opened with libusb_open().
487  * This apparently also applies to some Mac OS X versions.
488  */
489 #if defined(__FreeBSD__) || defined(__APPLE__)
490         struct libusb_device_handle *devh;
491         if (libusb_open(dev, &devh) != 0)
492                 return SR_ERR;
493 #endif
494         n = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
495 #if defined(__FreeBSD__) || defined(__APPLE__)
496         libusb_close(devh);
497 #endif
498
499 /* Workaround FreeBSD / Mac OS X libusb_get_port_numbers() returning 0. */
500 #if defined(__FreeBSD__) || defined(__APPLE__)
501         if (n == 0) {
502                 port_numbers[0] = libusb_get_device_address(dev);
503                 n = 1;
504         }
505 #endif
506         if (n < 1)
507                 return SR_ERR;
508
509         len = snprintf(path, path_len, "usb/%d-%d",
510                        libusb_get_bus_number(dev), port_numbers[0]);
511
512         for (i = 1; i < n; i++)
513                 len += snprintf(path+len, path_len-len, ".%d", port_numbers[i]);
514
515         return SR_OK;
516 }