]> sigrok.org Git - libsigrok.git/blame - src/usb.c
std: Simplifications, random fixes, Doxygen cosmetics.
[libsigrok.git] / src / usb.c
CommitLineData
0c632d36 1/*
50985c20 2 * This file is part of the libsigrok project.
0c632d36
UH
3 *
4 * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
c2bf5506 6 * Copyright (C) 2015 Daniel Elstner <daniel.kitta@gmail.com>
0c632d36 7 *
c2bf5506 8 * This program is free software: you can redistribute it and/or modify
0c632d36 9 * it under the terms of the GNU General Public License as published by
c2bf5506 10 * the Free Software Foundation, either version 3 of the License, or
0c632d36
UH
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
c2bf5506 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
0c632d36
UH
20 */
21
6ec6c43b 22#include <config.h>
0c632d36 23#include <stdlib.h>
db156e54 24#include <memory.h>
0c632d36
UH
25#include <glib.h>
26#include <libusb.h>
c1aae900 27#include <libsigrok/libsigrok.h>
0c632d36
UH
28#include "libsigrok-internal.h"
29
1953564a 30/* SR_CONF_CONN takes one of these: */
039a2fd7 31#define CONN_USB_VIDPID "^([0-9a-fA-F]{4})\\.([0-9a-fA-F]{4})$"
0c632d36
UH
32#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
33
3544f848 34#define LOG_PREFIX "usb"
0c632d36 35
c1adbb1e
DE
36#if !HAVE_LIBUSB_OS_HANDLE
37typedef int libusb_os_handle;
38#endif
39
c2bf5506
DE
40/** Custom GLib event source for libusb I/O.
41 * @internal
42 */
43struct 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 */
58static 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 */
97static 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 */
117static 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 }
c2bf5506
DE
137
138 if (!callback) {
139 sr_err("Callback not set, cannot dispatch event.");
140 return G_SOURCE_REMOVE;
141 }
142 keep = (*(sr_receive_data_callback)callback)(-1, revents, user_data);
143
144 if (G_LIKELY(keep) && G_LIKELY(!g_source_is_destroyed(source))) {
145 if (usource->timeout_us >= 0)
146 usource->due_us = g_source_get_time(source)
147 + usource->timeout_us;
148 else
149 usource->due_us = INT64_MAX;
150 }
151 return keep;
152}
153
154/** USB event source finalize() method.
155 */
156static void usb_source_finalize(GSource *source)
157{
158 struct usb_source *usource;
159
160 usource = (struct usb_source *)source;
161
162 sr_spew("%s", __func__);
163
164 libusb_set_pollfd_notifiers(usource->usb_ctx, NULL, NULL, NULL);
165
166 g_ptr_array_unref(usource->pollfds);
167 usource->pollfds = NULL;
168
169 sr_session_source_destroyed(usource->session,
170 usource->usb_ctx, source);
171}
172
173/** Callback invoked when a new libusb FD should be added to the poll set.
174 */
175static LIBUSB_CALL void usb_pollfd_added(libusb_os_handle fd,
176 short events, void *user_data)
177{
178 struct usb_source *usource;
179 GPollFD *pollfd;
180
181 usource = user_data;
182
5eff221e
DE
183 if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
184 return;
185
c2bf5506
DE
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);
5eff221e 195 g_source_add_poll(&usource->base, pollfd);
c2bf5506
DE
196}
197
198/** Callback invoked when a libusb FD should be removed from the poll set.
199 */
200static 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
5eff221e
DE
208 if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
209 return;
210
c2bf5506
DE
211 /* It's likely that the removed poll FD is at the end.
212 */
213 for (i = usource->pollfds->len; G_LIKELY(i > 0); i--) {
214 pollfd = g_ptr_array_index(usource->pollfds, i - 1);
215
216 if ((libusb_os_handle)pollfd->fd == fd) {
5eff221e 217 g_source_remove_poll(&usource->base, pollfd);
c2bf5506
DE
218 g_ptr_array_remove_index_fast(usource->pollfds, i - 1);
219 return;
220 }
221 }
222 sr_err("FD to be removed (%" G_GINTPTR_FORMAT
223 ") not found in event source poll set.", (gintptr)fd);
224}
225
226/** Destroy notify callback for FDs maintained by the USB event source.
227 */
228static void usb_source_free_pollfd(void *data)
229{
230 g_slice_free(GPollFD, data);
231}
232
233/** Create an event source for libusb I/O.
234 *
235 * TODO: The combination of the USB I/O source with a user timeout is
236 * conceptually broken. The user timeout supplied here is completely
237 * unrelated to I/O -- the actual I/O timeout is set when submitting
238 * a USB transfer.
239 * The sigrok drivers generally use the timeout to poll device state.
240 * Usually, this polling can be sensibly done only when there is no
241 * active USB transfer -- i.e. it's actually mutually exclusive with
242 * waiting for transfer completion.
243 * Thus, the user timeout should be removed from the USB event source
244 * API at some point. Instead, drivers should install separate timer
245 * event sources for their polling needs.
246 *
247 * @param session The session the event source belongs to.
248 * @param usb_ctx The libusb context for which to handle events.
249 * @param timeout_ms The timeout interval in ms, or -1 to wait indefinitely.
250 * @return A new event source object, or NULL on failure.
251 */
252static GSource *usb_source_new(struct sr_session *session,
253 struct libusb_context *usb_ctx, int timeout_ms)
254{
255 static GSourceFuncs usb_source_funcs = {
256 .prepare = &usb_source_prepare,
257 .check = &usb_source_check,
258 .dispatch = &usb_source_dispatch,
259 .finalize = &usb_source_finalize
260 };
261 GSource *source;
262 struct usb_source *usource;
263 const struct libusb_pollfd **upollfds, **upfd;
264
265 upollfds = libusb_get_pollfds(usb_ctx);
266 if (!upollfds) {
267 sr_err("Failed to get libusb file descriptors.");
268 return NULL;
269 }
270 source = g_source_new(&usb_source_funcs, sizeof(struct usb_source));
271 usource = (struct usb_source *)source;
272
273 g_source_set_name(source, "usb");
274
275 if (timeout_ms >= 0) {
276 usource->timeout_us = 1000 * (int64_t)timeout_ms;
277 usource->due_us = 0;
278 } else {
279 usource->timeout_us = -1;
280 usource->due_us = INT64_MAX;
281 }
282 usource->session = session;
283 usource->usb_ctx = usb_ctx;
284 usource->pollfds = g_ptr_array_new_full(8, &usb_source_free_pollfd);
285
286 for (upfd = upollfds; *upfd != NULL; upfd++)
287 usb_pollfd_added((*upfd)->fd, (*upfd)->events, usource);
288
289#if (LIBUSB_API_VERSION >= 0x01000104)
290 libusb_free_pollfds(upollfds);
291#else
292 free(upollfds);
293#endif
294 libusb_set_pollfd_notifiers(usb_ctx,
295 &usb_pollfd_added, &usb_pollfd_removed, usource);
296
297 return source;
298}
299
7ae6a758
BV
300/**
301 * Find USB devices according to a connection string.
302 *
303 * @param usb_ctx libusb context to use while scanning.
304 * @param conn Connection string specifying the device(s) to match. This
305 * can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
306 *
307 * @return A GSList of struct sr_usb_dev_inst, with bus and address fields
308 * matching the device that matched the connection string. The GSList and
309 * its contents must be freed by the caller.
310 */
311SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
0c632d36 312{
7ae6a758 313 struct sr_usb_dev_inst *usb;
0c632d36
UH
314 struct libusb_device **devlist;
315 struct libusb_device_descriptor des;
316 GSList *devices;
317 GRegex *reg;
318 GMatchInfo *match;
319 int vid, pid, bus, addr, b, a, ret, i;
320 char *mstr;
321
322 vid = pid = bus = addr = 0;
323 reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
324 if (g_regex_match(reg, conn, 0, &match)) {
e7f378fd 325 if ((mstr = g_match_info_fetch(match, 1)))
0c632d36 326 vid = strtoul(mstr, NULL, 16);
0c632d36
UH
327 g_free(mstr);
328
e7f378fd 329 if ((mstr = g_match_info_fetch(match, 2)))
0c632d36 330 pid = strtoul(mstr, NULL, 16);
0c632d36
UH
331 g_free(mstr);
332 sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
333 vid, pid);
334 } else {
335 g_match_info_unref(match);
336 g_regex_unref(reg);
337 reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
338 if (g_regex_match(reg, conn, 0, &match)) {
e7f378fd 339 if ((mstr = g_match_info_fetch(match, 1)))
1eb0a0df 340 bus = strtoul(mstr, NULL, 10);
0c632d36
UH
341 g_free(mstr);
342
e7f378fd 343 if ((mstr = g_match_info_fetch(match, 2)))
1eb0a0df 344 addr = strtoul(mstr, NULL, 10);
0c632d36
UH
345 g_free(mstr);
346 sr_dbg("Trying to find USB device with bus.address = "
347 "%d.%d.", bus, addr);
348 }
349 }
350 g_match_info_unref(match);
351 g_regex_unref(reg);
352
353 if (vid + pid + bus + addr == 0) {
e7f378fd 354 sr_err("Neither VID:PID nor bus.address was specified.");
0c632d36
UH
355 return NULL;
356 }
357
e4ce146f 358 if (bus > 255) {
0c632d36
UH
359 sr_err("Invalid bus specified: %d.", bus);
360 return NULL;
361 }
362
363 if (addr > 127) {
364 sr_err("Invalid address specified: %d.", addr);
365 return NULL;
366 }
367
368 /* Looks like a valid USB device specification, but is it connected? */
369 devices = NULL;
370 libusb_get_device_list(usb_ctx, &devlist);
371 for (i = 0; devlist[i]; i++) {
372 if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
d4928d71
PS
373 sr_err("Failed to get device descriptor: %s.",
374 libusb_error_name(ret));
0c632d36
UH
375 continue;
376 }
377
7ae6a758 378 if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
0c632d36 379 continue;
0c632d36 380
7ae6a758
BV
381 b = libusb_get_bus_number(devlist[i]);
382 a = libusb_get_device_address(devlist[i]);
383 if (bus + addr && (b != bus || a != addr))
0c632d36 384 continue;
0c632d36
UH
385
386 sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
387 "%d.%d).", des.idVendor, des.idProduct, b, a);
388
7ae6a758
BV
389 usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
390 libusb_get_device_address(devlist[i]), NULL);
391 devices = g_slist_append(devices, usb);
0c632d36
UH
392 }
393 libusb_free_device_list(devlist, 1);
394
395 sr_dbg("Found %d device(s).", g_slist_length(devices));
176d785d 396
0c632d36
UH
397 return devices;
398}
399
400SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
401{
402 struct libusb_device **devlist;
403 struct libusb_device_descriptor des;
404 int ret, r, cnt, i, a, b;
405
c5f1a021 406 sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
0c632d36
UH
407
408 if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
409 sr_err("Failed to retrieve device list: %s.",
410 libusb_error_name(cnt));
411 return SR_ERR;
412 }
413
414 ret = SR_ERR;
415 for (i = 0; i < cnt; i++) {
416 if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
417 sr_err("Failed to get device descriptor: %s.",
418 libusb_error_name(r));
419 continue;
420 }
421
422 b = libusb_get_bus_number(devlist[i]);
423 a = libusb_get_device_address(devlist[i]);
c5f1a021 424 if (b != usb->bus || a != usb->address)
0c632d36 425 continue;
0c632d36
UH
426
427 if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
428 sr_err("Failed to open device: %s.",
429 libusb_error_name(r));
430 break;
431 }
432
433 sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
434 "%d.%d).", des.idVendor, des.idProduct, b, a);
435
436 ret = SR_OK;
437 break;
438 }
439
440 libusb_free_device_list(devlist, 1);
441
442 return ret;
443}
6c60facc 444
67e95ed3
BV
445SR_PRIV void sr_usb_close(struct sr_usb_dev_inst *usb)
446{
447 libusb_close(usb->devhdl);
448 usb->devhdl = NULL;
449 sr_dbg("Closed USB device %d.%d.", usb->bus, usb->address);
450}
451
102f1239
BV
452SR_PRIV int usb_source_add(struct sr_session *session, struct sr_context *ctx,
453 int timeout, sr_receive_data_callback cb, void *cb_data)
6c60facc 454{
c2bf5506 455 GSource *source;
92248e78
DE
456 int ret;
457
c2bf5506
DE
458 source = usb_source_new(session, ctx->libusb_ctx, timeout);
459 if (!source)
92248e78 460 return SR_ERR;
534b634c 461
c2bf5506 462 g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
534b634c 463
c2bf5506
DE
464 ret = sr_session_source_add_internal(session, ctx->libusb_ctx, source);
465 g_source_unref(source);
4b9e2532 466
c2bf5506 467 return ret;
6c60facc
ML
468}
469
102f1239 470SR_PRIV int usb_source_remove(struct sr_session *session, struct sr_context *ctx)
6c60facc 471{
c2bf5506 472 return sr_session_source_remove_internal(session, ctx->libusb_ctx);
6c60facc 473}
db156e54 474
76bc5f63 475SR_PRIV int usb_get_port_path(libusb_device *dev, char *path, int path_len)
db156e54 476{
76bc5f63
AJ
477 uint8_t port_numbers[8];
478 int i, n, len;
479
19643b96
UJ
480/*
481 * FreeBSD requires that devices prior to calling libusb_get_port_numbers()
482 * have been opened with libusb_open().
b98b7022 483 * This apparently also applies to some Mac OS X versions.
19643b96 484 */
b98b7022 485#if defined(__FreeBSD__) || defined(__APPLE__)
19643b96
UJ
486 struct libusb_device_handle *devh;
487 if (libusb_open(dev, &devh) != 0)
488 return SR_ERR;
489#endif
76bc5f63 490 n = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
b98b7022 491#if defined(__FreeBSD__) || defined(__APPLE__)
19643b96
UJ
492 libusb_close(devh);
493#endif
76bc5f63 494
b98b7022
UH
495/* Workaround FreeBSD / Mac OS X libusb_get_port_numbers() returning 0. */
496#if defined(__FreeBSD__) || defined(__APPLE__)
19643b96
UJ
497 if (n == 0) {
498 port_numbers[0] = libusb_get_device_address(dev);
499 n = 1;
500 }
501#endif
2f004b4b
VP
502 if (n < 1)
503 return SR_ERR;
504
76bc5f63
AJ
505 len = snprintf(path, path_len, "usb/%d-%d",
506 libusb_get_bus_number(dev), port_numbers[0]);
db156e54 507
76bc5f63
AJ
508 for (i = 1; i < n; i++)
509 len += snprintf(path+len, path_len-len, ".%d", port_numbers[i]);
db156e54
SA
510
511 return SR_OK;
512}
69f7d9b4
JH
513
514/**
515 * Check the USB configuration to determine if this device has a given
516 * manufacturer and product string.
517 *
518 * @return TRUE if the device's configuration profile strings
519 * configuration, FALSE otherwise.
520 */
521SR_PRIV gboolean usb_match_manuf_prod(libusb_device *dev,
522 const char *manufacturer, const char *product)
523{
524 struct libusb_device_descriptor des;
525 struct libusb_device_handle *hdl;
526 gboolean ret;
527 unsigned char strdesc[64];
528
529 hdl = NULL;
530 ret = FALSE;
531 while (!ret) {
532 /* Assume the FW has not been loaded, unless proven wrong. */
533 libusb_get_device_descriptor(dev, &des);
534
535 if (libusb_open(dev, &hdl) != 0)
536 break;
537
538 if (libusb_get_string_descriptor_ascii(hdl,
539 des.iManufacturer, strdesc, sizeof(strdesc)) < 0)
540 break;
541 if (strcmp((const char *)strdesc, manufacturer))
542 break;
543
544 if (libusb_get_string_descriptor_ascii(hdl,
545 des.iProduct, strdesc, sizeof(strdesc)) < 0)
546 break;
547 if (strcmp((const char *)strdesc, product))
548 break;
549
550 ret = TRUE;
551 }
552 if (hdl)
553 libusb_close(hdl);
554
555 return ret;
556}