core: Only interrupt event handlers as necessary during libusb_open()
authorChris Dickens <christopher.a.dickens@gmail.com>
Tue, 26 Aug 2014 06:26:52 +0000 (23:26 -0700)
committerChris Dickens <christopher.a.dickens@gmail.com>
Wed, 27 Aug 2014 08:50:09 +0000 (01:50 -0700)
The current behavior of libusb_open() unconditionally interrupts
any event handlers via usbi_fd_notification(). However, not all
backends, namely Win/WinCE, make changes to the pollfd list during
a device open.

This change adds a new CAP for backends (HAS_POLLABLE_DEVICE_FD),
and libusb_open() will only call usbi_fd_notification() if the
backend declares this capability.

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
libusb/core.c
libusb/libusbi.h
libusb/os/darwin_usb.c
libusb/os/linux_usbfs.c
libusb/os/netbsd_usb.c
libusb/os/openbsd_usb.c

index f3d7ece..1b74493 100644 (file)
@@ -1125,13 +1125,15 @@ int API_EXPORTED libusb_open(libusb_device *dev,
        usbi_mutex_unlock(&ctx->open_devs_lock);
        *handle = _handle;
 
-       /* At this point, we want to interrupt any existing event handlers so
-        * that they realise the addition of the new device's poll fd. One
-        * example when this is desirable is if the user is running a separate
-        * dedicated libusb events handling thread, which is running with a long
-        * or infinite timeout. We want to interrupt that iteration of the loop,
-        * so that it picks up the new fd, and then continues. */
-       usbi_fd_notification(ctx);
+       if (usbi_backend->caps & USBI_CAP_HAS_POLLABLE_DEVICE_FD) {
+               /* At this point, we want to interrupt any existing event handlers so
+                * that they realise the addition of the new device's poll fd. One
+                * example when this is desirable is if the user is running a separate
+                * dedicated libusb events handling thread, which is running with a long
+                * or infinite timeout. We want to interrupt that iteration of the loop,
+                * so that it picks up the new fd, and then continues. */
+               usbi_fd_notification(ctx);
+       }
 
        return 0;
 }
index a36482c..f4e9973 100644 (file)
@@ -57,6 +57,7 @@
 /* Backend specific capabilities */
 #define USBI_CAP_HAS_HID_ACCESS                                        0x00010000
 #define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000
+#define USBI_CAP_HAS_POLLABLE_DEVICE_FD                0x00040000
 
 /* Maximum number of bytes in a log line */
 #define USBI_MAX_LOG_LEN       1024
index 19174b1..ed5b2ad 100644 (file)
@@ -1963,7 +1963,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
 
 const struct usbi_os_backend darwin_backend = {
         .name = "Darwin",
-        .caps = 0,
+        .caps = USBI_CAP_HAS_POLLABLE_DEVICE_FD,
         .init = darwin_init,
         .exit = darwin_exit,
         .get_device_list = NULL, /* not needed */
index db21710..77df258 100644 (file)
@@ -2646,7 +2646,7 @@ static clockid_t op_get_timerfd_clockid(void)
 
 const struct usbi_os_backend linux_usbfs_backend = {
        .name = "Linux usbfs",
-       .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
+       .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER|USBI_CAP_HAS_POLLABLE_DEVICE_FD,
        .init = op_init,
        .exit = op_exit,
        .get_device_list = NULL,
index ed4f50e..ecc0e55 100644 (file)
@@ -89,7 +89,7 @@ static int _access_endpoint(struct libusb_transfer *);
 
 const struct usbi_os_backend netbsd_backend = {
        "Synchronous NetBSD backend",
-       0,
+       USBI_CAP_HAS_POLLABLE_DEVICE_FD,
        NULL,                           /* init() */
        NULL,                           /* exit() */
        netbsd_get_device_list,
index ff470be..d1db8ca 100644 (file)
@@ -92,7 +92,7 @@ static int _bus_open(int);
 
 const struct usbi_os_backend openbsd_backend = {
        "Synchronous OpenBSD backend",
-       0,
+       USBI_CAP_HAS_POLLABLE_DEVICE_FD,
        NULL,                           /* init() */
        NULL,                           /* exit() */
        obsd_get_device_list,