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.
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
  }