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
@@ -1,7 +1,8 @@
1
1
  /* -*- Mode: C; indent-tabs-mode:nil -*- */
2
2
  /*
3
3
  * darwin backend for libusb 1.0
4
- * Copyright © 2008-2014 Nathan Hjelm <hjelmn@users.sourceforge.net>
4
+ * Copyright © 2008-2019 Nathan Hjelm <hjelmn@users.sourceforge.net>
5
+ * Copyright © 2019 Google LLC. All rights reserved.
5
6
  *
6
7
  * This library is free software; you can redistribute it and/or
7
8
  * modify it under the terms of the GNU Lesser General Public
@@ -19,6 +20,8 @@
19
20
  */
20
21
 
21
22
  #include "config.h"
23
+ #include <assert.h>
24
+ #include <time.h>
22
25
  #include <ctype.h>
23
26
  #include <errno.h>
24
27
  #include <pthread.h>
@@ -28,32 +31,63 @@
28
31
  #include <sys/types.h>
29
32
  #include <unistd.h>
30
33
  #include <fcntl.h>
31
- #include <libkern/OSAtomic.h>
34
+ #include <sys/sysctl.h>
32
35
 
33
36
  #include <mach/clock.h>
34
37
  #include <mach/clock_types.h>
35
38
  #include <mach/mach_host.h>
36
39
  #include <mach/mach_port.h>
37
40
 
41
+ /* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
42
+ * function. Its use is also conditionalized to only older deployment targets. */
43
+ #define OBJC_SILENCE_GC_DEPRECATIONS 1
44
+
38
45
  #include <AvailabilityMacros.h>
39
- #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
46
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
40
47
  #include <objc/objc-auto.h>
41
48
  #endif
42
49
 
50
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
51
+ /* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */
52
+ #include <stdatomic.h>
53
+ #define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y)
54
+
55
+ _Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
56
+ #else
57
+ /* use darwin atomics if the target is older than 10.12 */
58
+ #include <libkern/OSAtomic.h>
59
+
60
+ /* OSAtomicAdd32Barrier returns the new value */
61
+ #define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y)
62
+
63
+ static volatile int32_t initCount = 0;
64
+
65
+ #endif
66
+
67
+ /* On 10.12 and later, use newly available clock_*() functions */
68
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
69
+ #define OSX_USE_CLOCK_GETTIME 1
70
+ #else
71
+ #define OSX_USE_CLOCK_GETTIME 0
72
+ #endif
73
+
43
74
  #include "darwin_usb.h"
44
75
 
45
76
  /* async event thread */
46
77
  static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
47
78
  static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
48
79
 
80
+ #if !OSX_USE_CLOCK_GETTIME
49
81
  static clock_serv_t clock_realtime;
50
82
  static clock_serv_t clock_monotonic;
83
+ #endif
51
84
 
52
85
  static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
53
- static volatile int32_t initCount = 0;
86
+ static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
54
87
 
55
88
  static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
56
89
  static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
90
+ static const char *darwin_device_class = kIOUSBDeviceClassName;
57
91
 
58
92
  #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
59
93
 
@@ -66,11 +100,15 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
66
100
  static int darwin_reset_device(struct libusb_device_handle *dev_handle);
67
101
  static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
68
102
 
69
- static int darwin_scan_devices(struct libusb_context *ctx);
70
- static int process_new_device (struct libusb_context *ctx, io_service_t service);
103
+ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx);
104
+ static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
105
+ UInt64 old_session_id);
106
+
107
+ static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
108
+ UInt64 *old_session_id);
71
109
 
72
110
  #if defined(ENABLE_LOGGING)
73
- static const char *darwin_error_str (int result) {
111
+ static const char *darwin_error_str (IOReturn result) {
74
112
  static char string_buffer[50];
75
113
  switch (result) {
76
114
  case kIOReturnSuccess:
@@ -110,7 +148,7 @@ static const char *darwin_error_str (int result) {
110
148
  }
111
149
  #endif
112
150
 
113
- static int darwin_to_libusb (int result) {
151
+ static enum libusb_error darwin_to_libusb (IOReturn result) {
114
152
  switch (result) {
115
153
  case kIOReturnUnderrun:
116
154
  case kIOReturnSuccess:
@@ -142,7 +180,10 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
142
180
  if (0 == cached_dev->refcount) {
143
181
  list_del(&cached_dev->list);
144
182
 
145
- (*(cached_dev->device))->Release(cached_dev->device);
183
+ if (cached_dev->device) {
184
+ (*(cached_dev->device))->Release(cached_dev->device);
185
+ cached_dev->device = NULL;
186
+ }
146
187
  free (cached_dev);
147
188
  }
148
189
  }
@@ -157,14 +198,14 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
157
198
  /* current interface */
158
199
  struct darwin_interface *cInterface;
159
200
 
160
- int8_t i, iface;
201
+ uint8_t i, iface;
161
202
 
162
203
  usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep);
163
204
 
164
205
  for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
165
206
  cInterface = &priv->interfaces[iface];
166
207
 
167
- if (dev_handle->claimed_interfaces & (1 << iface)) {
208
+ if (dev_handle->claimed_interfaces & (1U << iface)) {
168
209
  for (i = 0 ; i < cInterface->num_endpoints ; i++) {
169
210
  if (cInterface->endpoint_addrs[i] == ep) {
170
211
  *pipep = i + 1;
@@ -176,7 +217,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
176
217
  *interface_out = cInterface;
177
218
 
178
219
  usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
179
- return 0;
220
+ return LIBUSB_SUCCESS;
180
221
  }
181
222
  }
182
223
  }
@@ -188,8 +229,8 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
188
229
  return LIBUSB_ERROR_NOT_FOUND;
189
230
  }
190
231
 
191
- static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
192
- CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
232
+ static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
233
+ CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class);
193
234
 
194
235
  if (!matchingDict)
195
236
  return kIOReturnError;
@@ -199,54 +240,91 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca
199
240
  &kCFTypeDictionaryKeyCallBacks,
200
241
  &kCFTypeDictionaryValueCallBacks);
201
242
 
202
- if (propertyMatchDict) {
203
- /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this
204
- internally (CFNumberType of locationID is 3) */
205
- CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
243
+ /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this
244
+ internally (CFNumberType of locationID is kCFNumberSInt32Type) */
245
+ CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
206
246
 
247
+ if (propertyMatchDict && locationCF) {
207
248
  CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
208
- /* release our reference to the CFNumber (CFDictionarySetValue retains it) */
209
- CFRelease (locationCF);
210
-
211
249
  CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
212
- /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */
213
- CFRelease (propertyMatchDict);
214
250
  }
215
251
  /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */
252
+
253
+ /* release our references as per the Create Rule */
254
+ if (propertyMatchDict)
255
+ CFRelease (propertyMatchDict);
256
+ if (locationCF)
257
+ CFRelease (locationCF);
216
258
  }
217
259
 
218
260
  return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
219
261
  }
220
262
 
221
263
  /* Returns 1 on success, 0 on failure. */
222
- static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
264
+ static bool get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
223
265
  CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
224
- int ret = 0;
266
+ Boolean success = 0;
225
267
 
226
268
  if (cfNumber) {
227
269
  if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) {
228
- ret = CFNumberGetValue(cfNumber, type, p);
270
+ success = CFNumberGetValue(cfNumber, type, p);
229
271
  }
230
272
 
231
273
  CFRelease (cfNumber);
232
274
  }
233
275
 
234
- return ret;
276
+ return (success != 0);
277
+ }
278
+
279
+ /* Returns 1 on success, 0 on failure. */
280
+ static bool get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) {
281
+ CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
282
+ bool success = false;
283
+
284
+ if (cfData) {
285
+ if (CFGetTypeID (cfData) == CFDataGetTypeID ()) {
286
+ CFIndex length = CFDataGetLength (cfData);
287
+ if (length < size) {
288
+ size = length;
289
+ }
290
+
291
+ CFDataGetBytes (cfData, CFRangeMake(0, size), p);
292
+ success = true;
293
+ }
294
+
295
+ CFRelease (cfData);
296
+ }
297
+
298
+ return success;
235
299
  }
236
300
 
237
301
  static usb_device_t **darwin_device_from_service (io_service_t service)
238
302
  {
239
303
  io_cf_plugin_ref_t *plugInInterface = NULL;
240
304
  usb_device_t **device;
241
- kern_return_t result;
305
+ IOReturn kresult;
242
306
  SInt32 score;
307
+ const int max_retries = 5;
308
+
309
+ /* The IOCreatePlugInInterfaceForService function might consistently return
310
+ an "out of resources" error with certain USB devices the first time we run
311
+ it. The reason is still unclear, but retrying fixes the problem */
312
+ for (int count = 0; count < max_retries; count++) {
313
+ kresult = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
314
+ kIOCFPlugInInterfaceID, &plugInInterface,
315
+ &score);
316
+ if (kIOReturnSuccess == kresult && plugInInterface) {
317
+ break;
318
+ }
243
319
 
244
- result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
245
- kIOCFPlugInInterfaceID, &plugInInterface,
246
- &score);
320
+ usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));
247
321
 
248
- if (kIOReturnSuccess != result || !plugInInterface) {
249
- usbi_dbg ("could not set up plugin for service: %s\n", darwin_error_str (result));
322
+ /* sleep for a little while before trying again */
323
+ nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
324
+ }
325
+
326
+ if (kIOReturnSuccess != kresult || !plugInInterface) {
327
+ usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
250
328
  return NULL;
251
329
  }
252
330
 
@@ -259,15 +337,29 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
259
337
  }
260
338
 
261
339
  static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
340
+ UNUSED(ptr);
341
+ struct darwin_cached_device *cached_device;
342
+ UInt64 old_session_id;
262
343
  struct libusb_context *ctx;
263
344
  io_service_t service;
345
+ int ret;
264
346
 
265
347
  usbi_mutex_lock(&active_contexts_lock);
266
348
 
267
349
  while ((service = IOIteratorNext(add_devices))) {
350
+ ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
351
+ if (ret < 0 || !cached_device->can_enumerate) {
352
+ continue;
353
+ }
354
+
268
355
  /* add this device to each active context's device list */
269
356
  list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
270
- process_new_device (ctx, service);;
357
+ process_new_device (ctx, cached_device, old_session_id);
358
+ }
359
+
360
+ if (cached_device->in_reenumerate) {
361
+ usbi_dbg ("cached device in reset state. reset complete...");
362
+ cached_device->in_reenumerate = false;
271
363
  }
272
364
 
273
365
  IOObjectRelease(service);
@@ -277,8 +369,10 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
277
369
  }
278
370
 
279
371
  static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
372
+ UNUSED(ptr);
280
373
  struct libusb_device *dev = NULL;
281
374
  struct libusb_context *ctx;
375
+ struct darwin_cached_device *old_device;
282
376
 
283
377
  io_service_t device;
284
378
  UInt64 session;
@@ -287,12 +381,44 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
287
381
  usbi_mutex_lock(&active_contexts_lock);
288
382
 
289
383
  while ((device = IOIteratorNext (rem_devices)) != 0) {
384
+ bool is_reenumerating = false;
385
+
290
386
  /* get the location from the i/o registry */
291
387
  ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
292
388
  IOObjectRelease (device);
293
389
  if (!ret)
294
390
  continue;
295
391
 
392
+ /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
393
+ otherwise no cached device will ever get freed */
394
+ usbi_mutex_lock(&darwin_cached_devices_lock);
395
+ list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
396
+ if (old_device->session == session) {
397
+ if (old_device->in_reenumerate) {
398
+ /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
399
+ * will deref if needed. */
400
+ usbi_dbg ("detected device detatched due to re-enumeration");
401
+
402
+ /* the device object is no longer usable so go ahead and release it */
403
+ if (old_device->device) {
404
+ (*(old_device->device))->Release(old_device->device);
405
+ old_device->device = NULL;
406
+ }
407
+
408
+ is_reenumerating = true;
409
+ } else {
410
+ darwin_deref_cached_device (old_device);
411
+ }
412
+
413
+ break;
414
+ }
415
+ }
416
+
417
+ usbi_mutex_unlock(&darwin_cached_devices_lock);
418
+ if (is_reenumerating) {
419
+ continue;
420
+ }
421
+
296
422
  list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
297
423
  usbi_dbg ("notifying context %p of device disconnect", ctx);
298
424
 
@@ -311,11 +437,11 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
311
437
 
312
438
  static void darwin_hotplug_poll (void)
313
439
  {
314
- /* not sure if 5 seconds will be too long/short but it should work ok */
315
- mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0};
440
+ /* not sure if 1 ms will be too long/short but it should work ok */
441
+ mach_timespec_t timeout = {.tv_sec = 0, .tv_nsec = 1000000ul};
316
442
 
317
- /* since a kernel thread may nodify the IOInterators used for
318
- * hotplug notidication we can't just clear the iterators.
443
+ /* since a kernel thread may notify the IOIterators used for
444
+ * hotplug notification we can't just clear the iterators.
319
445
  * instead just wait until all IOService providers are quiet */
320
446
  (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout);
321
447
  }
@@ -332,19 +458,24 @@ static void *darwin_event_thread_main (void *arg0) {
332
458
  struct libusb_context *ctx = (struct libusb_context *)arg0;
333
459
  CFRunLoopRef runloop;
334
460
 
461
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
335
462
  /* Set this thread's name, so it can be seen in the debugger
336
463
  and crash reports. */
337
- #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
338
464
  pthread_setname_np ("org.libusb.device-hotplug");
465
+ #endif
339
466
 
467
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
340
468
  /* Tell the Objective-C garbage collector about this thread.
341
469
  This is required because, unlike NSThreads, pthreads are
342
470
  not automatically registered. Although we don't use
343
- Objective-C, we use CoreFoundation, which does. */
471
+ Objective-C, we use CoreFoundation, which does.
472
+ Garbage collection support was entirely removed in 10.12,
473
+ so don't bother there. */
344
474
  objc_registerThreadWithCollector();
345
475
  #endif
346
476
 
347
477
  /* hotplug (device arrival/removal) sources */
478
+ CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
348
479
  CFRunLoopSourceRef libusb_notification_cfsource;
349
480
  io_notification_port_t libusb_notification_port;
350
481
  io_iterator_t libusb_rem_device_iterator;
@@ -355,6 +486,13 @@ static void *darwin_event_thread_main (void *arg0) {
355
486
  runloop = CFRunLoopGetCurrent ();
356
487
  CFRetain (runloop);
357
488
 
489
+ /* add the shutdown cfsource to the run loop */
490
+ memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
491
+ libusb_shutdown_cfsourcectx.info = runloop;
492
+ libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
493
+ libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
494
+ CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
495
+
358
496
  /* add the notification port to the run loop */
359
497
  libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault);
360
498
  libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
@@ -362,7 +500,7 @@ static void *darwin_event_thread_main (void *arg0) {
362
500
 
363
501
  /* create notifications for removed devices */
364
502
  kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification,
365
- IOServiceMatching(kIOUSBDeviceClassName),
503
+ IOServiceMatching(darwin_device_class),
366
504
  darwin_devices_detached,
367
505
  ctx, &libusb_rem_device_iterator);
368
506
 
@@ -374,7 +512,7 @@ static void *darwin_event_thread_main (void *arg0) {
374
512
 
375
513
  /* create notifications for attached devices */
376
514
  kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification,
377
- IOServiceMatching(kIOUSBDeviceClassName),
515
+ IOServiceMatching(darwin_device_class),
378
516
  darwin_devices_attached,
379
517
  ctx, &libusb_add_device_iterator);
380
518
 
@@ -404,6 +542,9 @@ static void *darwin_event_thread_main (void *arg0) {
404
542
  /* remove the notification cfsource */
405
543
  CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
406
544
 
545
+ /* remove the shutdown cfsource */
546
+ CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
547
+
407
548
  /* delete notification port */
408
549
  IONotificationPortDestroy (libusb_notification_port);
409
550
 
@@ -411,8 +552,10 @@ static void *darwin_event_thread_main (void *arg0) {
411
552
  IOObjectRelease (libusb_rem_device_iterator);
412
553
  IOObjectRelease (libusb_add_device_iterator);
413
554
 
555
+ CFRelease (libusb_darwin_acfls);
414
556
  CFRelease (runloop);
415
557
 
558
+ libusb_darwin_acfls = NULL;
416
559
  libusb_darwin_acfl = NULL;
417
560
 
418
561
  pthread_exit (NULL);
@@ -430,7 +573,6 @@ static void __attribute__((destructor)) _darwin_finalize(void) {
430
573
  }
431
574
 
432
575
  static int darwin_init(struct libusb_context *ctx) {
433
- host_name_port_t host_self;
434
576
  int rc;
435
577
 
436
578
  rc = darwin_scan_devices (ctx);
@@ -438,13 +580,16 @@ static int darwin_init(struct libusb_context *ctx) {
438
580
  return rc;
439
581
  }
440
582
 
441
- if (OSAtomicIncrement32Barrier(&initCount) == 1) {
442
- /* create the clocks that will be used */
583
+ if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) {
584
+ #if !OSX_USE_CLOCK_GETTIME
585
+ /* create the clocks that will be used if clock_gettime() is not available */
586
+ host_name_port_t host_self;
443
587
 
444
588
  host_self = mach_host_self();
445
589
  host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
446
590
  host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
447
591
  mach_port_deallocate(mach_task_self(), host_self);
592
+ #endif
448
593
 
449
594
  pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
450
595
 
@@ -457,13 +602,17 @@ static int darwin_init(struct libusb_context *ctx) {
457
602
  return rc;
458
603
  }
459
604
 
460
- static void darwin_exit (void) {
461
- if (OSAtomicDecrement32Barrier(&initCount) == 0) {
605
+ static void darwin_exit (struct libusb_context *ctx) {
606
+ UNUSED(ctx);
607
+ if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
608
+ #if !OSX_USE_CLOCK_GETTIME
462
609
  mach_port_deallocate(mach_task_self(), clock_realtime);
463
610
  mach_port_deallocate(mach_task_self(), clock_monotonic);
611
+ #endif
464
612
 
465
613
  /* stop the event runloop and wait for the thread to terminate. */
466
- CFRunLoopStop (libusb_darwin_acfl);
614
+ CFRunLoopSourceSignal(libusb_darwin_acfls);
615
+ CFRunLoopWakeUp (libusb_darwin_acfl);
467
616
  pthread_join (libusb_darwin_at, NULL);
468
617
  }
469
618
  }
@@ -476,7 +625,7 @@ static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char
476
625
 
477
626
  *host_endian = 0;
478
627
 
479
- return 0;
628
+ return LIBUSB_SUCCESS;
480
629
  }
481
630
 
482
631
  static int get_configuration_index (struct libusb_device *dev, int config_value) {
@@ -512,7 +661,8 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign
512
661
  if (config_index < 0)
513
662
  return config_index;
514
663
 
515
- return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian);
664
+ assert(config_index >= 0 && config_index <= UINT8_MAX);
665
+ return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len, host_endian);
516
666
  }
517
667
 
518
668
  static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) {
@@ -544,12 +694,12 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
544
694
  }
545
695
 
546
696
  /* check whether the os has configured the device */
547
- static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
697
+ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
548
698
  usb_device_t **darwin_device = dev->device;
549
699
 
550
700
  IOUSBConfigurationDescriptorPtr configDesc;
551
701
  IOUSBFindInterfaceRequest request;
552
- kern_return_t kresult;
702
+ IOReturn kresult;
553
703
  io_iterator_t interface_iterator;
554
704
  io_service_t firstInterface;
555
705
 
@@ -558,6 +708,14 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
558
708
  return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */
559
709
  }
560
710
 
711
+ /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
712
+ not usable anyway */
713
+ if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
714
+ usbi_dbg ("ignoring configuration on root hub simulation");
715
+ dev->active_config = 0;
716
+ return LIBUSB_SUCCESS;
717
+ }
718
+
561
719
  /* find the first configuration */
562
720
  kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc);
563
721
  dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
@@ -573,7 +731,7 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
573
731
  request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
574
732
 
575
733
  kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
576
- if (kresult)
734
+ if (kresult != kIOReturnSuccess)
577
735
  return darwin_to_libusb (kresult);
578
736
 
579
737
  /* iterate once */
@@ -598,20 +756,22 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin
598
756
 
599
757
  usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
600
758
 
601
- return 0;
759
+ return LIBUSB_SUCCESS;
602
760
  }
603
761
 
604
- static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
762
+ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
605
763
  IOUSBDevRequestTO req;
606
764
 
765
+ assert(buffer_size <= UINT16_MAX);
766
+
607
767
  memset (buffer, 0, buffer_size);
608
768
 
609
769
  /* Set up request for descriptor/ */
610
770
  req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
611
771
  req.bRequest = kUSBRqGetDescriptor;
612
- req.wValue = desc << 8;
772
+ req.wValue = (UInt16)(desc << 8);
613
773
  req.wIndex = desc_index;
614
- req.wLength = buffer_size;
774
+ req.wLength = (UInt16)buffer_size;
615
775
  req.pData = buffer;
616
776
  req.noDataTimeout = 20;
617
777
  req.completionTimeout = 100;
@@ -619,12 +779,13 @@ static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 d
619
779
  return (*device)->DeviceRequestTO (device, &req);
620
780
  }
621
781
 
622
- static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
782
+ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_device *dev) {
623
783
  usb_device_t **device = dev->device;
624
- int retries = 1, delay = 30000;
784
+ int retries = 1;
785
+ long delay = 30000; // microseconds
625
786
  int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
626
787
  int is_open = 0;
627
- int ret = 0, ret2;
788
+ IOReturn ret = 0, ret2;
628
789
  UInt8 bDeviceClass;
629
790
  UInt16 idProduct, idVendor;
630
791
 
@@ -677,7 +838,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
677
838
  (void)(*device)->GetUSBDeviceInformation (device, &info);
678
839
 
679
840
  /* note that the device was suspended */
680
- if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
841
+ if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
681
842
  try_unsuspend = 1;
682
843
  #endif
683
844
 
@@ -696,9 +857,9 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
696
857
  }
697
858
 
698
859
  if (kIOReturnSuccess != ret) {
699
- usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000);
860
+ usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
700
861
  /* sleep for a little while before trying again */
701
- usleep (delay);
862
+ nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
702
863
  }
703
864
  } while (kIOReturnSuccess != ret && retries--);
704
865
 
@@ -715,7 +876,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
715
876
  usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
716
877
  idVendor, idProduct, darwin_error_str (ret), ret);
717
878
  else
718
- usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
879
+ usbi_warn (NULL, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
719
880
  idVendor, idProduct, darwin_error_str (ret), ret);
720
881
  return darwin_to_libusb (ret);
721
882
  }
@@ -723,7 +884,7 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
723
884
  /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */
724
885
  if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) {
725
886
  /* not a valid device */
726
- usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
887
+ usbi_warn (NULL, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
727
888
  idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
728
889
  return LIBUSB_ERROR_NO_DEVICE;
729
890
  }
@@ -748,35 +909,80 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct da
748
909
  return LIBUSB_SUCCESS;
749
910
  }
750
911
 
751
- static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
752
- struct darwin_cached_device **cached_out) {
912
+ /* Returns 1 on success, 0 on failure. */
913
+ static bool get_device_port (io_service_t service, UInt8 *port) {
914
+ IOReturn kresult;
915
+ io_service_t parent;
916
+ bool ret = false;
917
+
918
+ if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) {
919
+ return true;
920
+ }
921
+
922
+ kresult = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent);
923
+ if (kIOReturnSuccess == kresult) {
924
+ ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port);
925
+ IOObjectRelease (parent);
926
+ }
927
+
928
+ return ret;
929
+ }
930
+
931
+ /* Returns 1 on success, 0 on failure. */
932
+ static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
933
+ IOReturn kresult;
934
+ io_service_t parent;
935
+
936
+ /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
937
+ parent = service;
938
+ while((kresult = IORegistryEntryGetParentEntry (parent, kIOUSBPlane, &parent)) == kIOReturnSuccess) {
939
+ if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
940
+ /* Success */
941
+ return true;
942
+ }
943
+ }
944
+
945
+ /* We ran out of parents */
946
+ return false;
947
+ }
948
+
949
+ static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
950
+ UInt64 *old_session_id) {
753
951
  struct darwin_cached_device *new_device;
754
952
  UInt64 sessionID = 0, parent_sessionID = 0;
755
- int ret = LIBUSB_SUCCESS;
953
+ UInt32 locationID = 0;
954
+ enum libusb_error ret = LIBUSB_SUCCESS;
756
955
  usb_device_t **device;
757
- io_service_t parent;
758
- kern_return_t result;
759
956
  UInt8 port = 0;
760
957
 
958
+ /* assuming sessionID != 0 normally (never seen it be 0) */
959
+ *old_session_id = 0;
960
+ *cached_out = NULL;
961
+
761
962
  /* get some info from the io registry */
762
963
  (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
763
- (void) get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, &port);
964
+ (void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
965
+ if (!get_device_port (service, &port)) {
966
+ usbi_dbg("could not get connected port number");
967
+ }
764
968
 
765
969
  usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
766
970
 
767
- result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent);
768
-
769
- if (kIOReturnSuccess == result) {
770
- (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID);
771
- IOObjectRelease(parent);
971
+ if (get_device_parent_sessionID(service, &parent_sessionID)) {
972
+ usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
772
973
  }
773
974
 
774
975
  usbi_mutex_lock(&darwin_cached_devices_lock);
775
976
  do {
776
- *cached_out = NULL;
777
-
778
977
  list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
779
- usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session);
978
+ usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
979
+ sessionID, locationID, new_device->session, new_device->location);
980
+ if (new_device->location == locationID && new_device->in_reenumerate) {
981
+ usbi_dbg ("found cached device with matching location that is being re-enumerated");
982
+ *old_session_id = new_device->session;
983
+ break;
984
+ }
985
+
780
986
  if (new_device->session == sessionID) {
781
987
  usbi_dbg("using cached device for device");
782
988
  *cached_out = new_device;
@@ -795,28 +1001,35 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
795
1001
  break;
796
1002
  }
797
1003
 
798
- new_device = calloc (1, sizeof (*new_device));
799
- if (!new_device) {
800
- ret = LIBUSB_ERROR_NO_MEM;
801
- break;
802
- }
1004
+ if (!(*old_session_id)) {
1005
+ new_device = calloc (1, sizeof (*new_device));
1006
+ if (!new_device) {
1007
+ ret = LIBUSB_ERROR_NO_MEM;
1008
+ break;
1009
+ }
803
1010
 
804
- /* add this device to the cached device list */
805
- list_add(&new_device->list, &darwin_cached_devices);
1011
+ /* add this device to the cached device list */
1012
+ list_add(&new_device->list, &darwin_cached_devices);
806
1013
 
807
- (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
1014
+ (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
808
1015
 
809
- /* keep a reference to this device */
810
- darwin_ref_cached_device(new_device);
1016
+ /* keep a reference to this device */
1017
+ darwin_ref_cached_device(new_device);
1018
+
1019
+ (*device)->GetLocationID (device, &new_device->location);
1020
+ new_device->port = port;
1021
+ new_device->parent_session = parent_sessionID;
1022
+ }
1023
+
1024
+ /* keep track of devices regardless of if we successfully enumerate them to
1025
+ prevent them from being enumerated multiple times */
1026
+ *cached_out = new_device;
811
1027
 
812
- new_device->device = device;
813
1028
  new_device->session = sessionID;
814
- (*device)->GetLocationID (device, &new_device->location);
815
- new_device->port = port;
816
- new_device->parent_session = parent_sessionID;
1029
+ new_device->device = device;
817
1030
 
818
1031
  /* cache the device descriptor */
819
- ret = darwin_cache_device_descriptor(ctx, new_device);
1032
+ ret = darwin_cache_device_descriptor(new_device);
820
1033
  if (ret)
821
1034
  break;
822
1035
 
@@ -829,55 +1042,56 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
829
1042
 
830
1043
  usbi_mutex_unlock(&darwin_cached_devices_lock);
831
1044
 
832
- /* keep track of devices regardless of if we successfully enumerate them to
833
- prevent them from being enumerated multiple times */
834
-
835
- *cached_out = new_device;
836
-
837
1045
  return ret;
838
1046
  }
839
1047
 
840
- static int process_new_device (struct libusb_context *ctx, io_service_t service) {
1048
+ static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
1049
+ UInt64 old_session_id) {
841
1050
  struct darwin_device_priv *priv;
842
1051
  struct libusb_device *dev = NULL;
843
- struct darwin_cached_device *cached_device;
844
1052
  UInt8 devSpeed;
845
- int ret = 0;
1053
+ enum libusb_error ret = LIBUSB_SUCCESS;
846
1054
 
847
1055
  do {
848
- ret = darwin_get_cached_device (ctx, service, &cached_device);
849
-
850
- if (ret < 0 || !cached_device->can_enumerate) {
851
- return ret;
852
- }
853
-
854
1056
  /* check current active configuration (and cache the first configuration value--
855
1057
  which may be used by claim_interface) */
856
1058
  ret = darwin_check_configuration (ctx, cached_device);
857
1059
  if (ret)
858
1060
  break;
859
1061
 
860
- usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
861
- ctx, cached_device->session);
1062
+ if (0 != old_session_id) {
1063
+ usbi_dbg ("re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
1064
+ ctx, old_session_id, cached_device->session);
1065
+ /* save the libusb device before the session id is updated */
1066
+ dev = usbi_get_device_by_session_id (ctx, (unsigned long) old_session_id);
1067
+ }
862
1068
 
863
- dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
864
1069
  if (!dev) {
865
- return LIBUSB_ERROR_NO_MEM;
866
- }
1070
+ usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
1071
+ ctx, cached_device->session);
1072
+
1073
+ dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
1074
+ if (!dev) {
1075
+ return LIBUSB_ERROR_NO_MEM;
1076
+ }
867
1077
 
868
- priv = (struct darwin_device_priv *)dev->os_priv;
1078
+ priv = (struct darwin_device_priv *)dev->os_priv;
869
1079
 
870
- priv->dev = cached_device;
871
- darwin_ref_cached_device (priv->dev);
1080
+ priv->dev = cached_device;
1081
+ darwin_ref_cached_device (priv->dev);
1082
+ dev->port_number = cached_device->port;
1083
+ dev->bus_number = cached_device->location >> 24;
1084
+ assert(cached_device->address <= UINT8_MAX);
1085
+ dev->device_address = (uint8_t)cached_device->address;
1086
+ } else {
1087
+ priv = (struct darwin_device_priv *)dev->os_priv;
1088
+ }
872
1089
 
873
1090
  if (cached_device->parent_session > 0) {
874
1091
  dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
875
1092
  } else {
876
1093
  dev->parent_dev = NULL;
877
1094
  }
878
- dev->port_number = cached_device->port;
879
- dev->bus_number = cached_device->location >> 24;
880
- dev->device_address = cached_device->address;
881
1095
 
882
1096
  (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
883
1097
 
@@ -885,8 +1099,11 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
885
1099
  case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
886
1100
  case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
887
1101
  case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
888
- #if DeviceVersion >= 500
1102
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
889
1103
  case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
1104
+ #endif
1105
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
1106
+ case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
890
1107
  #endif
891
1108
  default:
892
1109
  usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
@@ -898,9 +1115,10 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
898
1115
 
899
1116
  usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
900
1117
  dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
1118
+
901
1119
  } while (0);
902
1120
 
903
- if (0 == ret) {
1121
+ if (!cached_device->in_reenumerate && 0 == ret) {
904
1122
  usbi_connect_device (dev);
905
1123
  } else {
906
1124
  libusb_unref_device (dev);
@@ -909,24 +1127,32 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
909
1127
  return ret;
910
1128
  }
911
1129
 
912
- static int darwin_scan_devices(struct libusb_context *ctx) {
1130
+ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
1131
+ struct darwin_cached_device *cached_device;
1132
+ UInt64 old_session_id;
913
1133
  io_iterator_t deviceIterator;
914
1134
  io_service_t service;
915
- kern_return_t kresult;
1135
+ IOReturn kresult;
1136
+ int ret;
916
1137
 
917
1138
  kresult = usb_setup_device_iterator (&deviceIterator, 0);
918
1139
  if (kresult != kIOReturnSuccess)
919
1140
  return darwin_to_libusb (kresult);
920
1141
 
921
1142
  while ((service = IOIteratorNext (deviceIterator))) {
922
- (void) process_new_device (ctx, service);
1143
+ ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
1144
+ if (ret < 0 || !cached_device->can_enumerate) {
1145
+ continue;
1146
+ }
1147
+
1148
+ (void) process_new_device (ctx, cached_device, old_session_id);
923
1149
 
924
1150
  IOObjectRelease(service);
925
1151
  }
926
1152
 
927
1153
  IOObjectRelease(deviceIterator);
928
1154
 
929
- return 0;
1155
+ return LIBUSB_SUCCESS;
930
1156
  }
931
1157
 
932
1158
  static int darwin_open (struct libusb_device_handle *dev_handle) {
@@ -945,9 +1171,9 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
945
1171
  }
946
1172
 
947
1173
  /* it is possible to perform some actions on a device that is not open so do not return an error */
948
- priv->is_open = 0;
1174
+ priv->is_open = false;
949
1175
  } else {
950
- priv->is_open = 1;
1176
+ priv->is_open = true;
951
1177
  }
952
1178
 
953
1179
  /* create async event source */
@@ -959,7 +1185,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
959
1185
  (*(dpriv->device))->USBDeviceClose (dpriv->device);
960
1186
  }
961
1187
 
962
- priv->is_open = 0;
1188
+ priv->is_open = false;
963
1189
 
964
1190
  return darwin_to_libusb (kresult);
965
1191
  }
@@ -973,14 +1199,6 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
973
1199
  /* device opened successfully */
974
1200
  dpriv->open_count++;
975
1201
 
976
- /* create a file descriptor for notifications */
977
- pipe (priv->fds);
978
-
979
- /* set the pipe to be non-blocking */
980
- fcntl (priv->fds[1], F_SETFD, O_NONBLOCK);
981
-
982
- usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN);
983
-
984
1202
  usbi_dbg ("device open for access");
985
1203
 
986
1204
  return 0;
@@ -994,7 +1212,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
994
1212
 
995
1213
  if (dpriv->open_count == 0) {
996
1214
  /* something is probably very wrong if this is the case */
997
- usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n");
1215
+ usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!");
998
1216
  return;
999
1217
  }
1000
1218
 
@@ -1002,7 +1220,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
1002
1220
 
1003
1221
  /* make sure all interfaces are released */
1004
1222
  for (i = 0 ; i < USB_MAXINTERFACES ; i++)
1005
- if (dev_handle->claimed_interfaces & (1 << i))
1223
+ if (dev_handle->claimed_interfaces & (1U << i))
1006
1224
  libusb_release_interface (dev_handle, i);
1007
1225
 
1008
1226
  if (0 == dpriv->open_count) {
@@ -1017,20 +1235,13 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
1017
1235
  if (priv->is_open) {
1018
1236
  /* close the device */
1019
1237
  kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
1020
- if (kresult) {
1238
+ if (kresult != kIOReturnSuccess) {
1021
1239
  /* Log the fact that we had a problem closing the file, however failing a
1022
1240
  * close isn't really an error, so return success anyway */
1023
1241
  usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult));
1024
1242
  }
1025
1243
  }
1026
1244
  }
1027
-
1028
- /* file descriptors are maintained per-instance */
1029
- usbi_remove_pollfd (HANDLE_CTX (dev_handle), priv->fds[0]);
1030
- close (priv->fds[1]);
1031
- close (priv->fds[0]);
1032
-
1033
- priv->fds[0] = priv->fds[1] = -1;
1034
1245
  }
1035
1246
 
1036
1247
  static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
@@ -1038,40 +1249,42 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int
1038
1249
 
1039
1250
  *config = (int) dpriv->active_config;
1040
1251
 
1041
- return 0;
1252
+ return LIBUSB_SUCCESS;
1042
1253
  }
1043
1254
 
1044
- static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
1255
+ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
1045
1256
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1046
1257
  IOReturn kresult;
1047
1258
  int i;
1048
1259
 
1260
+ assert(config >= 0 && config <= UINT8_MAX);
1261
+
1049
1262
  /* Setting configuration will invalidate the interface, so we need
1050
1263
  to reclaim it. First, dispose of existing interfaces, if any. */
1051
1264
  for (i = 0 ; i < USB_MAXINTERFACES ; i++)
1052
- if (dev_handle->claimed_interfaces & (1 << i))
1265
+ if (dev_handle->claimed_interfaces & (1U << i))
1053
1266
  darwin_release_interface (dev_handle, i);
1054
1267
 
1055
- kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config);
1268
+ kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config);
1056
1269
  if (kresult != kIOReturnSuccess)
1057
1270
  return darwin_to_libusb (kresult);
1058
1271
 
1059
1272
  /* Reclaim any interfaces. */
1060
1273
  for (i = 0 ; i < USB_MAXINTERFACES ; i++)
1061
- if (dev_handle->claimed_interfaces & (1 << i))
1274
+ if (dev_handle->claimed_interfaces & (1U << i))
1062
1275
  darwin_claim_interface (dev_handle, i);
1063
1276
 
1064
- dpriv->active_config = config;
1277
+ dpriv->active_config = (UInt8)config;
1065
1278
 
1066
- return 0;
1279
+ return LIBUSB_SUCCESS;
1067
1280
  }
1068
1281
 
1069
- static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
1282
+ static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_service_t *usbInterfacep) {
1070
1283
  IOUSBFindInterfaceRequest request;
1071
- kern_return_t kresult;
1284
+ IOReturn kresult;
1072
1285
  io_iterator_t interface_iterator;
1073
1286
  UInt8 bInterfaceNumber;
1074
- int ret;
1287
+ bool ret;
1075
1288
 
1076
1289
  *usbInterfacep = IO_OBJECT_NULL;
1077
1290
 
@@ -1082,7 +1295,7 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s
1082
1295
  request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
1083
1296
 
1084
1297
  kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
1085
- if (kresult)
1298
+ if (kresult != kIOReturnSuccess)
1086
1299
  return kresult;
1087
1300
 
1088
1301
  while ((*usbInterfacep = IOIteratorNext(interface_iterator))) {
@@ -1100,64 +1313,84 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s
1100
1313
  /* done with the interface iterator */
1101
1314
  IOObjectRelease(interface_iterator);
1102
1315
 
1103
- return 0;
1316
+ return kIOReturnSuccess;
1104
1317
  }
1105
1318
 
1106
- static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
1319
+ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
1107
1320
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1108
1321
 
1109
1322
  /* current interface */
1110
1323
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1111
1324
 
1112
- kern_return_t kresult;
1325
+ IOReturn kresult;
1113
1326
 
1114
- u_int8_t numep, direction, number;
1115
- u_int8_t dont_care1, dont_care3;
1116
- u_int16_t dont_care2;
1117
- int i;
1327
+ UInt8 numep, direction, number;
1328
+ UInt8 dont_care1, dont_care3;
1329
+ UInt16 dont_care2;
1330
+ int rc;
1118
1331
 
1119
1332
  usbi_dbg ("building table of endpoints.");
1120
1333
 
1121
1334
  /* retrieve the total number of endpoints on this interface */
1122
1335
  kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
1123
- if (kresult) {
1336
+ if (kresult != kIOReturnSuccess) {
1124
1337
  usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
1125
1338
  return darwin_to_libusb (kresult);
1126
1339
  }
1127
1340
 
1128
1341
  /* iterate through pipe references */
1129
- for (i = 1 ; i <= numep ; i++) {
1342
+ for (UInt8 i = 1 ; i <= numep ; i++) {
1130
1343
  kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
1131
1344
  &dont_care2, &dont_care3);
1132
1345
 
1133
1346
  if (kresult != kIOReturnSuccess) {
1134
- usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult));
1347
+ /* probably a buggy device. try to get the endpoint address from the descriptors */
1348
+ struct libusb_config_descriptor *config;
1349
+ const struct libusb_endpoint_descriptor *endpoint_desc;
1350
+ UInt8 alt_setting;
1351
+
1352
+ kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
1353
+ if (kresult != kIOReturnSuccess) {
1354
+ usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
1355
+ return darwin_to_libusb (kresult);
1356
+ }
1135
1357
 
1136
- return darwin_to_libusb (kresult);
1137
- }
1358
+ rc = libusb_get_active_config_descriptor (dev_handle->dev, &config);
1359
+ if (LIBUSB_SUCCESS != rc) {
1360
+ return rc;
1361
+ }
1362
+
1363
+ endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1;
1138
1364
 
1139
- usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number);
1365
+ cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
1366
+ } else {
1367
+ cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
1368
+ }
1140
1369
 
1141
- cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
1370
+ usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
1371
+ cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
1142
1372
  }
1143
1373
 
1144
1374
  cInterface->num_endpoints = numep;
1145
1375
 
1146
- return 0;
1376
+ return LIBUSB_SUCCESS;
1147
1377
  }
1148
1378
 
1149
1379
  static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) {
1150
1380
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1151
1381
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1152
1382
  io_service_t usbInterface = IO_OBJECT_NULL;
1153
- IOReturn kresult;
1383
+ IOReturn kresult;
1384
+ enum libusb_error ret;
1154
1385
  IOCFPlugInInterface **plugInInterface = NULL;
1155
1386
  SInt32 score;
1156
1387
 
1388
+ assert(iface >= 0 && iface <= UINT8_MAX);
1389
+
1157
1390
  /* current interface */
1158
1391
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1159
1392
 
1160
- kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
1393
+ kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
1161
1394
  if (kresult != kIOReturnSuccess)
1162
1395
  return darwin_to_libusb (kresult);
1163
1396
 
@@ -1166,14 +1399,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1166
1399
  usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config);
1167
1400
 
1168
1401
  /* set the configuration */
1169
- kresult = darwin_set_configuration (dev_handle, dpriv->first_config);
1170
- if (kresult != LIBUSB_SUCCESS) {
1402
+ ret = darwin_set_configuration (dev_handle, dpriv->first_config);
1403
+ if (ret != LIBUSB_SUCCESS) {
1171
1404
  usbi_err (HANDLE_CTX (dev_handle), "could not set configuration");
1172
- return kresult;
1405
+ return ret;
1173
1406
  }
1174
1407
 
1175
- kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
1176
- if (kresult) {
1408
+ kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
1409
+ if (kresult != kIOReturnSuccess) {
1177
1410
  usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
1178
1411
  return darwin_to_libusb (kresult);
1179
1412
  }
@@ -1191,7 +1424,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1191
1424
  /* ignore release error */
1192
1425
  (void)IOObjectRelease (usbInterface);
1193
1426
 
1194
- if (kresult) {
1427
+ if (kresult != kIOReturnSuccess) {
1195
1428
  usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
1196
1429
  return darwin_to_libusb (kresult);
1197
1430
  }
@@ -1203,30 +1436,30 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1203
1436
 
1204
1437
  /* Do the actual claim */
1205
1438
  kresult = (*plugInInterface)->QueryInterface(plugInInterface,
1206
- CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
1439
+ CFUUIDGetUUIDBytes(InterfaceInterfaceID),
1207
1440
  (LPVOID)&cInterface->interface);
1208
1441
  /* We no longer need the intermediate plug-in */
1209
1442
  /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
1210
1443
  (*plugInInterface)->Release (plugInInterface);
1211
- if (kresult || !cInterface->interface) {
1444
+ if (kresult != kIOReturnSuccess || !cInterface->interface) {
1212
1445
  usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult));
1213
1446
  return darwin_to_libusb (kresult);
1214
1447
  }
1215
1448
 
1216
1449
  /* claim the interface */
1217
1450
  kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
1218
- if (kresult) {
1451
+ if (kresult != kIOReturnSuccess) {
1219
1452
  usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult));
1220
1453
  return darwin_to_libusb (kresult);
1221
1454
  }
1222
1455
 
1223
1456
  /* update list of endpoints */
1224
- kresult = get_endpoints (dev_handle, iface);
1225
- if (kresult) {
1457
+ ret = get_endpoints (dev_handle, iface);
1458
+ if (ret) {
1226
1459
  /* this should not happen */
1227
1460
  darwin_release_interface (dev_handle, iface);
1228
1461
  usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
1229
- return kresult;
1462
+ return ret;
1230
1463
  }
1231
1464
 
1232
1465
  cInterface->cfSource = NULL;
@@ -1247,7 +1480,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1247
1480
 
1248
1481
  usbi_dbg ("interface opened");
1249
1482
 
1250
- return 0;
1483
+ return LIBUSB_SUCCESS;
1251
1484
  }
1252
1485
 
1253
1486
  static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) {
@@ -1271,14 +1504,14 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
1271
1504
  }
1272
1505
 
1273
1506
  kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
1274
- if (kresult)
1507
+ if (kresult != kIOReturnSuccess)
1275
1508
  usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
1276
1509
 
1277
1510
  kresult = (*(cInterface->interface))->Release(cInterface->interface);
1278
1511
  if (kresult != kIOReturnSuccess)
1279
1512
  usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
1280
1513
 
1281
- cInterface->interface = IO_OBJECT_NULL;
1514
+ cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL;
1282
1515
 
1283
1516
  return darwin_to_libusb (kresult);
1284
1517
  }
@@ -1286,6 +1519,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
1286
1519
  static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) {
1287
1520
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1288
1521
  IOReturn kresult;
1522
+ enum libusb_error ret;
1289
1523
 
1290
1524
  /* current interface */
1291
1525
  struct darwin_interface *cInterface = &priv->interfaces[iface];
@@ -1293,17 +1527,18 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
1293
1527
  if (!cInterface->interface)
1294
1528
  return LIBUSB_ERROR_NO_DEVICE;
1295
1529
 
1296
- kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting);
1530
+ assert(altsetting >= 0 && altsetting <= UINT8_MAX);
1531
+ kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, (UInt8)altsetting);
1297
1532
  if (kresult != kIOReturnSuccess)
1298
1533
  darwin_reset_device (dev_handle);
1299
1534
 
1300
1535
  /* update list of endpoints */
1301
- kresult = get_endpoints (dev_handle, iface);
1302
- if (kresult) {
1536
+ ret = get_endpoints (dev_handle, iface);
1537
+ if (ret) {
1303
1538
  /* this should not happen */
1304
1539
  darwin_release_interface (dev_handle, iface);
1305
1540
  usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
1306
- return kresult;
1541
+ return ret;
1307
1542
  }
1308
1543
 
1309
1544
  return darwin_to_libusb (kresult);
@@ -1324,62 +1559,133 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1324
1559
 
1325
1560
  /* newer versions of darwin support clearing additional bits on the device's endpoint */
1326
1561
  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
1327
- if (kresult)
1562
+ if (kresult != kIOReturnSuccess)
1328
1563
  usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
1329
1564
 
1330
1565
  return darwin_to_libusb (kresult);
1331
1566
  }
1332
1567
 
1568
+ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
1569
+ unsigned long claimed_interfaces) {
1570
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1571
+ struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1572
+ int open_count = dpriv->open_count;
1573
+ int ret;
1574
+
1575
+ /* clear claimed interfaces temporarily */
1576
+ dev_handle->claimed_interfaces = 0;
1577
+
1578
+ /* close and re-open the device */
1579
+ priv->is_open = false;
1580
+ dpriv->open_count = 1;
1581
+
1582
+ /* clean up open interfaces */
1583
+ (void) darwin_close (dev_handle);
1584
+
1585
+ /* re-open the device */
1586
+ ret = darwin_open (dev_handle);
1587
+ dpriv->open_count = open_count;
1588
+ if (LIBUSB_SUCCESS != ret) {
1589
+ /* could not restore configuration */
1590
+ return LIBUSB_ERROR_NOT_FOUND;
1591
+ }
1592
+
1593
+ if (dpriv->active_config != active_config) {
1594
+ usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config);
1595
+
1596
+ ret = darwin_set_configuration (dev_handle, active_config);
1597
+ if (LIBUSB_SUCCESS != ret) {
1598
+ usbi_dbg ("darwin/restore_state: could not restore configuration");
1599
+ return LIBUSB_ERROR_NOT_FOUND;
1600
+ }
1601
+ }
1602
+
1603
+ usbi_dbg ("darwin/restore_state: reclaiming interfaces");
1604
+
1605
+ if (claimed_interfaces) {
1606
+ for (int iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
1607
+ if (!(claimed_interfaces & (1U << iface))) {
1608
+ continue;
1609
+ }
1610
+
1611
+ usbi_dbg ("darwin/restore_state: re-claiming interface %d", iface);
1612
+
1613
+ ret = darwin_claim_interface (dev_handle, iface);
1614
+ if (LIBUSB_SUCCESS != ret) {
1615
+ usbi_dbg ("darwin/restore_state: could not claim interface %d", iface);
1616
+ return LIBUSB_ERROR_NOT_FOUND;
1617
+ }
1618
+
1619
+ dev_handle->claimed_interfaces |= 1U << iface;
1620
+ }
1621
+ }
1622
+
1623
+ usbi_dbg ("darwin/restore_state: device state restored");
1624
+
1625
+ return LIBUSB_SUCCESS;
1626
+ }
1627
+
1333
1628
  static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
1334
1629
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1630
+ unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
1631
+ int8_t active_config = dpriv->active_config;
1335
1632
  IOUSBDeviceDescriptor descriptor;
1336
1633
  IOUSBConfigurationDescriptorPtr cached_configuration;
1337
- IOUSBConfigurationDescriptor configuration;
1338
- bool reenumerate = false;
1634
+ IOUSBConfigurationDescriptor *cached_configurations;
1339
1635
  IOReturn kresult;
1340
- int i;
1636
+ UInt8 i;
1341
1637
 
1342
- kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
1343
- if (kresult) {
1344
- usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult));
1345
- return darwin_to_libusb (kresult);
1638
+ if (dpriv->in_reenumerate) {
1639
+ /* ack, two (or more) threads are trying to reset the device! abort! */
1640
+ return LIBUSB_ERROR_NOT_FOUND;
1346
1641
  }
1347
1642
 
1348
- do {
1349
- usbi_dbg ("darwin/reset_device: checking if device descriptor changed");
1643
+ dpriv->in_reenumerate = true;
1350
1644
 
1351
- /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */
1352
- (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor));
1645
+ /* store copies of descriptors so they can be compared after the reset */
1646
+ memcpy (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor));
1647
+ cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
1353
1648
 
1354
- /* check if the device descriptor has changed */
1355
- if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) {
1356
- reenumerate = true;
1357
- break;
1358
- }
1649
+ for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1650
+ (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1651
+ memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
1652
+ }
1359
1653
 
1360
- /* check if any configuration descriptor has changed */
1361
- for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1362
- usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i);
1654
+ /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
1655
+ kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
1656
+ if (kresult != kIOReturnSuccess) {
1657
+ usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
1658
+ dpriv->in_reenumerate = false;
1659
+ return darwin_to_libusb (kresult);
1660
+ }
1363
1661
 
1364
- (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration));
1365
- (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1662
+ usbi_dbg ("darwin/reset_device: waiting for re-enumeration to complete...");
1366
1663
 
1367
- if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) {
1368
- reenumerate = true;
1369
- break;
1370
- }
1371
- }
1372
- } while (0);
1664
+ while (dpriv->in_reenumerate) {
1665
+ struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
1666
+ nanosleep (&delay, NULL);
1667
+ }
1668
+
1669
+ /* compare descriptors */
1670
+ usbi_dbg ("darwin/reset_device: checking whether descriptors changed");
1373
1671
 
1374
- if (reenumerate) {
1375
- usbi_dbg ("darwin/reset_device: device requires reenumeration");
1376
- (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
1672
+ if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
1673
+ /* device descriptor changed. need to return not found. */
1674
+ usbi_dbg ("darwin/reset_device: device descriptor changed");
1377
1675
  return LIBUSB_ERROR_NOT_FOUND;
1378
1676
  }
1379
1677
 
1380
- usbi_dbg ("darwin/reset_device: device reset complete");
1678
+ for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1679
+ (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1680
+ if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
1681
+ usbi_dbg ("darwin/reset_device: configuration descriptor %d changed", i);
1682
+ return LIBUSB_ERROR_NOT_FOUND;
1683
+ }
1684
+ }
1381
1685
 
1382
- return LIBUSB_SUCCESS;
1686
+ usbi_dbg ("darwin/reset_device: device reset complete. restoring state...");
1687
+
1688
+ return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
1383
1689
  }
1384
1690
 
1385
1691
  static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) {
@@ -1388,8 +1694,9 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
1388
1694
  CFTypeRef driver;
1389
1695
  IOReturn kresult;
1390
1696
 
1391
- kresult = darwin_get_interface (dpriv->device, interface, &usbInterface);
1392
- if (kresult) {
1697
+ assert(interface >= 0 && interface <= UINT8_MAX);
1698
+ kresult = darwin_get_interface (dpriv->device, (uint8_t)interface, &usbInterface);
1699
+ if (kresult != kIOReturnSuccess) {
1393
1700
  usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
1394
1701
 
1395
1702
  return darwin_to_libusb (kresult);
@@ -1410,14 +1717,14 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
1410
1717
 
1411
1718
  /* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
1412
1719
  static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
1413
- (void)dev_handle;
1414
- (void)interface;
1720
+ UNUSED(dev_handle);
1721
+ UNUSED(interface);
1415
1722
  return LIBUSB_ERROR_NOT_SUPPORTED;
1416
1723
  }
1417
1724
 
1418
1725
  static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
1419
- (void)dev_handle;
1420
- (void)interface;
1726
+ UNUSED(dev_handle);
1727
+ UNUSED(interface);
1421
1728
  return LIBUSB_ERROR_NOT_SUPPORTED;
1422
1729
  }
1423
1730
 
@@ -1469,21 +1776,21 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1469
1776
  if (transferType == kUSBInterrupt) {
1470
1777
  if (IS_XFERIN(transfer))
1471
1778
  ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
1472
- transfer->length, darwin_async_io_callback, itransfer);
1779
+ (UInt32)transfer->length, darwin_async_io_callback, itransfer);
1473
1780
  else
1474
1781
  ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
1475
- transfer->length, darwin_async_io_callback, itransfer);
1782
+ (UInt32)transfer->length, darwin_async_io_callback, itransfer);
1476
1783
  } else {
1477
- itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1784
+ itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1478
1785
 
1479
1786
  if (IS_XFERIN(transfer))
1480
1787
  ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
1481
- transfer->length, transfer->timeout, transfer->timeout,
1482
- darwin_async_io_callback, (void *)itransfer);
1788
+ (UInt32)transfer->length, transfer->timeout, transfer->timeout,
1789
+ darwin_async_io_callback, itransfer);
1483
1790
  else
1484
1791
  ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
1485
- transfer->length, transfer->timeout, transfer->timeout,
1486
- darwin_async_io_callback, (void *)itransfer);
1792
+ (UInt32)transfer->length, transfer->timeout, transfer->timeout,
1793
+ darwin_async_io_callback, itransfer);
1487
1794
  }
1488
1795
 
1489
1796
  if (ret)
@@ -1506,16 +1813,16 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
1506
1813
  return LIBUSB_ERROR_NOT_FOUND;
1507
1814
  }
1508
1815
 
1509
- itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1816
+ itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1510
1817
 
1511
1818
  if (IS_XFERIN(transfer))
1512
1819
  ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
1513
- transfer->buffer, transfer->length, transfer->timeout,
1514
- transfer->timeout, darwin_async_io_callback, (void *)itransfer);
1820
+ transfer->buffer, (UInt32)transfer->length, transfer->timeout,
1821
+ transfer->timeout, darwin_async_io_callback, itransfer);
1515
1822
  else
1516
1823
  ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
1517
- transfer->buffer, transfer->length, transfer->timeout,
1518
- transfer->timeout, darwin_async_io_callback, (void *)itransfer);
1824
+ transfer->buffer, (UInt32)transfer->length, transfer->timeout,
1825
+ transfer->timeout, darwin_async_io_callback, itransfer);
1519
1826
 
1520
1827
  if (ret)
1521
1828
  usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1538,22 +1845,25 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1538
1845
 
1539
1846
  struct darwin_interface *cInterface;
1540
1847
 
1541
- /* construct an array of IOUSBIsocFrames, reuse the old one if possible */
1542
- if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) {
1848
+ /* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */
1849
+ if (tpriv->num_iso_packets != transfer->num_iso_packets) {
1543
1850
  free(tpriv->isoc_framelist);
1544
1851
  tpriv->isoc_framelist = NULL;
1545
1852
  }
1546
1853
 
1547
1854
  if (!tpriv->isoc_framelist) {
1548
1855
  tpriv->num_iso_packets = transfer->num_iso_packets;
1549
- tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
1856
+ tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc ((size_t)transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
1550
1857
  if (!tpriv->isoc_framelist)
1551
1858
  return LIBUSB_ERROR_NO_MEM;
1552
1859
  }
1553
1860
 
1554
1861
  /* copy the frame list from the libusb descriptor (the structures differ only is member order) */
1555
- for (i = 0 ; i < transfer->num_iso_packets ; i++)
1556
- tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length;
1862
+ for (i = 0 ; i < transfer->num_iso_packets ; i++) {
1863
+ unsigned int length = transfer->iso_packet_desc[i].length;
1864
+ assert(length <= UINT16_MAX);
1865
+ tpriv->isoc_framelist[i].frReqCount = (UInt16)length;
1866
+ }
1557
1867
 
1558
1868
  /* determine the interface/endpoint to use */
1559
1869
  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
@@ -1568,7 +1878,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1568
1878
 
1569
1879
  /* Last but not least we need the bus frame number */
1570
1880
  kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
1571
- if (kresult) {
1881
+ if (kresult != kIOReturnSuccess) {
1572
1882
  usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
1573
1883
  free(tpriv->isoc_framelist);
1574
1884
  tpriv->isoc_framelist = NULL;
@@ -1588,19 +1898,19 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1588
1898
  /* submit the request */
1589
1899
  if (IS_XFERIN(transfer))
1590
1900
  kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
1591
- transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1901
+ (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1592
1902
  itransfer);
1593
1903
  else
1594
1904
  kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
1595
- transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1905
+ (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1596
1906
  itransfer);
1597
1907
 
1598
1908
  if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
1599
1909
  /* Full speed */
1600
- cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1));
1910
+ cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1));
1601
1911
  else
1602
1912
  /* High/super speed */
1603
- cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8;
1913
+ cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8;
1604
1914
 
1605
1915
  if (kresult != kIOReturnSuccess) {
1606
1916
  usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1620,9 +1930,9 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
1620
1930
 
1621
1931
  IOReturn kresult;
1622
1932
 
1623
- bzero(&tpriv->req, sizeof(tpriv->req));
1933
+ memset(&tpriv->req, 0, sizeof(tpriv->req));
1624
1934
 
1625
- /* IOUSBDeviceInterface expects the request in cpu endianess */
1935
+ /* IOUSBDeviceInterface expects the request in cpu endianness */
1626
1936
  tpriv->req.bmRequestType = setup->bmRequestType;
1627
1937
  tpriv->req.bRequest = setup->bRequest;
1628
1938
  /* these values should be in bus order from libusb_fill_control_setup */
@@ -1634,7 +1944,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
1634
1944
  tpriv->req.completionTimeout = transfer->timeout;
1635
1945
  tpriv->req.noDataTimeout = transfer->timeout;
1636
1946
 
1637
- itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1947
+ itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1638
1948
 
1639
1949
  /* all transfers in libusb-1.0 are async */
1640
1950
 
@@ -1761,9 +2071,7 @@ static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
1761
2071
  static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
1762
2072
  struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
1763
2073
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1764
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
1765
- struct darwin_msg_async_io_complete message = {.itransfer = itransfer, .result = result,
1766
- .size = (UInt32) (uintptr_t) arg0};
2074
+ struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
1767
2075
 
1768
2076
  usbi_dbg ("an async io operation has completed");
1769
2077
 
@@ -1777,12 +2085,15 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
1777
2085
  (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
1778
2086
  }
1779
2087
 
1780
- /* send a completion message to the device's file descriptor */
1781
- write (priv->fds[1], &message, sizeof (message));
2088
+ tpriv->result = result;
2089
+ tpriv->size = (UInt32) (uintptr_t) arg0;
2090
+
2091
+ /* signal the core that this transfer is complete */
2092
+ usbi_signal_transfer_completion(itransfer);
1782
2093
  }
1783
2094
 
1784
- static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
1785
- if (itransfer->flags & USBI_TRANSFER_TIMED_OUT)
2095
+ static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer *itransfer, IOReturn result) {
2096
+ if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
1786
2097
  result = kIOUSBTransactionTimeout;
1787
2098
 
1788
2099
  switch (result) {
@@ -1799,7 +2110,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
1799
2110
  return LIBUSB_TRANSFER_OVERFLOW;
1800
2111
  case kIOUSBTransactionTimeout:
1801
2112
  usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out");
1802
- itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
2113
+ itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
1803
2114
  return LIBUSB_TRANSFER_TIMED_OUT;
1804
2115
  default:
1805
2116
  usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
@@ -1807,78 +2118,42 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
1807
2118
  }
1808
2119
  }
1809
2120
 
1810
- static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) {
2121
+ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
1811
2122
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1812
2123
  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
1813
- int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
1814
- int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type;
1815
- int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type;
1816
- int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type;
2124
+ bool isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
2125
+ bool isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type;
2126
+ bool isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type;
2127
+ bool isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type;
1817
2128
  int i;
1818
2129
 
1819
2130
  if (!isIsoc && !isBulk && !isControl && !isInterrupt) {
1820
2131
  usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
1821
- return;
2132
+ return LIBUSB_ERROR_INVALID_PARAM;
1822
2133
  }
1823
2134
 
1824
2135
  usbi_dbg ("handling %s completion with kernel status %d",
1825
- isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result);
2136
+ isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
1826
2137
 
1827
- if (kIOReturnSuccess == result || kIOReturnUnderrun == result) {
2138
+ if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
1828
2139
  if (isIsoc && tpriv->isoc_framelist) {
1829
2140
  /* copy isochronous results back */
1830
2141
 
1831
2142
  for (i = 0; i < transfer->num_iso_packets ; i++) {
1832
2143
  struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
1833
- lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus);
2144
+ lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus);
1834
2145
  lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
1835
2146
  }
1836
2147
  } else if (!isIsoc)
1837
- itransfer->transferred += io_size;
2148
+ itransfer->transferred += tpriv->size;
1838
2149
  }
1839
2150
 
1840
2151
  /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
1841
- usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result));
1842
- }
1843
-
1844
- static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) {
1845
- struct darwin_msg_async_io_complete message;
1846
- POLL_NFDS_TYPE i = 0;
1847
- ssize_t ret;
1848
-
1849
- usbi_mutex_lock(&ctx->open_devs_lock);
1850
-
1851
- for (i = 0; i < nfds && num_ready > 0; i++) {
1852
- struct pollfd *pollfd = &fds[i];
1853
-
1854
- usbi_dbg ("checking fd %i with revents = %x", pollfd->fd, pollfd->revents);
1855
-
1856
- if (!pollfd->revents)
1857
- continue;
1858
-
1859
- num_ready--;
1860
-
1861
- if (pollfd->revents & POLLERR) {
1862
- /* this probably will never happen so ignore the error an move on. */
1863
- continue;
1864
- }
1865
-
1866
- /* there is only one type of message */
1867
- ret = read (pollfd->fd, &message, sizeof (message));
1868
- if (ret < (ssize_t) sizeof (message)) {
1869
- usbi_dbg ("WARNING: short read on async io completion pipe\n");
1870
- continue;
1871
- }
1872
-
1873
- darwin_handle_callback (message.itransfer, message.result, message.size);
1874
- }
1875
-
1876
- usbi_mutex_unlock(&ctx->open_devs_lock);
1877
-
1878
- return 0;
2152
+ return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
1879
2153
  }
1880
2154
 
1881
2155
  static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
2156
+ #if !OSX_USE_CLOCK_GETTIME
1882
2157
  mach_timespec_t sys_time;
1883
2158
  clock_serv_t clock_ref;
1884
2159
 
@@ -1900,7 +2175,17 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
1900
2175
  tp->tv_sec = sys_time.tv_sec;
1901
2176
  tp->tv_nsec = sys_time.tv_nsec;
1902
2177
 
1903
- return 0;
2178
+ return LIBUSB_SUCCESS;
2179
+ #else
2180
+ switch (clk_id) {
2181
+ case USBI_CLOCK_MONOTONIC:
2182
+ return clock_gettime(CLOCK_MONOTONIC, tp);
2183
+ case USBI_CLOCK_REALTIME:
2184
+ return clock_gettime(CLOCK_REALTIME, tp);
2185
+ default:
2186
+ return LIBUSB_ERROR_INVALID_PARAM;
2187
+ }
2188
+ #endif
1904
2189
  }
1905
2190
 
1906
2191
  #if InterfaceVersion >= 550
@@ -1935,7 +2220,8 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
1935
2220
  return darwin_to_libusb(rc);
1936
2221
  }
1937
2222
 
1938
- return num_streams;
2223
+ assert(num_streams <= INT_MAX);
2224
+ return (int)num_streams;
1939
2225
  }
1940
2226
 
1941
2227
  static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) {
@@ -1961,9 +2247,9 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
1961
2247
  }
1962
2248
  #endif
1963
2249
 
1964
- const struct usbi_os_backend darwin_backend = {
2250
+ const struct usbi_os_backend usbi_backend = {
1965
2251
  .name = "Darwin",
1966
- .caps = USBI_CAP_HAS_POLLABLE_DEVICE_FD,
2252
+ .caps = 0,
1967
2253
  .init = darwin_init,
1968
2254
  .exit = darwin_exit,
1969
2255
  .get_device_list = NULL, /* not needed */
@@ -1998,12 +2284,11 @@ const struct usbi_os_backend darwin_backend = {
1998
2284
  .cancel_transfer = darwin_cancel_transfer,
1999
2285
  .clear_transfer_priv = darwin_clear_transfer_priv,
2000
2286
 
2001
- .handle_events = op_handle_events,
2287
+ .handle_transfer_completion = darwin_handle_transfer_completion,
2002
2288
 
2003
2289
  .clock_gettime = darwin_clock_gettime,
2004
2290
 
2005
2291
  .device_priv_size = sizeof(struct darwin_device_priv),
2006
2292
  .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
2007
2293
  .transfer_priv_size = sizeof(struct darwin_transfer_priv),
2008
- .add_iso_packet_size = 0,
2009
2294
  };