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