usb 1.7.2 → 1.8.1-libusb.4

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 (188) hide show
  1. package/.gitmodules +1 -1
  2. package/Readme.md +2 -2
  3. package/binding.gyp +2 -2
  4. package/libusb/.private/pre-commit.sh +7 -1
  5. package/libusb/.travis.yml +49 -0
  6. package/libusb/AUTHORS +44 -3
  7. package/libusb/Brewfile +4 -0
  8. package/libusb/ChangeLog +74 -2
  9. package/libusb/README.md +32 -0
  10. package/libusb/TODO +1 -1
  11. package/libusb/Xcode/common.xcconfig +12 -0
  12. package/libusb/Xcode/config.h +25 -0
  13. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  14. package/libusb/android/README +4 -2
  15. package/libusb/android/config.h +75 -0
  16. package/libusb/appveyor.yml +41 -0
  17. package/libusb/appveyor_cygwin.bat +11 -0
  18. package/libusb/appveyor_minGW.bat +19 -0
  19. package/libusb/autogen.sh +1 -1
  20. package/libusb/bootstrap.sh +3 -16
  21. package/libusb/configure.ac +108 -80
  22. package/libusb/doc/doxygen.cfg.in +1785 -739
  23. package/libusb/examples/Makefile.am +1 -1
  24. package/libusb/examples/dpfp.c +3 -1
  25. package/libusb/examples/dpfp_threaded.c +23 -10
  26. package/libusb/examples/ezusb.c +3 -3
  27. package/libusb/examples/ezusb.h +2 -2
  28. package/libusb/examples/fxload.c +31 -9
  29. package/libusb/examples/hotplugtest.c +35 -7
  30. package/libusb/examples/listdevs.c +3 -1
  31. package/libusb/examples/sam3u_benchmark.c +3 -3
  32. package/libusb/examples/testlibusb.c +277 -0
  33. package/libusb/examples/xusb.c +40 -34
  34. package/libusb/libusb/Makefile.am +49 -23
  35. package/libusb/libusb/core.c +855 -457
  36. package/libusb/libusb/descriptor.c +72 -78
  37. package/libusb/libusb/hotplug.c +122 -76
  38. package/libusb/libusb/hotplug.h +42 -25
  39. package/libusb/libusb/io.c +625 -390
  40. package/libusb/libusb/libusb-1.0.def +12 -0
  41. package/libusb/libusb/libusb.h +218 -150
  42. package/libusb/libusb/libusbi.h +346 -176
  43. package/libusb/libusb/os/darwin_usb.c +604 -319
  44. package/libusb/libusb/os/darwin_usb.h +61 -20
  45. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  46. package/libusb/libusb/os/haiku_usb.h +113 -0
  47. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  48. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  49. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  50. package/libusb/libusb/os/linux_netlink.c +186 -146
  51. package/libusb/libusb/os/linux_udev.c +36 -14
  52. package/libusb/libusb/os/linux_usbfs.c +426 -225
  53. package/libusb/libusb/os/linux_usbfs.h +5 -3
  54. package/libusb/libusb/os/netbsd_usb.c +21 -77
  55. package/libusb/libusb/os/openbsd_usb.c +32 -115
  56. package/libusb/libusb/os/poll_posix.c +38 -5
  57. package/libusb/libusb/os/poll_posix.h +3 -0
  58. package/libusb/libusb/os/poll_windows.c +277 -626
  59. package/libusb/libusb/os/poll_windows.h +11 -44
  60. package/libusb/libusb/os/sunos_usb.c +1695 -0
  61. package/libusb/libusb/os/sunos_usb.h +80 -0
  62. package/libusb/libusb/os/threads_posix.c +24 -26
  63. package/libusb/libusb/os/threads_posix.h +73 -21
  64. package/libusb/libusb/os/threads_windows.c +71 -157
  65. package/libusb/libusb/os/threads_windows.h +68 -44
  66. package/libusb/libusb/os/wince_usb.c +276 -420
  67. package/libusb/libusb/os/wince_usb.h +23 -28
  68. package/libusb/libusb/os/windows_common.h +78 -58
  69. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  70. package/libusb/libusb/os/windows_nt_common.h +110 -0
  71. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  72. package/libusb/libusb/os/windows_usbdk.c +830 -0
  73. package/libusb/libusb/os/windows_usbdk.h +103 -0
  74. package/libusb/libusb/os/windows_winusb.c +4391 -0
  75. package/libusb/libusb/os/windows_winusb.h +783 -0
  76. package/libusb/libusb/strerror.c +41 -7
  77. package/libusb/libusb/sync.c +41 -13
  78. package/libusb/libusb/version.h +1 -1
  79. package/libusb/libusb/version_nano.h +1 -1
  80. package/libusb/libusb-1.0.pc.in +1 -1
  81. package/libusb/msvc/appveyor.bat +27 -0
  82. package/libusb/msvc/config.h +5 -4
  83. package/libusb/msvc/ddk_build.cmd +87 -43
  84. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  85. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  86. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  87. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  88. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  89. package/libusb/msvc/fxload_sources +1 -1
  90. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  91. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  92. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  93. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  94. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  95. package/libusb/msvc/getopt_sources +6 -2
  96. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  97. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  98. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  99. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  100. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  101. package/libusb/msvc/hotplugtest_sources +1 -1
  102. package/libusb/msvc/libusb_2005.sln +20 -20
  103. package/libusb/msvc/libusb_2010.sln +57 -46
  104. package/libusb/msvc/libusb_2012.sln +57 -46
  105. package/libusb/msvc/libusb_2013.sln +57 -50
  106. package/libusb/msvc/libusb_2015.sln +59 -52
  107. package/libusb/msvc/libusb_2017.sln +186 -0
  108. package/libusb/msvc/libusb_dll.dsp +2 -2
  109. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  110. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  111. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  112. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  113. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  114. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  115. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  116. package/libusb/msvc/libusb_sources +10 -5
  117. package/libusb/msvc/libusb_static.dsp +2 -2
  118. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  119. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  120. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  121. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  122. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  123. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  124. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  125. package/libusb/msvc/libusb_wince.sln +88 -88
  126. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  127. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  128. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  129. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  130. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  131. package/libusb/msvc/listdevs_sources +2 -1
  132. package/libusb/msvc/stress_2010.vcxproj +20 -101
  133. package/libusb/msvc/stress_2012.vcxproj +20 -104
  134. package/libusb/msvc/stress_2013.vcxproj +20 -104
  135. package/libusb/msvc/stress_2015.vcxproj +87 -0
  136. package/libusb/msvc/stress_2017.vcxproj +110 -0
  137. package/libusb/msvc/stress_sources +21 -0
  138. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  139. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  140. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  141. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  142. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  143. package/libusb/msvc/testlibusb_sources +20 -0
  144. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  145. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  146. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  147. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  148. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  149. package/libusb/msvc/xusb_sources +1 -1
  150. package/libusb/tests/stress.c +2 -2
  151. package/libusb/tests/testlib.c +0 -4
  152. package/libusb/travis-autogen.sh +39 -0
  153. package/libusb.gypi +13 -2
  154. package/package.json +20 -11
  155. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  156. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  157. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  158. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  159. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  160. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  161. package/prebuilds/linux-ia32/node.napi.node +0 -0
  162. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  163. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  164. package/prebuilds/win32-ia32/node.napi.node +0 -0
  165. package/prebuilds/win32-x64/node.napi.node +0 -0
  166. package/src/device.cc +1 -1
  167. package/usb.js +51 -5
  168. package/.github/workflows/prebuild.yml +0 -49
  169. package/libusb/INSTALL +0 -234
  170. package/libusb/README +0 -28
  171. package/libusb/libusb/os/windows_usb.c +0 -5347
  172. package/libusb/libusb/os/windows_usb.h +0 -971
  173. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  174. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  175. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  176. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  177. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  178. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  179. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  180. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  181. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  182. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  183. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  184. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  185. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  186. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  187. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  188. package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
@@ -34,16 +34,16 @@
34
34
  #include "hotplug.h"
35
35
 
36
36
  /**
37
- * @defgroup hotplug Device hotplug event notification
37
+ * @defgroup libusb_hotplug Device hotplug event notification
38
38
  * This page details how to use the libusb hotplug interface, where available.
39
39
  *
40
40
  * Be mindful that not all platforms currently implement hotplug notification and
41
41
  * that you should first call on \ref libusb_has_capability() with parameter
42
42
  * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available.
43
43
  *
44
- * \page hotplug Device hotplug event notification
44
+ * \page libusb_hotplug Device hotplug event notification
45
45
  *
46
- * \section intro Introduction
46
+ * \section hotplug_intro Introduction
47
47
  *
48
48
  * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support
49
49
  * for hotplug events on <b>some</b> platforms (you should test if your platform
@@ -55,7 +55,7 @@
55
55
  *
56
56
  * To receive hotplug notification you register a callback by calling
57
57
  * \ref libusb_hotplug_register_callback(). This function will optionally return
58
- * a handle that can be passed to \ref libusb_hotplug_deregister_callback().
58
+ * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback().
59
59
  *
60
60
  * A callback function must return an int (0 or 1) indicating whether the callback is
61
61
  * expecting additional events. Returning 0 will rearm the callback and 1 will cause
@@ -75,40 +75,47 @@
75
75
  *
76
76
  * Note: If you receive notification that a device has left and you have any
77
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.
78
+ * on each device handle to free up any remaining resources associated with the device.
79
79
  * Once a device has left any libusb_device_handle associated with the device
80
80
  * are invalid and will remain so even if the device comes back.
81
81
  *
82
82
  * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered
83
- * safe to call any libusb function that takes a libusb_device. On the other hand,
84
- * when handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
83
+ * safe to call any libusb function that takes a libusb_device. It also safe to
84
+ * open a device and submit asynchronous transfers. However, most other functions
85
+ * that take a libusb_device_handle are <b>not</b> safe to call. Examples of such
86
+ * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking
87
+ * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must
88
+ * be used outside of the context of the hotplug callback.
89
+ *
90
+ * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function
85
91
  * is libusb_get_device_descriptor().
86
92
  *
87
93
  * The following code provides an example of the usage of the hotplug interface:
88
94
  \code
89
95
  #include <stdio.h>
90
96
  #include <stdlib.h>
97
+ #include <time.h>
91
98
  #include <libusb.h>
92
99
 
93
100
  static int count = 0;
94
101
 
95
102
  int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
96
103
  libusb_hotplug_event event, void *user_data) {
97
- static libusb_device_handle *handle = NULL;
104
+ static libusb_device_handle *dev_handle = NULL;
98
105
  struct libusb_device_descriptor desc;
99
106
  int rc;
100
107
 
101
108
  (void)libusb_get_device_descriptor(dev, &desc);
102
109
 
103
110
  if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
104
- rc = libusb_open(dev, &handle);
111
+ rc = libusb_open(dev, &dev_handle);
105
112
  if (LIBUSB_SUCCESS != rc) {
106
113
  printf("Could not open USB device\n");
107
114
  }
108
115
  } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
109
- if (handle) {
110
- libusb_close(handle);
111
- handle = NULL;
116
+ if (dev_handle) {
117
+ libusb_close(dev_handle);
118
+ dev_handle = NULL;
112
119
  }
113
120
  } else {
114
121
  printf("Unhandled event %d\n", event);
@@ -119,7 +126,7 @@ int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
119
126
  }
120
127
 
121
128
  int main (void) {
122
- libusb_hotplug_callback_handle handle;
129
+ libusb_hotplug_callback_handle callback_handle;
123
130
  int rc;
124
131
 
125
132
  libusb_init(NULL);
@@ -127,7 +134,7 @@ int main (void) {
127
134
  rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
128
135
  LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005,
129
136
  LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
130
- &handle);
137
+ &callback_handle);
131
138
  if (LIBUSB_SUCCESS != rc) {
132
139
  printf("Error creating a hotplug callback\n");
133
140
  libusb_exit(NULL);
@@ -136,10 +143,10 @@ int main (void) {
136
143
 
137
144
  while (count < 2) {
138
145
  libusb_handle_events_completed(NULL, NULL);
139
- usleep(10000);
146
+ nanosleep(&(struct timespec){0, 10000000UL}, NULL);
140
147
  }
141
148
 
142
- libusb_hotplug_deregister_callback(NULL, handle);
149
+ libusb_hotplug_deregister_callback(NULL, callback_handle);
143
150
  libusb_exit(NULL);
144
151
 
145
152
  return 0;
@@ -147,36 +154,30 @@ int main (void) {
147
154
  \endcode
148
155
  */
149
156
 
150
- static int usbi_hotplug_match_cb (struct libusb_context *ctx,
157
+ static int usbi_hotplug_match_cb(struct libusb_context *ctx,
151
158
  struct libusb_device *dev, libusb_hotplug_event event,
152
159
  struct libusb_hotplug_callback *hotplug_cb)
153
160
  {
154
- /* Handle lazy deregistration of callback */
155
- if (hotplug_cb->needs_free) {
156
- /* Free callback */
157
- return 1;
158
- }
159
-
160
- if (!(hotplug_cb->events & event)) {
161
+ if (!(hotplug_cb->flags & event)) {
161
162
  return 0;
162
163
  }
163
164
 
164
- if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
165
+ if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
165
166
  hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
166
167
  return 0;
167
168
  }
168
169
 
169
- if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
170
+ if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
170
171
  hotplug_cb->product_id != dev->device_descriptor.idProduct) {
171
172
  return 0;
172
173
  }
173
174
 
174
- if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
175
+ if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) &&
175
176
  hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
176
177
  return 0;
177
178
  }
178
179
 
179
- return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
180
+ return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data);
180
181
  }
181
182
 
182
183
  void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
@@ -188,8 +189,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
188
189
  usbi_mutex_lock(&ctx->hotplug_cbs_lock);
189
190
 
190
191
  list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
192
+ if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
193
+ /* process deregistration in usbi_hotplug_deregister() */
194
+ continue;
195
+ }
196
+
191
197
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
192
- ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
198
+ ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb);
193
199
  usbi_mutex_lock(&ctx->hotplug_cbs_lock);
194
200
 
195
201
  if (ret) {
@@ -199,69 +205,102 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
199
205
  }
200
206
 
201
207
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
208
+ }
209
+
210
+ void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
211
+ libusb_hotplug_event event)
212
+ {
213
+ int pending_events;
214
+ struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
202
215
 
203
- /* the backend is expected to call the callback for each active transfer */
216
+ if (!message) {
217
+ usbi_err(ctx, "error allocating hotplug message");
218
+ return;
219
+ }
220
+
221
+ message->event = event;
222
+ message->device = dev;
223
+
224
+ /* Take the event data lock and add this message to the list.
225
+ * Only signal an event if there are no prior pending events. */
226
+ usbi_mutex_lock(&ctx->event_data_lock);
227
+ pending_events = usbi_pending_events(ctx);
228
+ list_add_tail(&message->list, &ctx->hotplug_msgs);
229
+ if (!pending_events)
230
+ usbi_signal_event(ctx);
231
+ usbi_mutex_unlock(&ctx->event_data_lock);
204
232
  }
205
233
 
206
234
  int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
207
235
  libusb_hotplug_event events, libusb_hotplug_flag flags,
208
236
  int vendor_id, int product_id, int dev_class,
209
237
  libusb_hotplug_callback_fn cb_fn, void *user_data,
210
- libusb_hotplug_callback_handle *handle)
238
+ libusb_hotplug_callback_handle *callback_handle)
211
239
  {
212
- libusb_hotplug_callback *new_callback;
213
- static int handle_id = 1;
214
-
215
- /* check for hotplug support */
216
- if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
217
- return LIBUSB_ERROR_NOT_SUPPORTED;
218
- }
240
+ struct libusb_hotplug_callback *new_callback;
219
241
 
220
242
  /* check for sane values */
221
- if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
243
+ if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) ||
244
+ (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) ||
245
+ (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
222
246
  (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
223
247
  (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
224
248
  !cb_fn) {
225
249
  return LIBUSB_ERROR_INVALID_PARAM;
226
250
  }
227
251
 
252
+ /* check for hotplug support */
253
+ if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
254
+ return LIBUSB_ERROR_NOT_SUPPORTED;
255
+ }
256
+
228
257
  USBI_GET_CONTEXT(ctx);
229
258
 
230
- new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
259
+ new_callback = calloc(1, sizeof(*new_callback));
231
260
  if (!new_callback) {
232
261
  return LIBUSB_ERROR_NO_MEM;
233
262
  }
234
263
 
235
- new_callback->ctx = ctx;
236
- new_callback->vendor_id = vendor_id;
237
- new_callback->product_id = product_id;
238
- new_callback->dev_class = dev_class;
239
- new_callback->flags = flags;
240
- new_callback->events = events;
264
+ new_callback->flags = (uint8_t)events;
265
+ if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
266
+ new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
267
+ new_callback->vendor_id = (uint16_t)vendor_id;
268
+ }
269
+ if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) {
270
+ new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID;
271
+ new_callback->product_id = (uint16_t)product_id;
272
+ }
273
+ if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) {
274
+ new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID;
275
+ new_callback->dev_class = (uint8_t)dev_class;
276
+ }
241
277
  new_callback->cb = cb_fn;
242
278
  new_callback->user_data = user_data;
243
- new_callback->needs_free = 0;
244
279
 
245
280
  usbi_mutex_lock(&ctx->hotplug_cbs_lock);
246
281
 
247
- /* protect the handle by the context hotplug lock. it doesn't matter if the same handle
248
- * is used for different contexts only that the handle is unique for this context */
249
- new_callback->handle = handle_id++;
282
+ /* protect the handle by the context hotplug lock */
283
+ new_callback->handle = ctx->next_hotplug_cb_handle++;
284
+
285
+ /* handle the unlikely case of overflow */
286
+ if (ctx->next_hotplug_cb_handle < 0)
287
+ ctx->next_hotplug_cb_handle = 1;
250
288
 
251
289
  list_add(&new_callback->list, &ctx->hotplug_cbs);
252
290
 
253
291
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
254
292
 
293
+ usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle);
255
294
 
256
- if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
257
- int i, len;
295
+ if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
296
+ ssize_t i, len;
258
297
  struct libusb_device **devs;
259
298
 
260
- len = (int) libusb_get_device_list(ctx, &devs);
299
+ len = libusb_get_device_list(ctx, &devs);
261
300
  if (len < 0) {
262
301
  libusb_hotplug_deregister_callback(ctx,
263
302
  new_callback->handle);
264
- return len;
303
+ return (int)len;
265
304
  }
266
305
 
267
306
  for (i = 0; i < len; i++) {
@@ -274,19 +313,17 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
274
313
  }
275
314
 
276
315
 
277
- if (handle) {
278
- *handle = new_callback->handle;
279
- }
316
+ if (callback_handle)
317
+ *callback_handle = new_callback->handle;
280
318
 
281
319
  return LIBUSB_SUCCESS;
282
320
  }
283
321
 
284
- void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
285
- libusb_hotplug_callback_handle handle)
322
+ void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx,
323
+ libusb_hotplug_callback_handle callback_handle)
286
324
  {
287
325
  struct libusb_hotplug_callback *hotplug_cb;
288
- libusb_hotplug_message message;
289
- ssize_t ret;
326
+ int deregistered = 0;
290
327
 
291
328
  /* check for hotplug support */
292
329
  if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
@@ -295,33 +332,42 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
295
332
 
296
333
  USBI_GET_CONTEXT(ctx);
297
334
 
335
+ usbi_dbg("deregister hotplug cb %d", callback_handle);
336
+
298
337
  usbi_mutex_lock(&ctx->hotplug_cbs_lock);
299
- list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
300
- struct libusb_hotplug_callback) {
301
- if (handle == hotplug_cb->handle) {
338
+ list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
339
+ if (callback_handle == hotplug_cb->handle) {
302
340
  /* Mark this callback for deregistration */
303
- hotplug_cb->needs_free = 1;
341
+ hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
342
+ deregistered = 1;
304
343
  }
305
344
  }
306
345
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
307
346
 
308
- /* wakeup handle_events to do the actual free */
309
- memset(&message, 0, sizeof(message));
310
- ret = usbi_write(ctx->hotplug_pipe[1], &message, sizeof(message));
311
- if (sizeof(message) != ret) {
312
- usbi_err(ctx, "error writing hotplug message");
347
+ if (deregistered) {
348
+ int pending_events;
349
+
350
+ usbi_mutex_lock(&ctx->event_data_lock);
351
+ pending_events = usbi_pending_events(ctx);
352
+ ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
353
+ if (!pending_events)
354
+ usbi_signal_event(ctx);
355
+ usbi_mutex_unlock(&ctx->event_data_lock);
313
356
  }
314
357
  }
315
358
 
316
- void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
359
+ void usbi_hotplug_deregister(struct libusb_context *ctx, int forced)
360
+ {
317
361
  struct libusb_hotplug_callback *hotplug_cb, *next;
318
362
 
319
363
  usbi_mutex_lock(&ctx->hotplug_cbs_lock);
320
- list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
321
- struct libusb_hotplug_callback) {
322
- list_del(&hotplug_cb->list);
323
- free(hotplug_cb);
364
+ list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
365
+ if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
366
+ usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
367
+ hotplug_cb->handle);
368
+ list_del(&hotplug_cb->list);
369
+ free(hotplug_cb);
370
+ }
324
371
  }
325
-
326
372
  usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
327
373
  }
@@ -19,12 +19,34 @@
19
19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
  */
21
21
 
22
- #if !defined(USBI_HOTPLUG_H)
22
+ #ifndef USBI_HOTPLUG_H
23
23
  #define USBI_HOTPLUG_H
24
24
 
25
- #ifndef LIBUSBI_H
26
25
  #include "libusbi.h"
27
- #endif
26
+
27
+ enum usbi_hotplug_flags {
28
+ /* This callback is interested in device arrivals */
29
+ USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
30
+
31
+ /* This callback is interested in device removals */
32
+ USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
33
+
34
+ /* IMPORTANT: The values for the below entries must start *after*
35
+ * the highest value of the above entries!!!
36
+ */
37
+
38
+ /* The vendor_id field is valid for matching */
39
+ USBI_HOTPLUG_VENDOR_ID_VALID = (1U << 3),
40
+
41
+ /* The product_id field is valid for matching */
42
+ USBI_HOTPLUG_PRODUCT_ID_VALID = (1U << 4),
43
+
44
+ /* The dev_class field is valid for matching */
45
+ USBI_HOTPLUG_DEV_CLASS_VALID = (1U << 5),
46
+
47
+ /* This callback has been unregistered and needs to be freed */
48
+ USBI_HOTPLUG_NEEDS_FREE = (1U << 6),
49
+ };
28
50
 
29
51
  /** \ingroup hotplug
30
52
  * The hotplug callback structure. The user populates this structure with
@@ -32,23 +54,17 @@
32
54
  * to receive notification of hotplug events.
33
55
  */
34
56
  struct libusb_hotplug_callback {
35
- /** Context this callback is associated with */
36
- struct libusb_context *ctx;
57
+ /** Flags that control how this callback behaves */
58
+ uint8_t flags;
37
59
 
38
- /** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
39
- int vendor_id;
60
+ /** Vendor ID to match (if flags says this is valid) */
61
+ uint16_t vendor_id;
40
62
 
41
- /** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
42
- int product_id;
63
+ /** Product ID to match (if flags says this is valid) */
64
+ uint16_t product_id;
43
65
 
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;
66
+ /** Device class to match (if flags says this is valid) */
67
+ uint8_t dev_class;
52
68
 
53
69
  /** Callback function to invoke for matching event/device */
54
70
  libusb_hotplug_callback_fn cb;
@@ -59,24 +75,25 @@ struct libusb_hotplug_callback {
59
75
  /** User data that will be passed to the callback function */
60
76
  void *user_data;
61
77
 
62
- /** Callback is marked for deletion */
63
- int needs_free;
64
-
65
78
  /** List this callback is registered in (ctx->hotplug_cbs) */
66
79
  struct list_head list;
67
80
  };
68
81
 
69
- typedef struct libusb_hotplug_callback libusb_hotplug_callback;
70
-
71
82
  struct libusb_hotplug_message {
83
+ /** The hotplug event that occurred */
72
84
  libusb_hotplug_event event;
85
+
86
+ /** The device for which this hotplug event occurred */
73
87
  struct libusb_device *device;
74
- };
75
88
 
76
- typedef struct libusb_hotplug_message libusb_hotplug_message;
89
+ /** List this message is contained in (ctx->hotplug_msgs) */
90
+ struct list_head list;
91
+ };
77
92
 
78
- void usbi_hotplug_deregister_all(struct libusb_context *ctx);
93
+ void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
79
94
  void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
80
95
  libusb_hotplug_event event);
96
+ void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
97
+ libusb_hotplug_event event);
81
98
 
82
99
  #endif