libusb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. 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 <config.h>
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
- * In accordance of the aim of being a lightweight library, libusbx does not
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
- * The first issue to discuss here is how your application can figure out
509
- * when libusbx has work to do. In fact, there are two naive options which
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 option is plainly not very nice, and will cause unnecessary
517
- * CPU wakeups leading to increased power usage and decreased battery life.
518
- * The second option is not very nice either, but may be the nicest option
519
- * available to you if the "proper" approach can not be applied to your
520
- * application (read on...).
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
- * The recommended option is to integrate libusbx with your application main
523
- * event loop. libusbx exposes a set of file descriptors which allow you to do
524
- * this. Your main loop is probably already calling poll() or select() or a
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
- * There is one final event handling complication. libusbx supports
532
- * asynchronous transfers which time out after a specified time period, and
533
- * this requires that libusbx is called into at or after the timeout so that
534
- * the timeout can be handled. So, in addition to considering libusbx's file
535
- * descriptors in your main event loop, you must also consider that libusbx
536
- * sometimes needs to be called into at fixed points in time even when there
537
- * is no file descriptor activity.
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
- * For the details on retrieving the set of file descriptors and determining
540
- * the next timeout, see the \ref poll "polling and timing" API documentation.
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. Exposing event sources
587
- * on Windows will require some further thought and design.
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 err_close_pipe;
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
- * returns 1 if the transfer has a timeout and it is the timeout next to
1155
- * expire */
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
- goto out;
1380
- r = usbi_backend->submit_transfer(itransfer);
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
- r = ctx->pollfd_modify;
1618
+ ru = ctx->pollfd_modify;
1540
1619
  usbi_mutex_unlock(&ctx->pollfd_modify_lock);
1541
- if (r) {
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[1] is the timerfd */
1917
- if (usbi_using_timerfd(ctx) && fds[1].revents) {
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[1].revents = 0;
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 device.
2410
- * The transfers get cancelled appropriately.
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 look), the situation
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
- * FIXME: is this still potentially racy?
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
  }