]> sigrok.org Git - libsigrok.git/blame - src/usb.c
libsigrok-internal.h: Remove unused prototypes
[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
22#include <stdlib.h>
db156e54 23#include <memory.h>
0c632d36
UH
24#include <glib.h>
25#include <libusb.h>
c1aae900 26#include <libsigrok/libsigrok.h>
0c632d36
UH
27#include "libsigrok-internal.h"
28
1953564a 29/* SR_CONF_CONN takes one of these: */
1eb0a0df 30#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
0c632d36
UH
31#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
32
3544f848 33#define LOG_PREFIX "usb"
0c632d36 34
c1adbb1e
DE
35#if !HAVE_LIBUSB_OS_HANDLE
36typedef int libusb_os_handle;
37#endif
38
c2bf5506
DE
39/** Custom GLib event source for libusb I/O.
40 * @internal
41 */
42struct 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 */
57static 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 */
96static 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 */
116static 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 */
159static 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 */
178static 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 */
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
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 */
225static 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 */
249static 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
7ae6a758
BV
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 */
308SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
0c632d36 309{
7ae6a758 310 struct sr_usb_dev_inst *usb;
0c632d36
UH
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)) {
e7f378fd 322 if ((mstr = g_match_info_fetch(match, 1)))
0c632d36 323 vid = strtoul(mstr, NULL, 16);
0c632d36
UH
324 g_free(mstr);
325
e7f378fd 326 if ((mstr = g_match_info_fetch(match, 2)))
0c632d36 327 pid = strtoul(mstr, NULL, 16);
0c632d36
UH
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)) {
e7f378fd 336 if ((mstr = g_match_info_fetch(match, 1)))
1eb0a0df 337 bus = strtoul(mstr, NULL, 10);
0c632d36
UH
338 g_free(mstr);
339
e7f378fd 340 if ((mstr = g_match_info_fetch(match, 2)))
1eb0a0df 341 addr = strtoul(mstr, NULL, 10);
0c632d36
UH
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) {
e7f378fd 351 sr_err("Neither VID:PID nor bus.address was specified.");
0c632d36
UH
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))) {
d4928d71
PS
370 sr_err("Failed to get device descriptor: %s.",
371 libusb_error_name(ret));
0c632d36
UH
372 continue;
373 }
374
7ae6a758 375 if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
0c632d36 376 continue;
0c632d36 377
7ae6a758
BV
378 b = libusb_get_bus_number(devlist[i]);
379 a = libusb_get_device_address(devlist[i]);
380 if (bus + addr && (b != bus || a != addr))
0c632d36 381 continue;
0c632d36
UH
382
383 sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
384 "%d.%d).", des.idVendor, des.idProduct, b, a);
385
7ae6a758
BV
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);
0c632d36
UH
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
397SR_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
c5f1a021 403 sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
0c632d36
UH
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]);
c5f1a021 421 if (b != usb->bus || a != usb->address)
0c632d36 422 continue;
0c632d36
UH
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}
6c60facc 441
67e95ed3
BV
442SR_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
102f1239
BV
449SR_PRIV int usb_source_add(struct sr_session *session, struct sr_context *ctx,
450 int timeout, sr_receive_data_callback cb, void *cb_data)
6c60facc 451{
c2bf5506 452 GSource *source;
92248e78
DE
453 int ret;
454
c2bf5506
DE
455 source = usb_source_new(session, ctx->libusb_ctx, timeout);
456 if (!source)
92248e78 457 return SR_ERR;
534b634c 458
c2bf5506 459 g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
534b634c 460
c2bf5506
DE
461 ret = sr_session_source_add_internal(session, ctx->libusb_ctx, source);
462 g_source_unref(source);
4b9e2532 463
c2bf5506 464 return ret;
6c60facc
ML
465}
466
102f1239 467SR_PRIV int usb_source_remove(struct sr_session *session, struct sr_context *ctx)
6c60facc 468{
c2bf5506 469 return sr_session_source_remove_internal(session, ctx->libusb_ctx);
6c60facc 470}
db156e54 471
76bc5f63 472SR_PRIV int usb_get_port_path(libusb_device *dev, char *path, int path_len)
db156e54 473{
76bc5f63
AJ
474 uint8_t port_numbers[8];
475 int i, n, len;
476
19643b96
UJ
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
76bc5f63 486 n = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
19643b96
UJ
487#ifdef __FreeBSD__
488 libusb_close(devh);
489#endif
76bc5f63 490
19643b96
UJ
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
2f004b4b
VP
498 if (n < 1)
499 return SR_ERR;
500
76bc5f63
AJ
501 len = snprintf(path, path_len, "usb/%d-%d",
502 libusb_get_bus_number(dev), port_numbers[0]);
db156e54 503
76bc5f63
AJ
504 for (i = 1; i < n; i++)
505 len += snprintf(path+len, path_len-len, ".%d", port_numbers[i]);
db156e54
SA
506
507 return SR_OK;
508}