libusb 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +1 -0
- data/History.md +10 -0
- data/README.md +19 -6
- data/Rakefile +1 -1
- data/ext/extconf.rb +17 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
- data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
- data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
- data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
- data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
- data/ext/libusbx-1.0.17/android/README +114 -0
- data/ext/libusbx-1.0.17/android/config.h +90 -0
- data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
- data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
- data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
- data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
- data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
- data/ext/libusbx-1.0.17/compile +347 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
- data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
- data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
- data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
- data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
- data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
- data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
- data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
- data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
- data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
- data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
- data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
- data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
- data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
- data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
- data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
- data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
- data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
- data/ext/libusbx-1.0.17/missing +215 -0
- data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
- data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
- data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
- data/ext/libusbx-1.0.17/tests/stress.c +160 -0
- data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
- data/lib/libusb.rb +4 -0
- data/lib/libusb/call.rb +43 -1
- data/lib/libusb/constants.rb +5 -0
- data/lib/libusb/context.rb +100 -0
- data/lib/libusb/dev_handle.rb +27 -0
- data/lib/libusb/device.rb +10 -4
- data/lib/libusb/version_gem.rb +1 -1
- data/test/test_libusb_capability.rb +2 -2
- data/test/test_libusb_compat.rb +2 -2
- data/test/test_libusb_compat_mass_storage.rb +2 -2
- data/test/test_libusb_descriptors.rb +4 -2
- data/test/test_libusb_event_machine.rb +2 -2
- data/test/test_libusb_gc.rb +2 -2
- data/test/test_libusb_hotplug.rb +115 -0
- data/test/test_libusb_iso_transfer.rb +3 -3
- data/test/test_libusb_mass_storage.rb +6 -16
- data/test/test_libusb_mass_storage2.rb +26 -3
- data/test/test_libusb_structs.rb +2 -2
- data/test/test_libusb_threads.rb +2 -2
- data/test/test_libusb_version.rb +2 -2
- metadata +127 -68
- metadata.gz.sig +0 -0
- data/ext/libusbx-1.0.14/THANKS +0 -7
- data/ext/libusbx-1.0.14/compile +0 -143
- data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
- data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
- data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
- data/ext/libusbx-1.0.14/missing +0 -376
@@ -0,0 +1,322 @@
|
|
1
|
+
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
|
2
|
+
/*
|
3
|
+
* Hotplug functions for libusbx
|
4
|
+
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
|
5
|
+
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
|
6
|
+
*
|
7
|
+
* This library is free software; you can redistribute it and/or
|
8
|
+
* modify it under the terms of the GNU Lesser General Public
|
9
|
+
* License as published by the Free Software Foundation; either
|
10
|
+
* version 2.1 of the License, or (at your option) any later version.
|
11
|
+
*
|
12
|
+
* This library is distributed in the hope that it will be useful,
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
* Lesser General Public License for more details.
|
16
|
+
*
|
17
|
+
* You should have received a copy of the GNU Lesser General Public
|
18
|
+
* License along with this library; if not, write to the Free Software
|
19
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <config.h>
|
23
|
+
|
24
|
+
#include <errno.h>
|
25
|
+
#include <stdio.h>
|
26
|
+
#include <stdlib.h>
|
27
|
+
#include <string.h>
|
28
|
+
#ifdef HAVE_SYS_TYPES_H
|
29
|
+
#include <sys/types.h>
|
30
|
+
#endif
|
31
|
+
#include <assert.h>
|
32
|
+
|
33
|
+
#include "libusbi.h"
|
34
|
+
#include "hotplug.h"
|
35
|
+
|
36
|
+
/**
|
37
|
+
* @defgroup hotplug Device hotplug event notification
|
38
|
+
* This page details how to use the libusb hotplug interface, where available.
|
39
|
+
*
|
40
|
+
* Be mindful that not all platforms currently implement hotplug notification and
|
41
|
+
* that you should first call on \ref libusb_has_capability() with parameter
|
42
|
+
* \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
|
43
|
+
*
|
44
|
+
* \page hotplug Device hotplug event notification
|
45
|
+
*
|
46
|
+
* \section intro Introduction
|
47
|
+
*
|
48
|
+
* Version 1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, has added support
|
49
|
+
* for hotplug events on <b>some</b> platforms (you should test if your platform
|
50
|
+
* supports hotplug notification by calling \ref libusb_has_capability() with
|
51
|
+
* parameter \ref LIBUSB_CAP_HAS_HOTPLUG).
|
52
|
+
*
|
53
|
+
* This interface allows you to request notification for the arrival and departure
|
54
|
+
* of matching USB devices.
|
55
|
+
*
|
56
|
+
* To receive hotplug notification you register a callback by calling
|
57
|
+
* \ref libusb_hotplug_register_callback(). This function will optionally return
|
58
|
+
* a handle that can be passed to \ref libusb_hotplug_deregister_callback().
|
59
|
+
*
|
60
|
+
* A callback function must return an int (0 or 1) indicating whether the callback is
|
61
|
+
* expecting additional events. Returning 0 will rearm the callback and 1 will cause
|
62
|
+
* the callback to be deregistered. Note that when callbacks are called from
|
63
|
+
* libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE
|
64
|
+
* flag, the callback return value is ignored, iow you cannot cause a callback
|
65
|
+
* to be deregistered by returning 1 when it is called from
|
66
|
+
* libusb_hotplug_register_callback().
|
67
|
+
*
|
68
|
+
* Callbacks for a particular context are automatically deregistered by libusb_exit().
|
69
|
+
*
|
70
|
+
* As of 1.0.16 there are two supported hotplug events:
|
71
|
+
* - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use
|
72
|
+
* - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available
|
73
|
+
*
|
74
|
+
* A hotplug event can listen for either or both of these events.
|
75
|
+
*
|
76
|
+
* Note: If you receive notification that a device has left and you have any
|
77
|
+
* a libusb_device_handles for the device it is up to you to call libusb_close()
|
78
|
+
* on each handle to free up any remaining resources associated with the device.
|
79
|
+
* Once a device has left any libusb_device_handle associated with the device
|
80
|
+
* are invalid and will remain so even if the device comes back.
|
81
|
+
*
|
82
|
+
* When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
|
83
|
+
* safe to call any libusbx function that takes a libusb_device. On the other hand,
|
84
|
+
* when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
|
85
|
+
* is libusb_get_device_descriptor().
|
86
|
+
*
|
87
|
+
* The following code provides an example of the usage of the hotplug interface:
|
88
|
+
\code
|
89
|
+
static int count = 0;
|
90
|
+
|
91
|
+
int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
|
92
|
+
libusb_hotplug_event event, void *user_data) {
|
93
|
+
static libusb_device_handle *handle = NULL;
|
94
|
+
struct libusb_device_descriptor desc;
|
95
|
+
int rc;
|
96
|
+
|
97
|
+
(void)libusb_get_device_descriptor(dev, &desc);
|
98
|
+
|
99
|
+
if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
|
100
|
+
rc = libusb_open(dev, &handle);
|
101
|
+
if (LIBUSB_SUCCESS != rc) {
|
102
|
+
printf("Could not open USB device\n");
|
103
|
+
}
|
104
|
+
} else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
|
105
|
+
if (handle) {
|
106
|
+
libusb_close(handle);
|
107
|
+
handle = NULL;
|
108
|
+
}
|
109
|
+
} else {
|
110
|
+
printf("Unhandled event %d\n", event);
|
111
|
+
}
|
112
|
+
count++;
|
113
|
+
|
114
|
+
return 0;
|
115
|
+
}
|
116
|
+
|
117
|
+
int main (void) {
|
118
|
+
libusb_hotplug_callback_handle handle;
|
119
|
+
int rc;
|
120
|
+
|
121
|
+
libusb_init(NULL);
|
122
|
+
|
123
|
+
rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
|
124
|
+
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
|
125
|
+
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
|
126
|
+
&handle);
|
127
|
+
if (LIBUSB_SUCCESS != rc) {
|
128
|
+
printf("Error creating a hotplug callback\n");
|
129
|
+
libusb_exit(NULL);
|
130
|
+
return EXIT_FAILURE;
|
131
|
+
}
|
132
|
+
|
133
|
+
while (count < 2) {
|
134
|
+
usleep(10000);
|
135
|
+
}
|
136
|
+
|
137
|
+
libusb_hotplug_deregister_callback(handle);
|
138
|
+
libusb_exit(NULL);
|
139
|
+
|
140
|
+
return 0;
|
141
|
+
}
|
142
|
+
\endcode
|
143
|
+
*/
|
144
|
+
|
145
|
+
static int usbi_hotplug_match_cb (struct libusb_context *ctx,
|
146
|
+
struct libusb_device *dev, libusb_hotplug_event event,
|
147
|
+
struct libusb_hotplug_callback *hotplug_cb)
|
148
|
+
{
|
149
|
+
/* Handle lazy deregistration of callback */
|
150
|
+
if (hotplug_cb->needs_free) {
|
151
|
+
/* Free callback */
|
152
|
+
return 1;
|
153
|
+
}
|
154
|
+
|
155
|
+
if (!(hotplug_cb->events & event)) {
|
156
|
+
return 0;
|
157
|
+
}
|
158
|
+
|
159
|
+
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
|
160
|
+
hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
|
161
|
+
return 0;
|
162
|
+
}
|
163
|
+
|
164
|
+
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
|
165
|
+
hotplug_cb->product_id != dev->device_descriptor.idProduct) {
|
166
|
+
return 0;
|
167
|
+
}
|
168
|
+
|
169
|
+
if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
|
170
|
+
hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
|
171
|
+
return 0;
|
172
|
+
}
|
173
|
+
|
174
|
+
return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
|
175
|
+
}
|
176
|
+
|
177
|
+
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
178
|
+
libusb_hotplug_event event)
|
179
|
+
{
|
180
|
+
struct libusb_hotplug_callback *hotplug_cb, *next;
|
181
|
+
int ret;
|
182
|
+
|
183
|
+
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
184
|
+
|
185
|
+
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
|
186
|
+
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
187
|
+
ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
|
188
|
+
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
189
|
+
|
190
|
+
if (ret) {
|
191
|
+
list_del(&hotplug_cb->list);
|
192
|
+
free(hotplug_cb);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
197
|
+
|
198
|
+
/* the backend is expected to call the callback for each active transfer */
|
199
|
+
}
|
200
|
+
|
201
|
+
int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
|
202
|
+
libusb_hotplug_event events, libusb_hotplug_flag flags,
|
203
|
+
int vendor_id, int product_id, int dev_class,
|
204
|
+
libusb_hotplug_callback_fn cb_fn, void *user_data,
|
205
|
+
libusb_hotplug_callback_handle *handle)
|
206
|
+
{
|
207
|
+
libusb_hotplug_callback *new_callback;
|
208
|
+
static int handle_id = 1;
|
209
|
+
|
210
|
+
/* check for hotplug support */
|
211
|
+
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
212
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
213
|
+
}
|
214
|
+
|
215
|
+
/* check for sane values */
|
216
|
+
if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
|
217
|
+
(LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
|
218
|
+
(LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
|
219
|
+
!cb_fn) {
|
220
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
221
|
+
}
|
222
|
+
|
223
|
+
USBI_GET_CONTEXT(ctx);
|
224
|
+
|
225
|
+
new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
|
226
|
+
if (!new_callback) {
|
227
|
+
return LIBUSB_ERROR_NO_MEM;
|
228
|
+
}
|
229
|
+
|
230
|
+
new_callback->ctx = ctx;
|
231
|
+
new_callback->vendor_id = vendor_id;
|
232
|
+
new_callback->product_id = product_id;
|
233
|
+
new_callback->dev_class = dev_class;
|
234
|
+
new_callback->flags = flags;
|
235
|
+
new_callback->events = events;
|
236
|
+
new_callback->cb = cb_fn;
|
237
|
+
new_callback->user_data = user_data;
|
238
|
+
new_callback->needs_free = 0;
|
239
|
+
|
240
|
+
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
241
|
+
|
242
|
+
/* protect the handle by the context hotplug lock. it doesn't matter if the same handle
|
243
|
+
* is used for different contexts only that the handle is unique for this context */
|
244
|
+
new_callback->handle = handle_id++;
|
245
|
+
|
246
|
+
list_add(&new_callback->list, &ctx->hotplug_cbs);
|
247
|
+
|
248
|
+
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
249
|
+
|
250
|
+
|
251
|
+
if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
|
252
|
+
int i, len;
|
253
|
+
struct libusb_device **devs;
|
254
|
+
|
255
|
+
len = (int) libusb_get_device_list(ctx, &devs);
|
256
|
+
if (len < 0) {
|
257
|
+
libusb_hotplug_deregister_callback(ctx,
|
258
|
+
new_callback->handle);
|
259
|
+
return len;
|
260
|
+
}
|
261
|
+
|
262
|
+
for (i = 0; i < len; i++) {
|
263
|
+
usbi_hotplug_match_cb(ctx, devs[i],
|
264
|
+
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
|
265
|
+
new_callback);
|
266
|
+
}
|
267
|
+
|
268
|
+
libusb_free_device_list(devs, 1);
|
269
|
+
}
|
270
|
+
|
271
|
+
|
272
|
+
if (handle) {
|
273
|
+
*handle = new_callback->handle;
|
274
|
+
}
|
275
|
+
|
276
|
+
return LIBUSB_SUCCESS;
|
277
|
+
}
|
278
|
+
|
279
|
+
void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
|
280
|
+
libusb_hotplug_callback_handle handle)
|
281
|
+
{
|
282
|
+
struct libusb_hotplug_callback *hotplug_cb;
|
283
|
+
libusb_hotplug_message message;
|
284
|
+
ssize_t ret;
|
285
|
+
|
286
|
+
/* check for hotplug support */
|
287
|
+
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
288
|
+
return;
|
289
|
+
}
|
290
|
+
|
291
|
+
USBI_GET_CONTEXT(ctx);
|
292
|
+
|
293
|
+
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
294
|
+
list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
|
295
|
+
struct libusb_hotplug_callback) {
|
296
|
+
if (handle == hotplug_cb->handle) {
|
297
|
+
/* Mark this callback for deregistration */
|
298
|
+
hotplug_cb->needs_free = 1;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
302
|
+
|
303
|
+
/* wakeup handle_events to do the actual free */
|
304
|
+
memset(&message, 0, sizeof(message));
|
305
|
+
ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message));
|
306
|
+
if (sizeof(message) != ret) {
|
307
|
+
usbi_err(ctx, "error writing hotplug message");
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
|
312
|
+
struct libusb_hotplug_callback *hotplug_cb, *next;
|
313
|
+
|
314
|
+
usbi_mutex_lock(&ctx->hotplug_cbs_lock);
|
315
|
+
list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
|
316
|
+
struct libusb_hotplug_callback) {
|
317
|
+
list_del(&hotplug_cb->list);
|
318
|
+
free(hotplug_cb);
|
319
|
+
}
|
320
|
+
|
321
|
+
usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
|
322
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
|
2
|
+
/*
|
3
|
+
* Hotplug support for libusbx
|
4
|
+
* Copyright © 2012-2013 Nathan Hjelm <hjelmn@mac.com>
|
5
|
+
* Copyright © 2012-2013 Peter Stuge <peter@stuge.se>
|
6
|
+
*
|
7
|
+
* This library is free software; you can redistribute it and/or
|
8
|
+
* modify it under the terms of the GNU Lesser General Public
|
9
|
+
* License as published by the Free Software Foundation; either
|
10
|
+
* version 2.1 of the License, or (at your option) any later version.
|
11
|
+
*
|
12
|
+
* This library is distributed in the hope that it will be useful,
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
* Lesser General Public License for more details.
|
16
|
+
*
|
17
|
+
* You should have received a copy of the GNU Lesser General Public
|
18
|
+
* License along with this library; if not, write to the Free Software
|
19
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
*/
|
21
|
+
|
22
|
+
#if !defined(USBI_HOTPLUG_H)
|
23
|
+
#define USBI_HOTPLUG_H
|
24
|
+
|
25
|
+
#ifndef LIBUSBI_H
|
26
|
+
#include "libusbi.h"
|
27
|
+
#endif
|
28
|
+
|
29
|
+
/** \ingroup hotplug
|
30
|
+
* The hotplug callback structure. The user populates this structure with
|
31
|
+
* libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback()
|
32
|
+
* to receive notification of hotplug events.
|
33
|
+
*/
|
34
|
+
struct libusb_hotplug_callback {
|
35
|
+
/** Context this callback is associated with */
|
36
|
+
struct libusb_context *ctx;
|
37
|
+
|
38
|
+
/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
39
|
+
int vendor_id;
|
40
|
+
|
41
|
+
/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
42
|
+
int product_id;
|
43
|
+
|
44
|
+
/** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */
|
45
|
+
int dev_class;
|
46
|
+
|
47
|
+
/** Hotplug callback flags */
|
48
|
+
libusb_hotplug_flag flags;
|
49
|
+
|
50
|
+
/** Event(s) that will trigger this callback */
|
51
|
+
libusb_hotplug_event events;
|
52
|
+
|
53
|
+
/** Callback function to invoke for matching event/device */
|
54
|
+
libusb_hotplug_callback_fn cb;
|
55
|
+
|
56
|
+
/** Handle for this callback (used to match on deregister) */
|
57
|
+
libusb_hotplug_callback_handle handle;
|
58
|
+
|
59
|
+
/** User data that will be passed to the callback function */
|
60
|
+
void *user_data;
|
61
|
+
|
62
|
+
/** Callback is marked for deletion */
|
63
|
+
int needs_free;
|
64
|
+
|
65
|
+
/** List this callback is registered in (ctx->hotplug_cbs) */
|
66
|
+
struct list_head list;
|
67
|
+
};
|
68
|
+
|
69
|
+
typedef struct libusb_hotplug_callback libusb_hotplug_callback;
|
70
|
+
|
71
|
+
struct libusb_hotplug_message {
|
72
|
+
libusb_hotplug_event event;
|
73
|
+
struct libusb_device *device;
|
74
|
+
};
|
75
|
+
|
76
|
+
typedef struct libusb_hotplug_message libusb_hotplug_message;
|
77
|
+
|
78
|
+
void usbi_hotplug_deregister_all(struct libusb_context *ctx);
|
79
|
+
void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
|
80
|
+
libusb_hotplug_event event);
|
81
|
+
|
82
|
+
#endif
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
|
1
2
|
/*
|
2
3
|
* I/O functions for libusbx
|
3
4
|
* Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
|
@@ -18,23 +19,24 @@
|
|
18
19
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
19
20
|
*/
|
20
21
|
|
21
|
-
#include
|
22
|
+
#include "config.h"
|
22
23
|
#include <errno.h>
|
23
|
-
#include <signal.h>
|
24
24
|
#include <stdint.h>
|
25
25
|
#include <stdlib.h>
|
26
26
|
#include <string.h>
|
27
27
|
#include <time.h>
|
28
|
-
|
28
|
+
#ifdef HAVE_SIGNAL_H
|
29
|
+
#include <signal.h>
|
30
|
+
#endif
|
29
31
|
#ifdef HAVE_SYS_TIME_H
|
30
32
|
#include <sys/time.h>
|
31
33
|
#endif
|
32
|
-
|
33
34
|
#ifdef USBI_TIMERFD_AVAILABLE
|
34
35
|
#include <sys/timerfd.h>
|
35
36
|
#endif
|
36
37
|
|
37
38
|
#include "libusbi.h"
|
39
|
+
#include "hotplug.h"
|
38
40
|
|
39
41
|
/**
|
40
42
|
* \page io Synchronous and asynchronous device I/O
|
@@ -494,10 +496,7 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
494
496
|
*
|
495
497
|
* \section asyncevent Event handling
|
496
498
|
*
|
497
|
-
*
|
498
|
-
* create threads internally. This means that libusbx code does not execute
|
499
|
-
* at any time other than when your application is calling a libusbx function.
|
500
|
-
* However, an asynchronous model requires that libusbx perform work at various
|
499
|
+
* An asynchronous model requires that libusbx perform work at various
|
501
500
|
* points in time - namely processing the results of previously-submitted
|
502
501
|
* transfers and invoking the user-supplied callback function.
|
503
502
|
*
|
@@ -505,39 +504,79 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
505
504
|
* application must call into when libusbx has work do to. This gives libusbx
|
506
505
|
* the opportunity to reap pending transfers, invoke callbacks, etc.
|
507
506
|
*
|
508
|
-
*
|
509
|
-
*
|
510
|
-
* do not actually require your application to know this:
|
511
|
-
* -# Periodically call libusb_handle_events() in non-blocking mode at fixed
|
512
|
-
* short intervals from your main loop
|
507
|
+
* There are 2 different approaches to dealing with libusb_handle_events:
|
508
|
+
*
|
513
509
|
* -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated
|
514
510
|
* thread.
|
511
|
+
* -# Integrate libusbx with your application's main event loop. libusbx
|
512
|
+
* exposes a set of file descriptors which allow you to do this.
|
515
513
|
*
|
516
|
-
* The first
|
517
|
-
*
|
518
|
-
*
|
519
|
-
*
|
520
|
-
*
|
514
|
+
* The first approach has the big advantage that it will also work on Windows
|
515
|
+
* were libusbx' poll API for select / poll integration is not available. So
|
516
|
+
* if you want to support Windows and use the async API, you must use this
|
517
|
+
* approach, see the \ref eventthread "Using an event handling thread" section
|
518
|
+
* below for details.
|
521
519
|
*
|
522
|
-
*
|
523
|
-
*
|
524
|
-
*
|
525
|
-
* variant on a set of file descriptors for other event sources (e.g. keyboard
|
526
|
-
* button presses, mouse movements, network sockets, etc). You then add
|
527
|
-
* libusbx's file descriptors to your poll()/select() calls, and when activity
|
528
|
-
* is detected on such descriptors you know it is time to call
|
529
|
-
* libusb_handle_events().
|
520
|
+
* If you prefer a single threaded approach with a single central event loop,
|
521
|
+
* see the \ref poll "polling and timing" section for how to integrate libusbx
|
522
|
+
* into your application's main event loop.
|
530
523
|
*
|
531
|
-
*
|
532
|
-
*
|
533
|
-
*
|
534
|
-
*
|
535
|
-
*
|
536
|
-
*
|
537
|
-
*
|
524
|
+
* \section eventthread Using an event handling thread
|
525
|
+
*
|
526
|
+
* Lets begin with stating the obvious: If you're going to use a separate
|
527
|
+
* thread for libusbx event handling, your callback functions MUST be
|
528
|
+
* threadsafe.
|
529
|
+
*
|
530
|
+
* Other then that doing event handling from a separate thread, is mostly
|
531
|
+
* simple. You can use an event thread function as follows:
|
532
|
+
\code
|
533
|
+
void *event_thread_func(void *ctx)
|
534
|
+
{
|
535
|
+
while (event_thread_run)
|
536
|
+
libusb_handle_events(ctx);
|
537
|
+
|
538
|
+
return NULL;
|
539
|
+
}
|
540
|
+
\endcode
|
541
|
+
*
|
542
|
+
* There is one caveat though, stopping this thread requires setting the
|
543
|
+
* event_thread_run variable to 0, and after that libusb_handle_events() needs
|
544
|
+
* to return control to event_thread_func. But unless some event happens,
|
545
|
+
* libusb_handle_events() will not return.
|
546
|
+
*
|
547
|
+
* There are 2 different ways of dealing with this, depending on if your
|
548
|
+
* application uses libusbx' \ref hotplug "hotplug" support or not.
|
549
|
+
*
|
550
|
+
* Applications which do not use hotplug support, should not start the event
|
551
|
+
* thread until after their first call to libusb_open(), and should stop the
|
552
|
+
* thread when closing the last open device as follows:
|
553
|
+
\code
|
554
|
+
void my_close_handle(libusb_device_handle *handle)
|
555
|
+
{
|
556
|
+
if (open_devs == 1)
|
557
|
+
event_thread_run = 0;
|
558
|
+
|
559
|
+
libusb_close(handle); // This wakes up libusb_handle_events()
|
560
|
+
|
561
|
+
if (open_devs == 1)
|
562
|
+
pthread_join(event_thread);
|
563
|
+
|
564
|
+
open_devs--;
|
565
|
+
}
|
566
|
+
\endcode
|
538
567
|
*
|
539
|
-
*
|
540
|
-
*
|
568
|
+
* Applications using hotplug support should start the thread at program init,
|
569
|
+
* after having successfully called libusb_hotplug_register_callback(), and
|
570
|
+
* should stop the thread at program exit as follows:
|
571
|
+
\code
|
572
|
+
void my_libusb_exit(void)
|
573
|
+
{
|
574
|
+
event_thread_run = 0;
|
575
|
+
libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events()
|
576
|
+
pthread_join(event_thread);
|
577
|
+
libusb_exit(ctx);
|
578
|
+
}
|
579
|
+
\endcode
|
541
580
|
*/
|
542
581
|
|
543
582
|
/**
|
@@ -554,6 +593,24 @@ if (r == 0 && actual_length == sizeof(data)) {
|
|
554
593
|
* asynchronous API documentation. In summary, libusbx does not create internal
|
555
594
|
* threads for event processing and hence relies on your application calling
|
556
595
|
* into libusbx at certain points in time so that pending events can be handled.
|
596
|
+
*
|
597
|
+
* Your main loop is probably already calling poll() or select() or a
|
598
|
+
* variant on a set of file descriptors for other event sources (e.g. keyboard
|
599
|
+
* button presses, mouse movements, network sockets, etc). You then add
|
600
|
+
* libusbx's file descriptors to your poll()/select() calls, and when activity
|
601
|
+
* is detected on such descriptors you know it is time to call
|
602
|
+
* libusb_handle_events().
|
603
|
+
*
|
604
|
+
* There is one final event handling complication. libusbx supports
|
605
|
+
* asynchronous transfers which time out after a specified time period.
|
606
|
+
*
|
607
|
+
* On some platforms a timerfd is used, so the timeout handling is just another
|
608
|
+
* fd, on other platforms this requires that libusbx is called into at or after
|
609
|
+
* the timeout to handle it. So, in addition to considering libusbx's file
|
610
|
+
* descriptors in your main event loop, you must also consider that libusbx
|
611
|
+
* sometimes needs to be called into at fixed points in time even when there
|
612
|
+
* is no file descriptor activity, see \ref polltime details.
|
613
|
+
*
|
557
614
|
* In order to know precisely when libusbx needs to be called into, libusbx
|
558
615
|
* offers you a set of pollable file descriptors and information about when
|
559
616
|
* the next timeout expires.
|
@@ -583,8 +640,9 @@ while (user_has_not_requested_exit)
|
|
583
640
|
* \section pollmain The more advanced option
|
584
641
|
*
|
585
642
|
* \note This functionality is currently only available on Unix-like platforms.
|
586
|
-
* On Windows, libusb_get_pollfds() simply returns NULL.
|
587
|
-
*
|
643
|
+
* On Windows, libusb_get_pollfds() simply returns NULL. Applications which
|
644
|
+
* want to support Windows are advised to use an \ref eventthread
|
645
|
+
* "event handling thread" instead.
|
588
646
|
*
|
589
647
|
* In more advanced applications, you will already have a main loop which
|
590
648
|
* is monitoring other event sources: network sockets, X11 events, mouse
|
@@ -729,7 +787,7 @@ void cb(struct libusb_transfer *transfer)
|
|
729
787
|
|
730
788
|
void myfunc() {
|
731
789
|
struct libusb_transfer *transfer;
|
732
|
-
unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE];
|
790
|
+
unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2)));
|
733
791
|
int completed = 0;
|
734
792
|
|
735
793
|
transfer = libusb_alloc_transfer(0);
|
@@ -1070,6 +1128,17 @@ int usbi_io_init(struct libusb_context *ctx)
|
|
1070
1128
|
if (r < 0)
|
1071
1129
|
goto err_close_pipe;
|
1072
1130
|
|
1131
|
+
/* create hotplug pipe */
|
1132
|
+
r = usbi_pipe(ctx->hotplug_pipe);
|
1133
|
+
if (r < 0) {
|
1134
|
+
r = LIBUSB_ERROR_OTHER;
|
1135
|
+
goto err;
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
r = usbi_add_pollfd(ctx, ctx->hotplug_pipe[0], POLLIN);
|
1139
|
+
if (r < 0)
|
1140
|
+
goto err_close_hp_pipe;
|
1141
|
+
|
1073
1142
|
#ifdef USBI_TIMERFD_AVAILABLE
|
1074
1143
|
ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
|
1075
1144
|
TFD_NONBLOCK);
|
@@ -1079,7 +1148,7 @@ int usbi_io_init(struct libusb_context *ctx)
|
|
1079
1148
|
if (r < 0) {
|
1080
1149
|
usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
|
1081
1150
|
close(ctx->timerfd);
|
1082
|
-
goto
|
1151
|
+
goto err_close_hp_pipe;
|
1083
1152
|
}
|
1084
1153
|
} else {
|
1085
1154
|
usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno);
|
@@ -1089,6 +1158,9 @@ int usbi_io_init(struct libusb_context *ctx)
|
|
1089
1158
|
|
1090
1159
|
return 0;
|
1091
1160
|
|
1161
|
+
err_close_hp_pipe:
|
1162
|
+
usbi_close(ctx->hotplug_pipe[0]);
|
1163
|
+
usbi_close(ctx->hotplug_pipe[1]);
|
1092
1164
|
err_close_pipe:
|
1093
1165
|
usbi_close(ctx->ctrl_pipe[0]);
|
1094
1166
|
usbi_close(ctx->ctrl_pipe[1]);
|
@@ -1107,6 +1179,9 @@ void usbi_io_exit(struct libusb_context *ctx)
|
|
1107
1179
|
usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
|
1108
1180
|
usbi_close(ctx->ctrl_pipe[0]);
|
1109
1181
|
usbi_close(ctx->ctrl_pipe[1]);
|
1182
|
+
usbi_remove_pollfd(ctx, ctx->hotplug_pipe[0]);
|
1183
|
+
usbi_close(ctx->hotplug_pipe[0]);
|
1184
|
+
usbi_close(ctx->hotplug_pipe[1]);
|
1110
1185
|
#ifdef USBI_TIMERFD_AVAILABLE
|
1111
1186
|
if (usbi_using_timerfd(ctx)) {
|
1112
1187
|
usbi_remove_pollfd(ctx, ctx->timerfd);
|
@@ -1151,8 +1226,10 @@ static int calculate_timeout(struct usbi_transfer *transfer)
|
|
1151
1226
|
}
|
1152
1227
|
|
1153
1228
|
/* add a transfer to the (timeout-sorted) active transfers list.
|
1154
|
-
*
|
1155
|
-
*
|
1229
|
+
* Callers of this function must hold the flying_transfers_lock.
|
1230
|
+
* This function *always* adds the transfer to the flying_transfers list,
|
1231
|
+
* it will return non 0 if it fails to update the timer, but even then the
|
1232
|
+
* transfer is added to the flying_transfers list. */
|
1156
1233
|
static int add_to_flying_list(struct usbi_transfer *transfer)
|
1157
1234
|
{
|
1158
1235
|
struct usbi_transfer *cur;
|
@@ -1161,8 +1238,6 @@ static int add_to_flying_list(struct usbi_transfer *transfer)
|
|
1161
1238
|
int r = 0;
|
1162
1239
|
int first = 1;
|
1163
1240
|
|
1164
|
-
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
1165
|
-
|
1166
1241
|
/* if we have no other flying transfers, start the list with this one */
|
1167
1242
|
if (list_empty(&ctx->flying_transfers)) {
|
1168
1243
|
list_add(&transfer->list, &ctx->flying_transfers);
|
@@ -1212,7 +1287,6 @@ out:
|
|
1212
1287
|
UNUSED(first);
|
1213
1288
|
#endif
|
1214
1289
|
|
1215
|
-
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
1216
1290
|
return r;
|
1217
1291
|
}
|
1218
1292
|
|
@@ -1374,17 +1448,19 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
|
|
1374
1448
|
goto out;
|
1375
1449
|
}
|
1376
1450
|
|
1451
|
+
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
1377
1452
|
r = add_to_flying_list(itransfer);
|
1378
|
-
if (r)
|
1379
|
-
|
1380
|
-
|
1381
|
-
if (r) {
|
1382
|
-
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
1453
|
+
if (r == LIBUSB_SUCCESS) {
|
1454
|
+
r = usbi_backend->submit_transfer(itransfer);
|
1455
|
+
}
|
1456
|
+
if (r != LIBUSB_SUCCESS) {
|
1383
1457
|
list_del(&itransfer->list);
|
1384
1458
|
arm_timerfd_for_next_timeout(ctx);
|
1385
|
-
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
1386
1459
|
}
|
1460
|
+
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
1387
1461
|
|
1462
|
+
/* keep a reference to this device */
|
1463
|
+
libusb_ref_device(transfer->dev_handle->dev);
|
1388
1464
|
out:
|
1389
1465
|
updated_fds = (itransfer->flags & USBI_TRANSFER_UPDATED_FDS);
|
1390
1466
|
usbi_mutex_unlock(&itransfer->lock);
|
@@ -1448,6 +1524,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
1448
1524
|
struct libusb_transfer *transfer =
|
1449
1525
|
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
1450
1526
|
struct libusb_context *ctx = TRANSFER_CTX(transfer);
|
1527
|
+
struct libusb_device_handle *handle = transfer->dev_handle;
|
1451
1528
|
uint8_t flags;
|
1452
1529
|
int r = 0;
|
1453
1530
|
|
@@ -1488,6 +1565,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
|
|
1488
1565
|
usbi_mutex_lock(&ctx->event_waiters_lock);
|
1489
1566
|
usbi_cond_broadcast(&ctx->event_waiters_cond);
|
1490
1567
|
usbi_mutex_unlock(&ctx->event_waiters_lock);
|
1568
|
+
libusb_unref_device(handle->dev);
|
1491
1569
|
return 0;
|
1492
1570
|
}
|
1493
1571
|
|
@@ -1531,14 +1609,15 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
|
|
1531
1609
|
int API_EXPORTED libusb_try_lock_events(libusb_context *ctx)
|
1532
1610
|
{
|
1533
1611
|
int r;
|
1612
|
+
unsigned int ru;
|
1534
1613
|
USBI_GET_CONTEXT(ctx);
|
1535
1614
|
|
1536
1615
|
/* is someone else waiting to modify poll fds? if so, don't let this thread
|
1537
1616
|
* start event handling */
|
1538
1617
|
usbi_mutex_lock(&ctx->pollfd_modify_lock);
|
1539
|
-
|
1618
|
+
ru = ctx->pollfd_modify;
|
1540
1619
|
usbi_mutex_unlock(&ctx->pollfd_modify_lock);
|
1541
|
-
if (
|
1620
|
+
if (ru) {
|
1542
1621
|
usbi_dbg("someone else is modifying poll fds");
|
1543
1622
|
return 1;
|
1544
1623
|
}
|
@@ -1621,7 +1700,7 @@ void API_EXPORTED libusb_unlock_events(libusb_context *ctx)
|
|
1621
1700
|
*/
|
1622
1701
|
int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
|
1623
1702
|
{
|
1624
|
-
int r;
|
1703
|
+
unsigned int r;
|
1625
1704
|
USBI_GET_CONTEXT(ctx);
|
1626
1705
|
|
1627
1706
|
/* is someone else waiting to modify poll fds? if so, don't let this thread
|
@@ -1649,7 +1728,7 @@ int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx)
|
|
1649
1728
|
*/
|
1650
1729
|
int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
|
1651
1730
|
{
|
1652
|
-
int r;
|
1731
|
+
unsigned int r;
|
1653
1732
|
USBI_GET_CONTEXT(ctx);
|
1654
1733
|
|
1655
1734
|
/* is someone else waiting to modify poll fds? if so, don't let this thread
|
@@ -1874,7 +1953,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|
1874
1953
|
}
|
1875
1954
|
usbi_mutex_unlock(&ctx->pollfds_lock);
|
1876
1955
|
|
1877
|
-
timeout_ms = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
|
1956
|
+
timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
|
1878
1957
|
|
1879
1958
|
/* round up to next millisecond */
|
1880
1959
|
if (tv->tv_usec % 1000)
|
@@ -1912,9 +1991,36 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|
1912
1991
|
}
|
1913
1992
|
}
|
1914
1993
|
|
1994
|
+
/* fd[1] is always the hotplug pipe */
|
1995
|
+
if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && fds[1].revents) {
|
1996
|
+
libusb_hotplug_message message;
|
1997
|
+
ssize_t ret;
|
1998
|
+
|
1999
|
+
usbi_dbg("caught a fish on the hotplug pipe");
|
2000
|
+
|
2001
|
+
/* read the message from the hotplug thread */
|
2002
|
+
ret = usbi_read(ctx->hotplug_pipe[0], &message, sizeof (message));
|
2003
|
+
if (ret != sizeof(message)) {
|
2004
|
+
usbi_err(ctx, "hotplug pipe read error %d != %u",
|
2005
|
+
ret, sizeof(message));
|
2006
|
+
r = LIBUSB_ERROR_OTHER;
|
2007
|
+
goto handled;
|
2008
|
+
}
|
2009
|
+
|
2010
|
+
usbi_hotplug_match(ctx, message.device, message.event);
|
2011
|
+
|
2012
|
+
/* the device left. dereference the device */
|
2013
|
+
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message.event)
|
2014
|
+
libusb_unref_device(message.device);
|
2015
|
+
|
2016
|
+
fds[1].revents = 0;
|
2017
|
+
if (1 == r--)
|
2018
|
+
goto handled;
|
2019
|
+
} /* else there shouldn't be anything on this pipe */
|
2020
|
+
|
1915
2021
|
#ifdef USBI_TIMERFD_AVAILABLE
|
1916
|
-
/* on timerfd configurations, fds[
|
1917
|
-
if (usbi_using_timerfd(ctx) && fds[
|
2022
|
+
/* on timerfd configurations, fds[2] is the timerfd */
|
2023
|
+
if (usbi_using_timerfd(ctx) && fds[2].revents) {
|
1918
2024
|
/* timerfd indicates that a timeout has expired */
|
1919
2025
|
int ret;
|
1920
2026
|
usbi_dbg("timerfd triggered");
|
@@ -1931,7 +2037,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
|
|
1931
2037
|
} else {
|
1932
2038
|
/* more events pending...
|
1933
2039
|
* prevent OS backend from trying to handle events on timerfd */
|
1934
|
-
fds[
|
2040
|
+
fds[2].revents = 0;
|
1935
2041
|
r--;
|
1936
2042
|
}
|
1937
2043
|
}
|
@@ -2406,8 +2512,9 @@ out:
|
|
2406
2512
|
#endif
|
2407
2513
|
}
|
2408
2514
|
|
2409
|
-
/* Backends call this from handle_events to report disconnection of a
|
2410
|
-
*
|
2515
|
+
/* Backends may call this from handle_events to report disconnection of a
|
2516
|
+
* device. This function ensures transfers get cancelled appropriately.
|
2517
|
+
* Callers of this function must hold the events_lock.
|
2411
2518
|
*/
|
2412
2519
|
void usbi_handle_disconnect(struct libusb_device_handle *handle)
|
2413
2520
|
{
|
@@ -2422,12 +2529,22 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle)
|
|
2422
2529
|
*
|
2423
2530
|
* this is a bit tricky because:
|
2424
2531
|
* 1. we can't do transfer completion while holding flying_transfers_lock
|
2532
|
+
* because the completion handler may try to re-submit the transfer
|
2425
2533
|
* 2. the transfers list can change underneath us - if we were to build a
|
2426
|
-
* list of transfers to complete (while holding
|
2534
|
+
* list of transfers to complete (while holding lock), the situation
|
2427
2535
|
* might be different by the time we come to free them
|
2428
2536
|
*
|
2429
2537
|
* so we resort to a loop-based approach as below
|
2430
|
-
*
|
2538
|
+
*
|
2539
|
+
* This is safe because transfers are only removed from the
|
2540
|
+
* flying_transfer list by usbi_handle_transfer_completion and
|
2541
|
+
* libusb_close, both of which hold the events_lock while doing so,
|
2542
|
+
* so usbi_handle_disconnect cannot be running at the same time.
|
2543
|
+
*
|
2544
|
+
* Note that libusb_submit_transfer also removes the transfer from
|
2545
|
+
* the flying_transfer list on submission failure, but it keeps the
|
2546
|
+
* flying_transfer list locked between addition and removal, so
|
2547
|
+
* usbi_handle_disconnect never sees such transfers.
|
2431
2548
|
*/
|
2432
2549
|
|
2433
2550
|
while (1) {
|
@@ -2443,6 +2560,9 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle)
|
|
2443
2560
|
if (!to_cancel)
|
2444
2561
|
break;
|
2445
2562
|
|
2563
|
+
usbi_dbg("cancelling transfer %p from disconnect",
|
2564
|
+
USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
|
2565
|
+
|
2446
2566
|
usbi_backend->clear_transfer_priv(to_cancel);
|
2447
2567
|
usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
|
2448
2568
|
}
|