libusb 0.3.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|