1 diff --git a/third_party/libusb/src/libusb/core.c b/third_party/libusb/src/libusb/core.c
2 index e816284..abc4f89 100644
3 --- a/third_party/libusb/src/libusb/core.c
4 +++ b/third_party/libusb/src/libusb/core.c
5 @@ -1129,6 +1129,83 @@ int API_EXPORTED libusb_open(libusb_device *dev,
9 + * Open a device and obtain a device handle. A handle allows you to perform
10 + * I/O on the device in question.
12 + * Instead of opening the device itself this function accepts an open file
13 + * descriptor that it will take ownership of.
15 + * Internally, this function adds a reference to the device and makes it
16 + * available to you through libusb_get_device(). This reference is removed
17 + * during libusb_close().
19 + * This is a non-blocking function; no requests are sent over the bus.
21 + * \param dev the device to open
22 + * \param fd open file handle to the device
23 + * \param handle output location for the returned device handle pointer. Only
24 + * populated when the return code is 0.
25 + * \returns 0 on success
26 + * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure
27 + * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions
28 + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
29 + * \returns another LIBUSB_ERROR code on other failure
31 +int API_EXPORTED libusb_open_fd(libusb_device *dev,
33 + libusb_device_handle **handle)
35 + struct libusb_context *ctx = DEVICE_CTX(dev);
36 + struct libusb_device_handle *_handle;
37 + size_t priv_size = usbi_backend->device_handle_priv_size;
39 + usbi_dbg("open %d.%d", dev->bus_number, dev->device_address);
41 + if (!dev->attached) {
42 + return LIBUSB_ERROR_NO_DEVICE;
45 + _handle = malloc(sizeof(*_handle) + priv_size);
47 + return LIBUSB_ERROR_NO_MEM;
49 + r = usbi_mutex_init(&_handle->lock, NULL);
52 + return LIBUSB_ERROR_OTHER;
55 + _handle->dev = libusb_ref_device(dev);
56 + _handle->auto_detach_kernel_driver = 0;
57 + _handle->claimed_interfaces = 0;
58 + memset(&_handle->os_priv, 0, priv_size);
60 + r = usbi_backend->open_fd(_handle, fd);
62 + usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r);
63 + libusb_unref_device(dev);
64 + usbi_mutex_destroy(&_handle->lock);
69 + usbi_mutex_lock(&ctx->open_devs_lock);
70 + list_add(&_handle->list, &ctx->open_devs);
71 + usbi_mutex_unlock(&ctx->open_devs_lock);
74 + /* At this point, we want to interrupt any existing event handlers so
75 + * that they realise the addition of the new device's poll fd. One
76 + * example when this is desirable is if the user is running a separate
77 + * dedicated libusbx events handling thread, which is running with a long
78 + * or infinite timeout. We want to interrupt that iteration of the loop,
79 + * so that it picks up the new fd, and then continues. */
80 + usbi_fd_notification(ctx);
86 * Convenience function for finding a device with a particular
87 * <tt>idVendor</tt>/<tt>idProduct</tt> combination. This function is intended
88 * for those scenarios where you are using libusbx to knock up a quick test
89 diff --git a/third_party/libusb/src/libusb/libusb.h b/third_party/libusb/src/libusb/libusb.h
90 index d144b3e..5d60951 100644
91 --- a/third_party/libusb/src/libusb/libusb.h
92 +++ b/third_party/libusb/src/libusb/libusb.h
93 @@ -1371,6 +1371,8 @@ int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
94 unsigned char endpoint);
96 int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
97 +int LIBUSB_CALL libusb_open_fd(libusb_device *dev, int fd,
98 + libusb_device_handle **handle);
99 void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
100 libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle);
102 diff --git a/third_party/libusb/src/libusb/libusbi.h b/third_party/libusb/src/libusb/libusbi.h
103 index bc608b92..eb2f0e6 100644
104 --- a/third_party/libusb/src/libusb/libusbi.h
105 +++ b/third_party/libusb/src/libusb/libusbi.h
106 @@ -615,6 +615,11 @@ struct usbi_os_backend {
108 int (*open)(struct libusb_device_handle *handle);
110 + /* Like open() above but uses the file descriptor provided instead of opening
113 + int (*open_fd)(struct libusb_device_handle *handle, int fd);
115 /* Close a device such that the handle cannot be used again. Your backend
116 * should destroy any resources that were allocated in the open path.
117 * This may also be a good place to call usbi_remove_pollfd() to inform
118 diff --git a/third_party/libusb/src/libusb/os/darwin_usb.c b/third_party/libusb/src/libusb/os/darwin_usb.c
119 index f95706a..f6b397e 100644
120 --- a/third_party/libusb/src/libusb/os/darwin_usb.c
121 +++ b/third_party/libusb/src/libusb/os/darwin_usb.c
122 @@ -1877,6 +1877,7 @@ const struct usbi_os_backend darwin_backend = {
123 .get_config_descriptor = darwin_get_config_descriptor,
126 + .open_fd = NULL, /* not implemented */
127 .close = darwin_close,
128 .get_configuration = darwin_get_configuration,
129 .set_configuration = darwin_set_configuration,
130 diff --git a/third_party/libusb/src/libusb/os/linux_usbfs.c b/third_party/libusb/src/libusb/os/linux_usbfs.c
131 index 142fa2b..e965856 100644
132 --- a/third_party/libusb/src/libusb/os/linux_usbfs.c
133 +++ b/third_party/libusb/src/libusb/os/linux_usbfs.c
134 @@ -1259,26 +1259,12 @@ static int linux_default_scan_devices (struct libusb_context *ctx)
138 -static int op_open(struct libusb_device_handle *handle)
139 +static int op_open_fd(struct libusb_device_handle *handle, int fd)
141 struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
144 - hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
145 - if (hpriv->fd < 0) {
146 - if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
147 - /* device will still be marked as attached if hotplug monitor thread
148 - * hasn't processed remove event yet */
149 - usbi_mutex_static_lock(&linux_hotplug_lock);
150 - if (handle->dev->attached) {
151 - usbi_dbg("open failed with no device, but device still attached");
152 - linux_device_disconnected(handle->dev->bus_number,
153 - handle->dev->device_address, NULL);
155 - usbi_mutex_static_unlock(&linux_hotplug_lock);
161 r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
163 @@ -1296,6 +1282,29 @@ static int op_open(struct libusb_device_handle *handle)
164 return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
167 +static int op_open(struct libusb_device_handle *handle)
169 + struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
170 + int fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
173 + if (fd == LIBUSB_ERROR_NO_DEVICE) {
174 + /* device will still be marked as attached if hotplug monitor thread
175 + * hasn't processed remove event yet */
176 + usbi_mutex_static_lock(&linux_hotplug_lock);
177 + if (handle->dev->attached) {
178 + usbi_dbg("open failed with no device, but device still attached");
179 + linux_device_disconnected(handle->dev->bus_number,
180 + handle->dev->device_address, NULL);
182 + usbi_mutex_static_unlock(&linux_hotplug_lock);
187 + return op_open_fd(handle, fd);
190 static void op_close(struct libusb_device_handle *dev_handle)
192 int fd = _device_handle_priv(dev_handle)->fd;
193 @@ -2570,6 +2579,7 @@ const struct usbi_os_backend linux_usbfs_backend = {
194 .get_config_descriptor_by_value = op_get_config_descriptor_by_value,
197 + .open_fd = op_open_fd,
199 .get_configuration = op_get_configuration,
200 .set_configuration = op_set_configuration,
201 diff --git a/third_party/libusb/src/libusb/os/openbsd_usb.c b/third_party/libusb/src/libusb/os/openbsd_usb.c
202 index 2997e53..2d24f2c 100644
203 --- a/third_party/libusb/src/libusb/os/openbsd_usb.c
204 +++ b/third_party/libusb/src/libusb/os/openbsd_usb.c
205 @@ -98,6 +98,7 @@ const struct usbi_os_backend openbsd_backend = {
206 obsd_get_device_list,
207 NULL, /* hotplug_poll */
209 + NULL, /* open_fd */
212 obsd_get_device_descriptor,
213 diff --git a/third_party/libusb/src/libusb/os/wince_usb.c b/third_party/libusb/src/libusb/os/wince_usb.c
214 index 90c129b..c069c56 100644
215 --- a/third_party/libusb/src/libusb/os/wince_usb.c
216 +++ b/third_party/libusb/src/libusb/os/wince_usb.c
217 @@ -990,6 +990,7 @@ const struct usbi_os_backend wince_backend = {
218 wince_get_device_list,
219 NULL, /* hotplug_poll */
221 + NULL, /* open_fd */
224 wince_get_device_descriptor,
225 diff --git a/third_party/libusb/src/libusb/os/windows_usb.c b/third_party/libusb/src/libusb/os/windows_usb.c
226 index 4469992..bc4def6 100644
227 --- a/third_party/libusb/src/libusb/os/windows_usb.c
228 +++ b/third_party/libusb/src/libusb/os/windows_usb.c
229 @@ -2290,6 +2290,7 @@ const struct usbi_os_backend windows_backend = {
230 windows_get_device_list,
231 NULL, /* hotplug_poll */
233 + NULL, /* open_fd */
236 windows_get_device_descriptor,