usb 2.12.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +1 -1
  3. package/dist/index.js +6 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/usb/bindings.js +1 -1
  6. package/dist/usb/bindings.js.map +1 -1
  7. package/dist/usb/capability.js.map +1 -1
  8. package/dist/usb/device.js.map +1 -1
  9. package/dist/usb/endpoint.d.ts +1 -0
  10. package/dist/usb/endpoint.js +2 -2
  11. package/dist/usb/endpoint.js.map +1 -1
  12. package/dist/usb/index.js.map +1 -1
  13. package/dist/usb/interface.js +2 -2
  14. package/dist/usb/interface.js.map +1 -1
  15. package/dist/webusb/index.d.ts +2 -2
  16. package/dist/webusb/index.js.map +1 -1
  17. package/dist/webusb/webusb-device.js +10 -10
  18. package/dist/webusb/webusb-device.js.map +1 -1
  19. package/libusb/.codespellrc +3 -0
  20. package/libusb/.private/appveyor_build.sh +5 -1
  21. package/libusb/.private/ci-build.sh +26 -1
  22. package/libusb/.private/ci-container-build.sh +2 -5
  23. package/libusb/.private/wbs.txt +5 -8
  24. package/libusb/AUTHORS +22 -0
  25. package/libusb/ChangeLog +19 -2
  26. package/libusb/HACKING +25 -0
  27. package/libusb/INSTALL_WIN.txt +11 -10
  28. package/libusb/NEWS +2 -2
  29. package/libusb/README +3 -2
  30. package/libusb/README.git +1 -1
  31. package/libusb/Xcode/common.xcconfig +8 -1
  32. package/libusb/Xcode/config.h +0 -6
  33. package/libusb/Xcode/debug.xcconfig +4 -1
  34. package/libusb/Xcode/libusb.xcconfig +1 -1
  35. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +60 -30
  36. package/libusb/Xcode/libusb_debug.xcconfig +1 -1
  37. package/libusb/Xcode/libusb_release.xcconfig +1 -1
  38. package/libusb/Xcode/release.xcconfig +1 -1
  39. package/libusb/appveyor.yml +33 -9
  40. package/libusb/configure.ac +68 -37
  41. package/libusb/examples/dpfp.c +2 -2
  42. package/libusb/examples/fxload.c +2 -2
  43. package/libusb/examples/hotplugtest.c +28 -13
  44. package/libusb/examples/listdevs.c +1 -1
  45. package/libusb/examples/sam3u_benchmark.c +1 -1
  46. package/libusb/examples/testlibusb.c +1 -1
  47. package/libusb/examples/xusb.c +74 -19
  48. package/libusb/libusb/Makefile.am +11 -1
  49. package/libusb/libusb/core.c +364 -186
  50. package/libusb/libusb/descriptor.c +276 -16
  51. package/libusb/libusb/hotplug.c +5 -4
  52. package/libusb/libusb/io.c +72 -61
  53. package/libusb/libusb/libusb-1.0.def +14 -1
  54. package/libusb/libusb/libusb.h +245 -76
  55. package/libusb/libusb/libusbi.h +35 -13
  56. package/libusb/libusb/os/darwin_usb.c +542 -279
  57. package/libusb/libusb/os/darwin_usb.h +44 -115
  58. package/libusb/libusb/os/emscripten_webusb.cpp +870 -0
  59. package/libusb/libusb/os/events_posix.c +40 -0
  60. package/libusb/libusb/os/events_posix.h +3 -0
  61. package/libusb/libusb/os/linux_usbfs.c +27 -16
  62. package/libusb/libusb/os/netbsd_usb.c +36 -36
  63. package/libusb/libusb/os/openbsd_usb.c +34 -34
  64. package/libusb/libusb/os/sunos_usb.c +25 -15
  65. package/libusb/libusb/os/threads_posix.c +1 -5
  66. package/libusb/libusb/os/windows_common.c +13 -5
  67. package/libusb/libusb/os/windows_common.h +8 -0
  68. package/libusb/libusb/os/windows_winusb.c +366 -174
  69. package/libusb/libusb/os/windows_winusb.h +13 -9
  70. package/libusb/libusb/strerror.c +5 -5
  71. package/libusb/libusb/sync.c +24 -19
  72. package/libusb/libusb/version.h +1 -1
  73. package/libusb/libusb/version_nano.h +1 -1
  74. package/libusb/msvc/Base.props +60 -0
  75. package/libusb/msvc/Configuration.Application.props +7 -0
  76. package/libusb/msvc/Configuration.Base.props +47 -0
  77. package/libusb/msvc/Configuration.DynamicLibrary.props +21 -0
  78. package/libusb/msvc/Configuration.StaticLibrary.props +7 -0
  79. package/libusb/msvc/ProjectConfigurations.Base.props +69 -0
  80. package/libusb/msvc/build_all.ps1 +17 -0
  81. package/libusb/msvc/config.h +2 -2
  82. package/libusb/msvc/dpfp.vcxproj +33 -0
  83. package/libusb/msvc/dpfp_threaded.vcxproj +38 -0
  84. package/libusb/msvc/fxload.vcxproj +46 -0
  85. package/libusb/msvc/getopt.vcxproj +33 -0
  86. package/libusb/msvc/hotplugtest.vcxproj +32 -0
  87. package/libusb/msvc/init_context.vcxproj +35 -0
  88. package/libusb/msvc/libusb.sln +542 -0
  89. package/libusb/msvc/libusb_dll.vcxproj +61 -0
  90. package/libusb/msvc/libusb_static.vcxproj +49 -0
  91. package/libusb/msvc/listdevs.vcxproj +32 -0
  92. package/libusb/msvc/sam3u_benchmark.vcxproj +33 -0
  93. package/libusb/msvc/set_option.vcxproj +35 -0
  94. package/libusb/msvc/stress.vcxproj +35 -0
  95. package/libusb/msvc/stress_mt.vcxproj +33 -0
  96. package/libusb/msvc/testlibusb.vcxproj +32 -0
  97. package/libusb/msvc/xusb.vcxproj +38 -0
  98. package/libusb/tests/Makefile.am +25 -3
  99. package/libusb/tests/init_context.c +153 -0
  100. package/libusb/tests/macos.c +130 -0
  101. package/libusb/tests/set_option.c +253 -0
  102. package/libusb/tests/stress.c +17 -14
  103. package/libusb/tests/stress_mt.c +265 -0
  104. package/libusb/tests/testlib.c +1 -1
  105. package/libusb/tests/umockdev.c +9 -9
  106. package/libusb/tests/webusb-test-shim/index.js +12 -0
  107. package/libusb/tests/webusb-test-shim/package-lock.json +50 -0
  108. package/libusb/tests/webusb-test-shim/package.json +10 -0
  109. package/package.json +7 -7
  110. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  111. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  112. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  113. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  114. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  115. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  116. package/prebuilds/linux-ia32/node.napi.node +0 -0
  117. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  118. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  119. package/prebuilds/win32-arm64/node.napi.node +0 -0
  120. package/prebuilds/win32-ia32/node.napi.node +0 -0
  121. package/prebuilds/win32-x64/node.napi.node +0 -0
  122. package/src/device.cc +15 -5
  123. package/libusb/msvc/dpfp_2013.vcxproj +0 -87
  124. package/libusb/msvc/dpfp_2013.vcxproj.filters +0 -26
  125. package/libusb/msvc/dpfp_2015.vcxproj +0 -87
  126. package/libusb/msvc/dpfp_2015.vcxproj.filters +0 -26
  127. package/libusb/msvc/dpfp_2017.vcxproj +0 -106
  128. package/libusb/msvc/dpfp_2017.vcxproj.filters +0 -26
  129. package/libusb/msvc/dpfp_2019.vcxproj +0 -106
  130. package/libusb/msvc/dpfp_2019.vcxproj.filters +0 -26
  131. package/libusb/msvc/dpfp_threaded_2013.vcxproj +0 -87
  132. package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +0 -26
  133. package/libusb/msvc/dpfp_threaded_2015.vcxproj +0 -87
  134. package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +0 -26
  135. package/libusb/msvc/dpfp_threaded_2017.vcxproj +0 -106
  136. package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +0 -26
  137. package/libusb/msvc/dpfp_threaded_2019.vcxproj +0 -106
  138. package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +0 -26
  139. package/libusb/msvc/fxload_2013.vcxproj +0 -94
  140. package/libusb/msvc/fxload_2013.vcxproj.filters +0 -35
  141. package/libusb/msvc/fxload_2015.vcxproj +0 -94
  142. package/libusb/msvc/fxload_2015.vcxproj.filters +0 -35
  143. package/libusb/msvc/fxload_2017.vcxproj +0 -113
  144. package/libusb/msvc/fxload_2017.vcxproj.filters +0 -35
  145. package/libusb/msvc/fxload_2019.vcxproj +0 -113
  146. package/libusb/msvc/fxload_2019.vcxproj.filters +0 -35
  147. package/libusb/msvc/getopt_2013.vcxproj +0 -72
  148. package/libusb/msvc/getopt_2013.vcxproj.filters +0 -26
  149. package/libusb/msvc/getopt_2015.vcxproj +0 -73
  150. package/libusb/msvc/getopt_2015.vcxproj.filters +0 -26
  151. package/libusb/msvc/getopt_2017.vcxproj +0 -92
  152. package/libusb/msvc/getopt_2017.vcxproj.filters +0 -26
  153. package/libusb/msvc/getopt_2019.vcxproj +0 -92
  154. package/libusb/msvc/getopt_2019.vcxproj.filters +0 -26
  155. package/libusb/msvc/hotplugtest_2013.vcxproj +0 -86
  156. package/libusb/msvc/hotplugtest_2013.vcxproj.filters +0 -23
  157. package/libusb/msvc/hotplugtest_2015.vcxproj +0 -86
  158. package/libusb/msvc/hotplugtest_2015.vcxproj.filters +0 -23
  159. package/libusb/msvc/hotplugtest_2017.vcxproj +0 -105
  160. package/libusb/msvc/hotplugtest_2017.vcxproj.filters +0 -23
  161. package/libusb/msvc/hotplugtest_2019.vcxproj +0 -105
  162. package/libusb/msvc/hotplugtest_2019.vcxproj.filters +0 -23
  163. package/libusb/msvc/libusb_2013.sln +0 -137
  164. package/libusb/msvc/libusb_2015.sln +0 -137
  165. package/libusb/msvc/libusb_2017.sln +0 -240
  166. package/libusb/msvc/libusb_2019.sln +0 -240
  167. package/libusb/msvc/libusb_dll_2013.vcxproj +0 -104
  168. package/libusb/msvc/libusb_dll_2013.vcxproj.filters +0 -94
  169. package/libusb/msvc/libusb_dll_2015.vcxproj +0 -105
  170. package/libusb/msvc/libusb_dll_2015.vcxproj.filters +0 -94
  171. package/libusb/msvc/libusb_dll_2017.vcxproj +0 -124
  172. package/libusb/msvc/libusb_dll_2017.vcxproj.filters +0 -94
  173. package/libusb/msvc/libusb_dll_2019.vcxproj +0 -124
  174. package/libusb/msvc/libusb_dll_2019.vcxproj.filters +0 -94
  175. package/libusb/msvc/libusb_static_2013.vcxproj +0 -94
  176. package/libusb/msvc/libusb_static_2013.vcxproj.filters +0 -80
  177. package/libusb/msvc/libusb_static_2015.vcxproj +0 -95
  178. package/libusb/msvc/libusb_static_2015.vcxproj.filters +0 -80
  179. package/libusb/msvc/libusb_static_2017.vcxproj +0 -114
  180. package/libusb/msvc/libusb_static_2017.vcxproj.filters +0 -80
  181. package/libusb/msvc/libusb_static_2019.vcxproj +0 -114
  182. package/libusb/msvc/libusb_static_2019.vcxproj.filters +0 -80
  183. package/libusb/msvc/listdevs_2013.vcxproj +0 -86
  184. package/libusb/msvc/listdevs_2013.vcxproj.filters +0 -23
  185. package/libusb/msvc/listdevs_2015.vcxproj +0 -86
  186. package/libusb/msvc/listdevs_2015.vcxproj.filters +0 -23
  187. package/libusb/msvc/listdevs_2017.vcxproj +0 -105
  188. package/libusb/msvc/listdevs_2017.vcxproj.filters +0 -23
  189. package/libusb/msvc/listdevs_2019.vcxproj +0 -105
  190. package/libusb/msvc/listdevs_2019.vcxproj.filters +0 -23
  191. package/libusb/msvc/sam3u_benchmark_2013.vcxproj +0 -87
  192. package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +0 -26
  193. package/libusb/msvc/sam3u_benchmark_2015.vcxproj +0 -87
  194. package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +0 -26
  195. package/libusb/msvc/sam3u_benchmark_2017.vcxproj +0 -106
  196. package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +0 -26
  197. package/libusb/msvc/sam3u_benchmark_2019.vcxproj +0 -106
  198. package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +0 -26
  199. package/libusb/msvc/stress_2013.vcxproj +0 -89
  200. package/libusb/msvc/stress_2013.vcxproj.filters +0 -32
  201. package/libusb/msvc/stress_2015.vcxproj +0 -89
  202. package/libusb/msvc/stress_2015.vcxproj.filters +0 -32
  203. package/libusb/msvc/stress_2017.vcxproj +0 -108
  204. package/libusb/msvc/stress_2017.vcxproj.filters +0 -32
  205. package/libusb/msvc/stress_2019.vcxproj +0 -108
  206. package/libusb/msvc/stress_2019.vcxproj.filters +0 -32
  207. package/libusb/msvc/testlibusb_2013.vcxproj +0 -86
  208. package/libusb/msvc/testlibusb_2013.vcxproj.filters +0 -23
  209. package/libusb/msvc/testlibusb_2015.vcxproj +0 -86
  210. package/libusb/msvc/testlibusb_2015.vcxproj.filters +0 -23
  211. package/libusb/msvc/testlibusb_2017.vcxproj +0 -105
  212. package/libusb/msvc/testlibusb_2017.vcxproj.filters +0 -23
  213. package/libusb/msvc/testlibusb_2019.vcxproj +0 -105
  214. package/libusb/msvc/testlibusb_2019.vcxproj.filters +0 -23
  215. package/libusb/msvc/xusb_2013.vcxproj +0 -86
  216. package/libusb/msvc/xusb_2013.vcxproj.filters +0 -23
  217. package/libusb/msvc/xusb_2015.vcxproj +0 -86
  218. package/libusb/msvc/xusb_2015.vcxproj.filters +0 -23
  219. package/libusb/msvc/xusb_2017.vcxproj +0 -105
  220. package/libusb/msvc/xusb_2017.vcxproj.filters +0 -23
  221. package/libusb/msvc/xusb_2019.vcxproj +0 -105
  222. package/libusb/msvc/xusb_2019.vcxproj.filters +0 -23
  223. package/prebuilds/android-arm/usb.armv7.node +0 -0
  224. package/prebuilds/android-arm64/usb.armv8.node +0 -0
  225. package/prebuilds/darwin-x64+arm64/usb.node +0 -0
  226. package/prebuilds/linux-arm/usb.armv6.node +0 -0
  227. package/prebuilds/linux-arm/usb.armv7.node +0 -0
  228. package/prebuilds/linux-arm64/usb.armv8.node +0 -0
  229. package/prebuilds/linux-ia32/usb.node +0 -0
  230. package/prebuilds/linux-x64/usb.glibc.node +0 -0
  231. package/prebuilds/linux-x64/usb.musl.node +0 -0
  232. package/prebuilds/win32-arm64/usb.node +0 -0
  233. package/prebuilds/win32-ia32/usb.node +0 -0
  234. package/prebuilds/win32-x64/usb.node +0 -0
@@ -1,8 +1,8 @@
1
1
  /* -*- Mode: C; indent-tabs-mode:nil -*- */
2
2
  /*
3
3
  * darwin backend for libusb 1.0
4
- * Copyright © 2008-2021 Nathan Hjelm <hjelmn@cs.unm.edu>
5
- * Copyright © 2019-2021 Google LLC. All rights reserved.
4
+ * Copyright © 2008-2023 Nathan Hjelm <hjelmn@cs.unm.edu>
5
+ * Copyright © 2019-2023 Google LLC. All rights reserved.
6
6
  *
7
7
  * This library is free software; you can redistribute it and/or
8
8
  * modify it under the terms of the GNU Lesser General Public
@@ -32,10 +32,7 @@
32
32
  #include <fcntl.h>
33
33
  #include <sys/sysctl.h>
34
34
 
35
- #include <mach/clock.h>
36
- #include <mach/clock_types.h>
37
- #include <mach/mach_host.h>
38
- #include <mach/mach_port.h>
35
+ #include <mach/mach_time.h>
39
36
 
40
37
  /* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
41
38
  * function. Its use is also conditionalized to only older deployment targets. */
@@ -58,28 +55,34 @@ static int init_count = 0;
58
55
  static const mach_port_t darwin_default_master_port = 0;
59
56
 
60
57
  /* async event thread */
58
+ /* if both this mutex and darwin_cached_devices_mutex are to be acquired then
59
+ darwin_cached_devices_mutex must be acquired first. */
61
60
  static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
62
61
  static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
63
62
 
64
- #if !defined(HAVE_CLOCK_GETTIME)
65
- static clock_serv_t clock_realtime;
66
- static clock_serv_t clock_monotonic;
67
- #endif
68
-
69
63
  #define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1)
70
64
 
71
65
  static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
72
66
  static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
73
67
 
74
- static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
68
+ static usbi_mutex_t darwin_cached_devices_mutex = PTHREAD_MUTEX_INITIALIZER;
75
69
  static struct list_head darwin_cached_devices;
76
70
  static const char *darwin_device_class = "IOUSBDevice";
77
71
 
72
+ uint32_t libusb_testonly_fake_running_version __attribute__ ((visibility ("hidden")));
73
+ int libusb_testonly_using_running_interface_version __attribute__ ((visibility ("hidden")));
74
+ int libusb_testonly_using_running_device_version __attribute__ ((visibility ("hidden")));
75
+ bool libusb_testonly_clear_running_version_cache __attribute__ ((visibility ("hidden")));
76
+
78
77
  #define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
79
78
 
80
79
  /* async event thread */
81
80
  static pthread_t libusb_darwin_at;
82
81
 
82
+ /* protected by libusb_darwin_at_mutex */
83
+ static bool libusb_darwin_at_started;
84
+
85
+ static void darwin_exit(struct libusb_context *ctx);
83
86
  static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len);
84
87
  static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
85
88
  static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
@@ -96,6 +99,186 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
96
99
  static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
97
100
  UInt64 *old_session_id);
98
101
 
102
+ struct darwin_iokit_interface {
103
+ uint32_t min_os_version;
104
+ uint32_t version;
105
+ CFUUIDRef interface_id;
106
+ };
107
+
108
+ static const struct darwin_iokit_interface *get_interface_interface(void) {
109
+ const struct darwin_iokit_interface interfaces[] = {
110
+ #if defined(kIOUSBInterfaceInterfaceID800)
111
+ {
112
+ .min_os_version = 101200,
113
+ .version = 800,
114
+ .interface_id = kIOUSBInterfaceInterfaceID800,
115
+ },
116
+ #endif
117
+ #if defined(kIOUSBInterfaceInterfaceID700)
118
+ {
119
+ .min_os_version = 101000,
120
+ .version = 700,
121
+ .interface_id = kIOUSBInterfaceInterfaceID700,
122
+ },
123
+ #endif
124
+ #if defined(kIOUSBInterfaceInterfaceID650)
125
+ {
126
+ .min_os_version = 100900,
127
+ .version = 650,
128
+ .interface_id = kIOUSBInterfaceInterfaceID650
129
+ },
130
+ #endif
131
+ #if defined(kIOUSBInterfaceInterfaceID550)
132
+ {
133
+ .min_os_version = 100803,
134
+ .version = 550,
135
+ .interface_id = kIOUSBInterfaceInterfaceID550,
136
+ },
137
+ #endif
138
+ #if defined(kIOUSBInterfaceInterfaceID245)
139
+ {
140
+ .min_os_version = 100407,
141
+ .version = 245,
142
+ .interface_id = kIOUSBInterfaceInterfaceID245,
143
+ },
144
+ #endif
145
+ {
146
+ .min_os_version = 100000,
147
+ .version = 220,
148
+ .interface_id = kIOUSBInterfaceInterfaceID220,
149
+ },
150
+ {
151
+ .version = 0,
152
+ },
153
+ };
154
+ static struct darwin_iokit_interface cached_interface = {.version = 0};
155
+ if (libusb_testonly_clear_running_version_cache) {
156
+ memset (&cached_interface, 0, sizeof (cached_interface));
157
+ }
158
+ if (0 == cached_interface.version) {
159
+ uint32_t os_version = get_running_version();
160
+ for (int i = 0 ; interfaces[i].version > 0 ; ++i) {
161
+ if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
162
+ cached_interface = interfaces[i];
163
+ }
164
+ }
165
+
166
+ libusb_testonly_using_running_interface_version = cached_interface.version;
167
+ }
168
+
169
+ return &cached_interface;
170
+ }
171
+
172
+ static CFUUIDRef get_interface_interface_id(void) {
173
+ return get_interface_interface()->interface_id;
174
+ }
175
+
176
+ static int get_interface_interface_version(void) {
177
+ return get_interface_interface()->version;
178
+ }
179
+
180
+ static const struct darwin_iokit_interface *get_device_interface(void) {
181
+ struct darwin_iokit_interface interfaces[] = {
182
+ #if defined(kIOUSBDeviceInterfaceID650)
183
+ {
184
+ .min_os_version = 100900,
185
+ .version = 650,
186
+ .interface_id = kIOUSBDeviceInterfaceID650,
187
+ },
188
+ #endif
189
+ #if defined(kIOUSBDeviceInterfaceID500)
190
+ {
191
+ .min_os_version = 100703,
192
+ .version = 500,
193
+ .interface_id = kIOUSBDeviceInterfaceID500,
194
+ },
195
+ #endif
196
+ #if defined(kIOUSBDeviceInterfaceID320)
197
+ {
198
+ .min_os_version = 100504,
199
+ .version = 320,
200
+ .interface_id = kIOUSBDeviceInterfaceID320,
201
+ },
202
+ #endif
203
+ #if defined(kIOUSBDeviceInterfaceID300)
204
+ {
205
+ .min_os_version = 100500,
206
+ .version = 300,
207
+ .interface_id = kIOUSBDeviceInterfaceID300,
208
+ },
209
+ #endif
210
+ #if defined(kIOUSBDeviceInterfaceID245)
211
+ {
212
+ .min_os_version = 100407,
213
+ .version = 245,
214
+ .interface_id = kIOUSBDeviceInterfaceID245,
215
+ },
216
+ #endif
217
+ {
218
+ .min_os_version = 100000,
219
+ .version = 197,
220
+ .interface_id = kIOUSBDeviceInterfaceID197,
221
+ },
222
+ {
223
+ .version = 0,
224
+ },
225
+ };
226
+ static struct darwin_iokit_interface cached_interface = {.version = 0};
227
+ if (libusb_testonly_clear_running_version_cache) {
228
+ memset (&cached_interface, 0, sizeof (cached_interface));
229
+ }
230
+ if (0 == cached_interface.version) {
231
+ uint32_t os_version = get_running_version();
232
+ for (int i = 0 ; interfaces[i].version > 0 ; ++i) {
233
+ if (os_version >= interfaces[i].min_os_version && cached_interface.min_os_version < interfaces[i].min_os_version) {
234
+ cached_interface = interfaces[i];
235
+ }
236
+ }
237
+ libusb_testonly_using_running_device_version = cached_interface.version;
238
+ }
239
+
240
+ return &cached_interface;
241
+ }
242
+
243
+ static CFUUIDRef get_device_interface_id(void) {
244
+ return get_device_interface()->interface_id;
245
+ }
246
+
247
+ static int get_device_interface_version(void) {
248
+ return get_device_interface()->version;
249
+ }
250
+
251
+ struct darwin_pipe_properties {
252
+ uint8_t number;
253
+ uint8_t direction;
254
+ uint8_t transfer_type;
255
+ uint16_t max_packet_size;
256
+ uint8_t interval;
257
+ };
258
+ typedef struct darwin_pipe_properties darwin_pipe_properties_t;
259
+
260
+ static IOReturn darwin_get_pipe_properties(struct darwin_interface *cInterface, uint8_t pipe, darwin_pipe_properties_t *out) {
261
+ IOReturn kresult;
262
+
263
+ #if (MAX_INTERFACE_VERSION >= 550)
264
+ if (get_interface_interface_version() >= 550) {
265
+ IOUSBEndpointProperties pipe_properties = {.bVersion = kUSBEndpointPropertiesVersion3};
266
+ kresult = (*IOINTERFACE_V(cInterface, 550))->GetPipePropertiesV3 (IOINTERFACE(cInterface), pipe, &pipe_properties);
267
+ if (kIOReturnSuccess == kresult) {
268
+ out->number = pipe_properties.bEndpointNumber;
269
+ out->direction = pipe_properties.bDirection;
270
+ out->transfer_type = pipe_properties.bTransferType;
271
+ out->max_packet_size = pipe_properties.wMaxPacketSize;
272
+ out->interval = pipe_properties.bInterval;
273
+ }
274
+ return kresult;
275
+ }
276
+ #endif
277
+ return (*IOINTERFACE(cInterface))->GetPipeProperties(IOINTERFACE(cInterface), pipe, &out->direction,
278
+ &out->number, &out->transfer_type, &out->max_packet_size,
279
+ &out->interval);
280
+ }
281
+
99
282
  #if defined(ENABLE_LOGGING)
100
283
  static const char *darwin_error_str (IOReturn result) {
101
284
  static char string_buffer[50];
@@ -172,7 +355,72 @@ static enum libusb_error darwin_to_libusb (IOReturn result) {
172
355
  }
173
356
  }
174
357
 
175
- /* this function must be called with the darwin_cached_devices_lock held */
358
+ uint32_t get_running_version(void) {
359
+ if (libusb_testonly_fake_running_version > 0) {
360
+ return libusb_testonly_fake_running_version;
361
+ }
362
+
363
+ int ret;
364
+ #if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1
365
+ char os_version_string[64] = {'\0'};;
366
+ size_t os_version_string_len = sizeof(os_version_string) - 1;
367
+
368
+ /* newer versions of macOS provide a sysctl for the OS version but this is not useful for iOS without
369
+ * code detecting this is iOS and a mapping from iOS -> macOS version. it is still useful to have since
370
+ * it provides the exact macOS version instead of the approximate version (as below). */
371
+ ret = sysctlbyname("kern.osproductversion", os_version_string, &os_version_string_len, NULL, 0);
372
+ if (ret == 0) {
373
+ int major = 10, minor = 0, patch = 0;
374
+ ret = sscanf(os_version_string, "%i.%i.%i", &major, &minor, &patch);
375
+ if (ret < 2) {
376
+ usbi_err (NULL, "could not determine the running OS version, assuming 10.0, kern.osproductversion=%s", os_version_string);
377
+ return 100000;
378
+ }
379
+ return (major * 10000) + (minor * 100) + patch;
380
+ }
381
+ #endif
382
+
383
+ char os_release_string[64] = {'\0'};
384
+ size_t os_release_string_len = sizeof(os_release_string) - 1;
385
+ /* if the version can not be detected libusb assumes 10.0 so ignore any error here */
386
+ ret = sysctlbyname("kern.osrelease", os_release_string, &os_release_string_len, NULL, 0);
387
+ if (ret != 0) {
388
+ usbi_err (NULL, "could not read kern.osrelease, errno=", errno);
389
+ return 100000;
390
+ }
391
+
392
+ int darwin_major = 1, darwin_minor = 0;
393
+ ret = sscanf(os_release_string, "%i.%i", &darwin_major, &darwin_minor);
394
+ if (ret < 1) {
395
+ usbi_err (NULL, "could not determine the running Darwin version, assuming 1.3 (OS X 10.0), kern.osrelease=%s", os_release_string);
396
+ return 100000;
397
+ }
398
+
399
+ int major = 10, minor = 0, patch = 0;
400
+
401
+ if (1 == darwin_major && darwin_minor < 4) {
402
+ /* 10.0.x */
403
+ } else if (darwin_major < 6) {
404
+ /* assume 10.1 for anything in this range */
405
+ minor = 1;
406
+ } else if (darwin_major < 20) {
407
+ /* from macOS 10.2 through 10.15 the minor version can be calculated from the darwin_major by subtracting 4 and
408
+ * the patch level almost always matches darwin_minor. when the darwin_minor does not match the OS X patch level
409
+ * it is usually because Apple did not change it in a particular point release. when darwin_minor is changed it
410
+ * always matches the OS X/macOS patch level. */
411
+ minor = darwin_major - 4;
412
+ patch = darwin_minor;
413
+ } else {
414
+ /* unlikely to be used as kern.osproductversion is available from 10.10 on */
415
+ major = darwin_major - 9;
416
+ minor = darwin_minor;
417
+ /* ignore the patch level in this range */
418
+ }
419
+
420
+ return (major * 10000) + (minor * 100) + patch;
421
+ }
422
+
423
+ /* this function must be called with the darwin_cached_devices_mutex held */
176
424
  static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) {
177
425
  cached_dev->refcount--;
178
426
  /* free the device and remove it from the cache */
@@ -180,7 +428,7 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
180
428
  list_del(&cached_dev->list);
181
429
 
182
430
  if (cached_dev->device) {
183
- (*(cached_dev->device))->Release(cached_dev->device);
431
+ (*cached_dev->device)->Release(cached_dev->device);
184
432
  cached_dev->device = NULL;
185
433
  }
186
434
  IOObjectRelease (cached_dev->service);
@@ -300,12 +548,12 @@ static bool get_ioregistry_value_data (io_service_t service, CFStringRef propert
300
548
  return success;
301
549
  }
302
550
 
303
- static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io_service_t service)
551
+ static int darwin_device_from_service (struct libusb_context *ctx, io_service_t service, usb_device_t* device)
304
552
  {
305
553
  io_cf_plugin_ref_t *plugInInterface = NULL;
306
- usb_device_t **device;
307
554
  IOReturn kresult;
308
555
  SInt32 score;
556
+
309
557
  const int max_retries = 5;
310
558
 
311
559
  /* The IOCreatePlugInInterfaceForService function might consistently return
@@ -325,17 +573,21 @@ static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io
325
573
  nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
326
574
  }
327
575
 
328
- if (kIOReturnSuccess != kresult || !plugInInterface) {
576
+ if (kIOReturnSuccess != kresult) {
329
577
  usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult));
330
- return NULL;
578
+ return darwin_to_libusb(kresult);
579
+ }
580
+ if (!plugInInterface) {
581
+ usbi_dbg (ctx, "could not set up plugin for service");
582
+ return LIBUSB_ERROR_OTHER;
331
583
  }
332
584
 
333
- (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
334
- (LPVOID)&device);
585
+ (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(get_device_interface_id()),
586
+ (LPVOID)device);
335
587
  /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
336
588
  (*plugInInterface)->Release (plugInInterface);
337
589
 
338
- return device;
590
+ return LIBUSB_SUCCESS;
339
591
  }
340
592
 
341
593
  static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
@@ -377,8 +629,6 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
377
629
  struct darwin_cached_device *old_device;
378
630
 
379
631
  io_service_t device;
380
- UInt64 session, locationID;
381
- int ret;
382
632
 
383
633
  usbi_mutex_lock(&active_contexts_lock);
384
634
 
@@ -386,7 +636,9 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
386
636
  bool is_reenumerating = false;
387
637
 
388
638
  /* get the location from the i/o registry */
389
- ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
639
+ UInt64 session = 0;
640
+ bool ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
641
+ UInt32 locationID = 0;
390
642
  (void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
391
643
  IOObjectRelease (device);
392
644
  if (!ret)
@@ -394,18 +646,18 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
394
646
 
395
647
  /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function
396
648
  otherwise no cached device will ever get freed */
397
- usbi_mutex_lock(&darwin_cached_devices_lock);
649
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
398
650
  list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) {
399
651
  if (old_device->session == session) {
400
652
  if (old_device->in_reenumerate) {
401
653
  /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
402
654
  * will deref if needed. */
403
- usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 ", locationID: 0x%" PRIx64,
404
- session, locationID);
655
+ usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64
656
+ ", locationID: 0x%" PRIx32, session, locationID);
405
657
 
406
658
  /* the device object is no longer usable so go ahead and release it */
407
659
  if (old_device->device) {
408
- (*(old_device->device))->Release(old_device->device);
660
+ (*old_device->device)->Release(old_device->device);
409
661
  old_device->device = NULL;
410
662
  }
411
663
 
@@ -418,7 +670,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
418
670
  }
419
671
  }
420
672
 
421
- usbi_mutex_unlock(&darwin_cached_devices_lock);
673
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
422
674
  if (is_reenumerating) {
423
675
  continue;
424
676
  }
@@ -466,8 +718,8 @@ static void darwin_fail_startup(void) {
466
718
  }
467
719
 
468
720
  static void *darwin_event_thread_main (void *arg0) {
721
+ UNUSED(arg0);
469
722
  IOReturn kresult;
470
- struct libusb_context *ctx = (struct libusb_context *)arg0;
471
723
  CFRunLoopRef runloop;
472
724
  CFRunLoopSourceRef libusb_shutdown_cfsource;
473
725
  CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
@@ -495,7 +747,7 @@ static void *darwin_event_thread_main (void *arg0) {
495
747
  io_iterator_t libusb_add_device_iterator;
496
748
 
497
749
  /* ctx must only be used for logging during thread startup */
498
- usbi_dbg (ctx, "creating hotplug event source");
750
+ usbi_dbg (NULL, "creating hotplug event source");
499
751
 
500
752
  runloop = CFRunLoopGetCurrent ();
501
753
  CFRetain (runloop);
@@ -519,7 +771,7 @@ static void *darwin_event_thread_main (void *arg0) {
519
771
  NULL, &libusb_rem_device_iterator);
520
772
 
521
773
  if (kresult != kIOReturnSuccess) {
522
- usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
774
+ usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult));
523
775
  CFRelease (libusb_shutdown_cfsource);
524
776
  CFRelease (runloop);
525
777
  darwin_fail_startup ();
@@ -532,7 +784,7 @@ static void *darwin_event_thread_main (void *arg0) {
532
784
  NULL, &libusb_add_device_iterator);
533
785
 
534
786
  if (kresult != kIOReturnSuccess) {
535
- usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
787
+ usbi_err (NULL, "could not add hotplug event source: %s", darwin_error_str (kresult));
536
788
  CFRelease (libusb_shutdown_cfsource);
537
789
  CFRelease (runloop);
538
790
  darwin_fail_startup ();
@@ -542,7 +794,7 @@ static void *darwin_event_thread_main (void *arg0) {
542
794
  darwin_clear_iterator (libusb_rem_device_iterator);
543
795
  darwin_clear_iterator (libusb_add_device_iterator);
544
796
 
545
- usbi_dbg (ctx, "darwin event thread ready to receive events");
797
+ usbi_dbg (NULL, "darwin event thread ready to receive events");
546
798
 
547
799
  /* signal the main thread that the hotplug runloop has been created. */
548
800
  pthread_mutex_lock (&libusb_darwin_at_mutex);
@@ -582,73 +834,82 @@ static void *darwin_event_thread_main (void *arg0) {
582
834
  pthread_exit (NULL);
583
835
  }
584
836
 
585
- /* cleanup function to destroy cached devices */
837
+ /* cleanup function to destroy cached devices. must be called with a lock on darwin_cached_devices_mutex */
586
838
  static void darwin_cleanup_devices(void) {
587
839
  struct darwin_cached_device *dev, *next;
588
840
 
589
841
  list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
842
+ if (dev->refcount > 1) {
843
+ usbi_err(NULL, "device still referenced at libusb_exit");
844
+ }
590
845
  darwin_deref_cached_device(dev);
591
846
  }
592
847
  }
593
848
 
594
- static int darwin_init(struct libusb_context *ctx) {
595
- bool first_init;
596
- int rc;
849
+ /* must be called with a lock on darwin_cached_devices_mutex */
850
+ static int darwin_first_time_init(void) {
851
+ if (NULL == darwin_cached_devices.next) {
852
+ list_init (&darwin_cached_devices);
853
+ }
597
854
 
598
- first_init = (1 == ++init_count);
855
+ /* cache the interface versions that will be used. as a sanity check verify
856
+ * that the interface versions are non-zero. */
857
+ const struct darwin_iokit_interface *interface_interface = get_interface_interface();
858
+ const struct darwin_iokit_interface *device_interface = get_device_interface();
859
+ if (0 == interface_interface->version || 0 == device_interface->version) {
860
+ usbi_err(NULL, "could not determine the device or interface interface to use with this version "
861
+ "of macOS (or MacOS X), current_running_version = %" PRIu32, get_running_version());
862
+ return LIBUSB_ERROR_OTHER;
863
+ }
599
864
 
600
- do {
601
- if (first_init) {
602
- if (NULL == darwin_cached_devices.next) {
603
- list_init (&darwin_cached_devices);
604
- }
605
- assert(list_empty(&darwin_cached_devices));
606
- #if !defined(HAVE_CLOCK_GETTIME)
607
- /* create the clocks that will be used if clock_gettime() is not available */
608
- host_name_port_t host_self;
609
-
610
- host_self = mach_host_self();
611
- host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
612
- host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
613
- mach_port_deallocate(mach_task_self(), host_self);
614
- #endif
615
- }
865
+ if (!list_empty(&darwin_cached_devices)) {
866
+ usbi_err(NULL, "libusb_device reference not released on last exit. will not continue");
867
+ return LIBUSB_ERROR_OTHER;
868
+ }
616
869
 
617
- rc = darwin_scan_devices (ctx);
618
- if (LIBUSB_SUCCESS != rc)
619
- break;
870
+ int rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, NULL);
871
+ if (0 != rc) {
872
+ usbi_err (NULL, "could not create event thread, error %d", rc);
873
+ return LIBUSB_ERROR_OTHER;
874
+ }
620
875
 
621
- if (first_init) {
622
- rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
623
- if (0 != rc) {
624
- usbi_err (ctx, "could not create event thread, error %d", rc);
625
- rc = LIBUSB_ERROR_OTHER;
626
- break;
627
- }
876
+ pthread_mutex_lock (&libusb_darwin_at_mutex);
877
+ libusb_darwin_at_started = true;
878
+ while (NULL == libusb_darwin_acfl) {
879
+ pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
880
+ }
628
881
 
629
- pthread_mutex_lock (&libusb_darwin_at_mutex);
630
- while (!libusb_darwin_acfl)
631
- pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
632
- if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
633
- libusb_darwin_acfl = NULL;
634
- rc = LIBUSB_ERROR_OTHER;
635
- }
636
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
882
+ if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
883
+ libusb_darwin_acfl = NULL;
884
+ rc = LIBUSB_ERROR_OTHER;
885
+ }
886
+ pthread_mutex_unlock (&libusb_darwin_at_mutex);
637
887
 
638
- if (0 != rc)
639
- pthread_join (libusb_darwin_at, NULL);
888
+ return rc;
889
+ }
890
+
891
+ static int darwin_init_context(struct libusb_context *ctx) {
892
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
893
+
894
+ bool first_init = (1 == ++init_count);
895
+
896
+ if (first_init) {
897
+ int rc = darwin_first_time_init();
898
+ if (LIBUSB_SUCCESS != rc) {
899
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
900
+ return rc;
640
901
  }
641
- } while (0);
902
+ }
903
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
904
+
905
+ return darwin_scan_devices (ctx);
906
+ }
642
907
 
908
+ static int darwin_init(struct libusb_context *ctx) {
909
+ int rc = darwin_init_context(ctx);
643
910
  if (LIBUSB_SUCCESS != rc) {
644
- if (first_init) {
645
- darwin_cleanup_devices ();
646
- #if !defined(HAVE_CLOCK_GETTIME)
647
- mach_port_deallocate(mach_task_self(), clock_realtime);
648
- mach_port_deallocate(mach_task_self(), clock_monotonic);
649
- #endif
650
- }
651
- --init_count;
911
+ /* clean up any allocated resources */
912
+ darwin_exit(ctx);
652
913
  }
653
914
 
654
915
  return rc;
@@ -657,23 +918,26 @@ static int darwin_init(struct libusb_context *ctx) {
657
918
  static void darwin_exit (struct libusb_context *ctx) {
658
919
  UNUSED(ctx);
659
920
 
921
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
660
922
  if (0 == --init_count) {
661
923
  /* stop the event runloop and wait for the thread to terminate. */
662
924
  pthread_mutex_lock (&libusb_darwin_at_mutex);
663
- CFRunLoopSourceSignal (libusb_darwin_acfls);
664
- CFRunLoopWakeUp (libusb_darwin_acfl);
665
- while (libusb_darwin_acfl)
666
- pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
925
+ if (NULL != libusb_darwin_acfls) {
926
+ CFRunLoopSourceSignal (libusb_darwin_acfls);
927
+ CFRunLoopWakeUp (libusb_darwin_acfl);
928
+ while (libusb_darwin_acfl)
929
+ pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
930
+ }
931
+
932
+ if (libusb_darwin_at_started) {
933
+ pthread_join (libusb_darwin_at, NULL);
934
+ libusb_darwin_at_started = false;
935
+ }
667
936
  pthread_mutex_unlock (&libusb_darwin_at_mutex);
668
- pthread_join (libusb_darwin_at, NULL);
669
937
 
670
938
  darwin_cleanup_devices ();
671
-
672
- #if !defined(HAVE_CLOCK_GETTIME)
673
- mach_port_deallocate(mach_task_self(), clock_realtime);
674
- mach_port_deallocate(mach_task_self(), clock_monotonic);
675
- #endif
676
939
  }
940
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
677
941
  }
678
942
 
679
943
  static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
@@ -683,12 +947,12 @@ static int get_configuration_index (struct libusb_device *dev, UInt8 config_valu
683
947
  IOReturn kresult;
684
948
 
685
949
  /* is there a simpler way to determine the index? */
686
- kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig);
950
+ kresult = (*priv->device)->GetNumberOfConfigurations (priv->device, &numConfig);
687
951
  if (kresult != kIOReturnSuccess)
688
952
  return darwin_to_libusb (kresult);
689
953
 
690
954
  for (i = 0 ; i < numConfig ; i++) {
691
- (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc);
955
+ (*priv->device)->GetConfigurationDescriptorPtr (priv->device, i, &desc);
692
956
 
693
957
  if (desc->bConfigurationValue == config_value)
694
958
  return i;
@@ -740,7 +1004,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
740
1004
 
741
1005
  /* check whether the os has configured the device */
742
1006
  static enum libusb_error darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
743
- usb_device_t **darwin_device = dev->device;
1007
+ usb_device_t darwin_device = dev->device;
744
1008
 
745
1009
  IOUSBConfigurationDescriptorPtr configDesc;
746
1010
  IOUSBFindInterfaceRequest request;
@@ -776,7 +1040,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
776
1040
  request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
777
1041
  request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
778
1042
 
779
- kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
1043
+ kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
780
1044
  if (kresult != kIOReturnSuccess)
781
1045
  return darwin_to_libusb (kresult);
782
1046
 
@@ -805,7 +1069,7 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
805
1069
  return LIBUSB_SUCCESS;
806
1070
  }
807
1071
 
808
- static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
1072
+ static IOReturn darwin_request_descriptor (usb_device_t device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
809
1073
  IOUSBDevRequestTO req;
810
1074
 
811
1075
  assert(buffer_size <= UINT16_MAX);
@@ -826,7 +1090,7 @@ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UI
826
1090
  }
827
1091
 
828
1092
  static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
829
- usb_device_t **device = dev->device;
1093
+ usb_device_t device = dev->device;
830
1094
  int retries = 1;
831
1095
  long delay = 30000; // microseconds
832
1096
  int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
@@ -877,15 +1141,17 @@ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *
877
1141
 
878
1142
  if (kIOReturnSuccess != ret && is_open && try_unsuspend) {
879
1143
  /* device may be suspended. unsuspend it and try again */
880
- #if DeviceVersion >= 320
881
- UInt32 info = 0;
1144
+ #if MAX_DEVICE_VERSION >= 320
1145
+ if (get_device_interface_version() >= 320) {
1146
+ UInt32 info = 0;
882
1147
 
883
- /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */
884
- (void)(*device)->GetUSBDeviceInformation (device, &info);
1148
+ /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */
1149
+ (void)(*IODEVICE_V(device, 320))->GetUSBDeviceInformation (device, &info);
885
1150
 
886
- /* note that the device was suspended */
887
- if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
888
- try_unsuspend = 1;
1151
+ /* note that the device was suspended */
1152
+ if (info & (1U << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
1153
+ try_unsuspend = 1;
1154
+ }
889
1155
  #endif
890
1156
 
891
1157
  if (try_unsuspend) {
@@ -998,7 +1264,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
998
1264
  UInt64 sessionID = 0, parent_sessionID = 0;
999
1265
  UInt32 locationID = 0;
1000
1266
  enum libusb_error ret = LIBUSB_SUCCESS;
1001
- usb_device_t **device;
1267
+ usb_device_t device;
1002
1268
  UInt8 port = 0;
1003
1269
 
1004
1270
  /* assuming sessionID != 0 normally (never seen it be 0) */
@@ -1018,10 +1284,10 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
1018
1284
  usbi_dbg(ctx, "parent sessionID: 0x%" PRIx64, parent_sessionID);
1019
1285
  }
1020
1286
 
1021
- usbi_mutex_lock(&darwin_cached_devices_lock);
1287
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
1022
1288
  do {
1023
1289
  list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
1024
- usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
1290
+ usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32 " against cached device with sessionID/locationID 0x%" PRIx64 "/0x%" PRIx32,
1025
1291
  sessionID, locationID, new_device->session, new_device->location);
1026
1292
  if (new_device->location == locationID && new_device->in_reenumerate) {
1027
1293
  usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
@@ -1041,9 +1307,8 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
1041
1307
 
1042
1308
  usbi_dbg(ctx, "caching new device with sessionID 0x%" PRIx64, sessionID);
1043
1309
 
1044
- device = darwin_device_from_service (ctx, service);
1045
- if (!device) {
1046
- ret = LIBUSB_ERROR_NO_DEVICE;
1310
+ ret = darwin_device_from_service (ctx, service, &device);
1311
+ if (LIBUSB_SUCCESS != ret) {
1047
1312
  break;
1048
1313
  }
1049
1314
 
@@ -1094,7 +1359,7 @@ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io
1094
1359
  }
1095
1360
  } while (0);
1096
1361
 
1097
- usbi_mutex_unlock(&darwin_cached_devices_lock);
1362
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
1098
1363
 
1099
1364
  return ret;
1100
1365
  }
@@ -1158,7 +1423,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1158
1423
  dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
1159
1424
  }
1160
1425
 
1161
- (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
1426
+ (*priv->dev->device)->GetDeviceSpeed (priv->dev->device, &devSpeed);
1162
1427
 
1163
1428
  switch (devSpeed) {
1164
1429
  case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
@@ -1227,7 +1492,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
1227
1492
 
1228
1493
  if (0 == dpriv->open_count) {
1229
1494
  /* try to open the device */
1230
- kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device);
1495
+ kresult = (*dpriv->device)->USBDeviceOpenSeize (dpriv->device);
1231
1496
  if (kresult != kIOReturnSuccess) {
1232
1497
  usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult));
1233
1498
 
@@ -1242,12 +1507,13 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
1242
1507
  }
1243
1508
 
1244
1509
  /* create async event source */
1245
- kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource);
1510
+ kresult = (*dpriv->device)->CreateDeviceAsyncEventSource (dpriv->device,
1511
+ &priv->cfSource);
1246
1512
  if (kresult != kIOReturnSuccess) {
1247
1513
  usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult));
1248
1514
 
1249
1515
  if (priv->is_open) {
1250
- (*(dpriv->device))->USBDeviceClose (dpriv->device);
1516
+ (*dpriv->device)->USBDeviceClose (dpriv->device);
1251
1517
  }
1252
1518
 
1253
1519
  priv->is_open = false;
@@ -1303,7 +1569,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
1303
1569
 
1304
1570
  if (priv->is_open) {
1305
1571
  /* close the device */
1306
- kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
1572
+ kresult = (*dpriv->device)->USBDeviceClose(dpriv->device);
1307
1573
  if (kresult != kIOReturnSuccess) {
1308
1574
  /* Log the fact that we had a problem closing the file, however failing a
1309
1575
  * close isn't really an error, so return success anyway */
@@ -1335,7 +1601,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
1335
1601
  if (dev_handle->claimed_interfaces & (1U << i))
1336
1602
  darwin_release_interface (dev_handle, i);
1337
1603
 
1338
- kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, (UInt8)config);
1604
+ kresult = (*dpriv->device)->SetConfiguration (dpriv->device, (UInt8)config);
1339
1605
  if (kresult != kIOReturnSuccess)
1340
1606
  return darwin_to_libusb (kresult);
1341
1607
 
@@ -1349,7 +1615,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
1349
1615
  return LIBUSB_SUCCESS;
1350
1616
  }
1351
1617
 
1352
- static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
1618
+ static IOReturn darwin_get_interface (usb_device_t darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
1353
1619
  IOUSBFindInterfaceRequest request;
1354
1620
  IOReturn kresult;
1355
1621
  io_iterator_t interface_iterator;
@@ -1364,7 +1630,7 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc,
1364
1630
  request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
1365
1631
  request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
1366
1632
 
1367
- kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
1633
+ kresult = (*darwin_device)->CreateInterfaceIterator(darwin_device, &request, &interface_iterator);
1368
1634
  if (kresult != kIOReturnSuccess)
1369
1635
  return kresult;
1370
1636
 
@@ -1386,29 +1652,34 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc,
1386
1652
  return kIOReturnSuccess;
1387
1653
  }
1388
1654
 
1655
+ static const struct libusb_interface_descriptor *get_interface_descriptor_by_number(struct libusb_device_handle *dev_handle, struct libusb_config_descriptor *conf_desc, int iface, uint8_t altsetting)
1656
+ {
1657
+ int i;
1658
+
1659
+ for (i = 0; i < conf_desc->bNumInterfaces; i++) {
1660
+ if (altsetting < conf_desc->interface[i].num_altsetting && conf_desc->interface[i].altsetting[altsetting].bInterfaceNumber == iface) {
1661
+ return &conf_desc->interface[i].altsetting[altsetting];
1662
+ }
1663
+ }
1664
+
1665
+ usbi_err(HANDLE_CTX(dev_handle), "interface %d with altsetting %d not found for device", iface, (int)altsetting);
1666
+ return NULL;
1667
+ }
1668
+
1389
1669
  static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, uint8_t iface) {
1390
1670
  struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1391
1671
 
1392
1672
  /* current interface */
1393
1673
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1394
- #if InterfaceVersion >= 550
1395
- IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
1396
- #else
1397
- UInt8 dont_care1, dont_care3;
1398
- UInt16 dont_care2;
1399
- #endif
1400
-
1401
1674
  IOReturn kresult;
1402
-
1403
- UInt8 numep, direction, number;
1675
+ uint8_t numep;
1404
1676
  int rc;
1405
1677
  struct libusb_context *ctx = HANDLE_CTX (dev_handle);
1406
1678
 
1407
-
1408
1679
  usbi_dbg (ctx, "building table of endpoints.");
1409
1680
 
1410
1681
  /* retrieve the total number of endpoints on this interface */
1411
- kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
1682
+ kresult = (*IOINTERFACE(cInterface))->GetNumEndpoints(IOINTERFACE(cInterface), &numep);
1412
1683
  if (kresult != kIOReturnSuccess) {
1413
1684
  usbi_err (ctx, "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
1414
1685
  return darwin_to_libusb (kresult);
@@ -1416,21 +1687,16 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
1416
1687
 
1417
1688
  /* iterate through pipe references */
1418
1689
  for (UInt8 i = 1 ; i <= numep ; i++) {
1419
- #if InterfaceVersion >= 550
1420
- kresult = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, i, &pipeProperties);
1421
- number = pipeProperties.bEndpointNumber;
1422
- direction = pipeProperties.bDirection;
1423
- #else
1424
- kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
1425
- &dont_care2, &dont_care3);
1426
- #endif
1690
+ darwin_pipe_properties_t pipe_properties;
1691
+ kresult = darwin_get_pipe_properties(cInterface, i, &pipe_properties);
1427
1692
  if (kresult != kIOReturnSuccess) {
1428
1693
  /* probably a buggy device. try to get the endpoint address from the descriptors */
1429
1694
  struct libusb_config_descriptor *config;
1695
+ const struct libusb_interface_descriptor *if_desc;
1430
1696
  const struct libusb_endpoint_descriptor *endpoint_desc;
1431
1697
  UInt8 alt_setting;
1432
1698
 
1433
- kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting);
1699
+ kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), &alt_setting);
1434
1700
  if (kresult != kIOReturnSuccess) {
1435
1701
  usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface");
1436
1702
  return darwin_to_libusb (kresult);
@@ -1441,15 +1707,19 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
1441
1707
  return rc;
1442
1708
  }
1443
1709
 
1444
- if (iface >= config->bNumInterfaces) {
1445
- usbi_err (HANDLE_CTX (dev_handle), "interface %d out of range for device", iface);
1710
+ if_desc = get_interface_descriptor_by_number (dev_handle, config, iface, alt_setting);
1711
+ if (if_desc == NULL) {
1712
+ libusb_free_config_descriptor (config);
1446
1713
  return LIBUSB_ERROR_NOT_FOUND;
1447
1714
  }
1448
- endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1;
1715
+
1716
+ endpoint_desc = if_desc->endpoint + i - 1;
1449
1717
 
1450
1718
  cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress;
1719
+ libusb_free_config_descriptor (config);
1451
1720
  } else {
1452
- cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
1721
+ cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == pipe_properties.direction) << kUSBRqDirnShift) |
1722
+ (pipe_properties.number & LIBUSB_ENDPOINT_ADDRESS_MASK));
1453
1723
  }
1454
1724
 
1455
1725
  usbi_dbg (ctx, "interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
@@ -1521,18 +1791,22 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
1521
1791
 
1522
1792
  /* Do the actual claim */
1523
1793
  kresult = (*plugInInterface)->QueryInterface(plugInInterface,
1524
- CFUUIDGetUUIDBytes(InterfaceInterfaceID),
1525
- (LPVOID)&cInterface->interface);
1794
+ CFUUIDGetUUIDBytes(get_interface_interface_id()),
1795
+ (LPVOID)&IOINTERFACE(cInterface));
1526
1796
  /* We no longer need the intermediate plug-in */
1527
1797
  /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
1528
1798
  (*plugInInterface)->Release (plugInInterface);
1529
- if (kresult != kIOReturnSuccess || !cInterface->interface) {
1799
+ if (kresult != kIOReturnSuccess) {
1530
1800
  usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult));
1531
1801
  return darwin_to_libusb (kresult);
1532
1802
  }
1803
+ if (!IOINTERFACE(cInterface)) {
1804
+ usbi_err (ctx, "QueryInterface: returned null interface");
1805
+ return LIBUSB_ERROR_OTHER;
1806
+ }
1533
1807
 
1534
1808
  /* claim the interface */
1535
- kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
1809
+ kresult = (*IOINTERFACE(cInterface))->USBInterfaceOpen(IOINTERFACE(cInterface));
1536
1810
  if (kresult != kIOReturnSuccess) {
1537
1811
  usbi_info (ctx, "USBInterfaceOpen: %s", darwin_error_str(kresult));
1538
1812
  return darwin_to_libusb (kresult);
@@ -1550,7 +1824,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8
1550
1824
  cInterface->cfSource = NULL;
1551
1825
 
1552
1826
  /* create async event source */
1553
- kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource);
1827
+ kresult = (*IOINTERFACE(cInterface))->CreateInterfaceAsyncEventSource (IOINTERFACE(cInterface), &cInterface->cfSource);
1554
1828
  if (kresult != kIOReturnSuccess) {
1555
1829
  usbi_err (ctx, "could not create async event source");
1556
1830
 
@@ -1576,8 +1850,9 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
1576
1850
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1577
1851
 
1578
1852
  /* Check to see if an interface is open */
1579
- if (!cInterface->interface)
1853
+ if (!IOINTERFACE(cInterface)) {
1580
1854
  return LIBUSB_SUCCESS;
1855
+ }
1581
1856
 
1582
1857
  /* clean up endpoint data */
1583
1858
  cInterface->num_endpoints = 0;
@@ -1589,15 +1864,15 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uin
1589
1864
  cInterface->cfSource = NULL;
1590
1865
  }
1591
1866
 
1592
- kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
1867
+ kresult = (*IOINTERFACE(cInterface))->USBInterfaceClose(IOINTERFACE(cInterface));
1593
1868
  if (kresult != kIOReturnSuccess)
1594
1869
  usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult));
1595
1870
 
1596
- kresult = (*(cInterface->interface))->Release(cInterface->interface);
1871
+ kresult = (*IOINTERFACE(cInterface))->Release(IOINTERFACE(cInterface));
1597
1872
  if (kresult != kIOReturnSuccess)
1598
1873
  usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
1599
1874
 
1600
- cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL;
1875
+ IOINTERFACE(cInterface) = NULL;
1601
1876
 
1602
1877
  return darwin_to_libusb (kresult);
1603
1878
  }
@@ -1607,7 +1882,7 @@ static int check_alt_setting_and_clear_halt(struct libusb_device_handle *dev_han
1607
1882
  IOReturn kresult;
1608
1883
  uint8_t current_alt_setting;
1609
1884
 
1610
- kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &current_alt_setting);
1885
+ kresult = (*IOINTERFACE(cInterface))->GetAlternateSetting (IOINTERFACE(cInterface), &current_alt_setting);
1611
1886
  if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) {
1612
1887
  return LIBUSB_ERROR_PIPE;
1613
1888
  }
@@ -1634,10 +1909,11 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
1634
1909
  /* current interface */
1635
1910
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1636
1911
 
1637
- if (!cInterface->interface)
1912
+ if (!IOINTERFACE(cInterface)) {
1638
1913
  return LIBUSB_ERROR_NO_DEVICE;
1914
+ }
1639
1915
 
1640
- kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting);
1916
+ kresult = (*IOINTERFACE(cInterface))->SetAlternateInterface (IOINTERFACE(cInterface), altsetting);
1641
1917
  if (kresult == kIOReturnSuccess) {
1642
1918
  /* update the list of endpoints */
1643
1919
  ret = get_endpoints (dev_handle, iface);
@@ -1689,7 +1965,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1689
1965
  }
1690
1966
 
1691
1967
  /* newer versions of darwin support clearing additional bits on the device's endpoint */
1692
- kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
1968
+ kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef);
1693
1969
  if (kresult != kIOReturnSuccess)
1694
1970
  usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
1695
1971
 
@@ -1783,12 +2059,12 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
1783
2059
  cached_configurations = alloca (sizeof (*cached_configurations) * descriptor.bNumConfigurations);
1784
2060
 
1785
2061
  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1786
- (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
2062
+ (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1787
2063
  memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
1788
2064
  }
1789
2065
 
1790
2066
  /* if we need to release capture */
1791
- if (HAS_CAPTURE_DEVICE()) {
2067
+ if (get_running_version() >= 101000) {
1792
2068
  if (capture) {
1793
2069
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
1794
2070
  options |= kUSBReEnumerateCaptureDeviceMask;
@@ -1799,7 +2075,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
1799
2075
  }
1800
2076
 
1801
2077
  /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
1802
- kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, options);
2078
+ kresult = (*dpriv->device)->USBDeviceReEnumerate (dpriv->device, options);
1803
2079
  if (kresult != kIOReturnSuccess) {
1804
2080
  usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
1805
2081
  dpriv->in_reenumerate = false;
@@ -1844,7 +2120,7 @@ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, b
1844
2120
  }
1845
2121
 
1846
2122
  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1847
- (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
2123
+ (void) (*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1848
2124
  if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
1849
2125
  usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
1850
2126
  return LIBUSB_ERROR_NOT_FOUND;
@@ -1864,7 +2140,7 @@ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
1864
2140
  #if !defined(TARGET_OS_OSX) || TARGET_OS_OSX == 1
1865
2141
  if (dpriv->capture_count > 0) {
1866
2142
  /* we have to use ResetDevice as USBDeviceReEnumerate() loses the authorization for capture */
1867
- kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
2143
+ kresult = (*dpriv->device)->ResetDevice (dpriv->device);
1868
2144
  ret = darwin_to_libusb (kresult);
1869
2145
  } else {
1870
2146
  ret = darwin_reenumerate_device (dev_handle, false);
@@ -1945,10 +2221,10 @@ static void darwin_destroy_device(struct libusb_device *dev) {
1945
2221
 
1946
2222
  if (dpriv->dev) {
1947
2223
  /* need to hold the lock in case this is the last reference to the device */
1948
- usbi_mutex_lock(&darwin_cached_devices_lock);
2224
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
1949
2225
  darwin_deref_cached_device (dpriv->dev);
1950
2226
  dpriv->dev = NULL;
1951
- usbi_mutex_unlock(&darwin_cached_devices_lock);
2227
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
1952
2228
  }
1953
2229
  }
1954
2230
 
@@ -1956,17 +2232,10 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1956
2232
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1957
2233
 
1958
2234
  IOReturn ret;
1959
- uint8_t transferType;
1960
2235
  uint8_t pipeRef;
1961
- uint16_t maxPacketSize;
1962
2236
 
1963
2237
  struct darwin_interface *cInterface;
1964
- #if InterfaceVersion >= 550
1965
- IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
1966
- #else
1967
- /* None of the values below are used in libusb for bulk transfers */
1968
- uint8_t direction, number, interval;
1969
- #endif
2238
+ darwin_pipe_properties_t pipe_properties;
1970
2239
 
1971
2240
  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
1972
2241
  usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
@@ -1974,47 +2243,38 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1974
2243
  return LIBUSB_ERROR_NOT_FOUND;
1975
2244
  }
1976
2245
 
1977
- #if InterfaceVersion >= 550
1978
- ret = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties);
1979
-
1980
- transferType = pipeProperties.bTransferType;
1981
- maxPacketSize = pipeProperties.wMaxPacketSize;
1982
- #else
1983
- ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
1984
- &transferType, &maxPacketSize, &interval);
1985
- #endif
1986
-
1987
- if (ret) {
2246
+ ret = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties);
2247
+ if (kIOReturnSuccess != ret) {
1988
2248
  usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
1989
2249
  darwin_error_str(ret), ret);
1990
2250
  return darwin_to_libusb (ret);
1991
2251
  }
1992
2252
 
1993
- if (0 != (transfer->length % maxPacketSize)) {
2253
+ if (0 != (transfer->length % pipe_properties.max_packet_size)) {
1994
2254
  /* do not need a zero packet */
1995
2255
  transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET;
1996
2256
  }
1997
2257
 
1998
2258
  /* submit the request */
1999
2259
  /* timeouts are unavailable on interrupt endpoints */
2000
- if (transferType == kUSBInterrupt) {
2260
+ if (pipe_properties.transfer_type == kUSBInterrupt) {
2001
2261
  if (IS_XFERIN(transfer))
2002
- ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
2003
- (UInt32)transfer->length, darwin_async_io_callback, itransfer);
2262
+ ret = (*IOINTERFACE(cInterface))->ReadPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
2263
+ (UInt32)transfer->length, darwin_async_io_callback, itransfer);
2004
2264
  else
2005
- ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
2006
- (UInt32)transfer->length, darwin_async_io_callback, itransfer);
2265
+ ret = (*IOINTERFACE(cInterface))->WritePipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
2266
+ (UInt32)transfer->length, darwin_async_io_callback, itransfer);
2007
2267
  } else {
2008
2268
  itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
2009
2269
 
2010
2270
  if (IS_XFERIN(transfer))
2011
- ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
2012
- (UInt32)transfer->length, transfer->timeout, transfer->timeout,
2013
- darwin_async_io_callback, itransfer);
2271
+ ret = (*IOINTERFACE(cInterface))->ReadPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
2272
+ (UInt32)transfer->length, transfer->timeout, transfer->timeout,
2273
+ darwin_async_io_callback, itransfer);
2014
2274
  else
2015
- ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
2016
- (UInt32)transfer->length, transfer->timeout, transfer->timeout,
2017
- darwin_async_io_callback, itransfer);
2275
+ ret = (*IOINTERFACE(cInterface))->WritePipeAsyncTO(IOINTERFACE(cInterface), pipeRef, transfer->buffer,
2276
+ (UInt32)transfer->length, transfer->timeout, transfer->timeout,
2277
+ darwin_async_io_callback, itransfer);
2018
2278
  }
2019
2279
 
2020
2280
  if (ret)
@@ -2024,7 +2284,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
2024
2284
  return darwin_to_libusb (ret);
2025
2285
  }
2026
2286
 
2027
- #if InterfaceVersion >= 550
2287
+ #if MAX_INTERFACE_VERSION >= 550
2028
2288
  static int submit_stream_transfer(struct usbi_transfer *itransfer) {
2029
2289
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2030
2290
  struct darwin_interface *cInterface;
@@ -2037,16 +2297,22 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
2037
2297
  return LIBUSB_ERROR_NOT_FOUND;
2038
2298
  }
2039
2299
 
2300
+ if (get_interface_interface_version() < 550) {
2301
+ usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version %d does not support bulk stream transfers",
2302
+ get_interface_interface_version());
2303
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2304
+ }
2305
+
2040
2306
  itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
2041
2307
 
2042
2308
  if (IS_XFERIN(transfer))
2043
- ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
2044
- transfer->buffer, (UInt32)transfer->length, transfer->timeout,
2045
- transfer->timeout, darwin_async_io_callback, itransfer);
2309
+ ret = (*IOINTERFACE_V(cInterface, 550))->ReadStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id,
2310
+ transfer->buffer, (UInt32)transfer->length, transfer->timeout,
2311
+ transfer->timeout, darwin_async_io_callback, itransfer);
2046
2312
  else
2047
- ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id,
2048
- transfer->buffer, (UInt32)transfer->length, transfer->timeout,
2049
- transfer->timeout, darwin_async_io_callback, itransfer);
2313
+ ret = (*IOINTERFACE_V(cInterface, 550))->WriteStreamsPipeAsyncTO(IOINTERFACE(cInterface), pipeRef, itransfer->stream_id,
2314
+ transfer->buffer, (UInt32)transfer->length, transfer->timeout,
2315
+ transfer->timeout, darwin_async_io_callback, itransfer);
2050
2316
 
2051
2317
  if (ret)
2052
2318
  usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
@@ -2061,18 +2327,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
2061
2327
  struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2062
2328
 
2063
2329
  IOReturn kresult;
2064
- uint8_t pipeRef, interval;
2330
+ uint8_t pipeRef;
2065
2331
  UInt64 frame;
2066
2332
  AbsoluteTime atTime;
2067
2333
  int i;
2068
- #if InterfaceVersion >= 550
2069
- IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
2070
- #else
2071
- /* None of the values below are used in libusb for iso transfers */
2072
- uint8_t direction, number, transferType;
2073
- uint16_t maxPacketSize;
2074
- #endif
2075
-
2334
+ darwin_pipe_properties_t pipe_properties;
2076
2335
  struct darwin_interface *cInterface;
2077
2336
 
2078
2337
  /* construct an array of IOUSBIsocFrames, reuse the old one if the sizes are the same */
@@ -2103,13 +2362,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
2103
2362
  }
2104
2363
 
2105
2364
  /* determine the properties of this endpoint and the speed of the device */
2106
- #if InterfaceVersion >= 550
2107
- kresult = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties);
2108
- interval = pipeProperties.bInterval;
2109
- #else
2110
- kresult = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
2111
- &transferType, &maxPacketSize, &interval);
2112
- #endif
2365
+ kresult = darwin_get_pipe_properties(cInterface, pipeRef, &pipe_properties);
2113
2366
  if (kresult != kIOReturnSuccess) {
2114
2367
  usbi_err (TRANSFER_CTX (transfer), "failed to get pipe properties: %d", kresult);
2115
2368
  free(tpriv->isoc_framelist);
@@ -2119,7 +2372,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
2119
2372
  }
2120
2373
 
2121
2374
  /* Last but not least we need the bus frame number */
2122
- kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
2375
+ kresult = (*IOINTERFACE(cInterface))->GetBusFrameNumber(IOINTERFACE(cInterface), &frame, &atTime);
2123
2376
  if (kresult != kIOReturnSuccess) {
2124
2377
  usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult);
2125
2378
  free(tpriv->isoc_framelist);
@@ -2136,20 +2389,20 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
2136
2389
 
2137
2390
  /* submit the request */
2138
2391
  if (IS_XFERIN(transfer))
2139
- kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
2140
- (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
2141
- itransfer);
2392
+ kresult = (*IOINTERFACE(cInterface))->ReadIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame,
2393
+ (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
2394
+ itransfer);
2142
2395
  else
2143
- kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
2144
- (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
2145
- itransfer);
2396
+ kresult = (*IOINTERFACE(cInterface))->WriteIsochPipeAsync(IOINTERFACE(cInterface), pipeRef, transfer->buffer, frame,
2397
+ (UInt32)transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
2398
+ itransfer);
2146
2399
 
2147
2400
  if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
2148
2401
  /* Full speed */
2149
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1));
2402
+ cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1));
2150
2403
  else
2151
2404
  /* High/super speed */
2152
- cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (interval - 1)) / 8;
2405
+ cInterface->frames[transfer->endpoint] = frame + (UInt32)transfer->num_iso_packets * (1U << (pipe_properties.interval - 1)) / 8;
2153
2406
 
2154
2407
  if (kresult != kIOReturnSuccess) {
2155
2408
  usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
@@ -2197,10 +2450,11 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
2197
2450
  return LIBUSB_ERROR_NOT_FOUND;
2198
2451
  }
2199
2452
 
2200
- kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer);
2453
+ kresult = (*IOINTERFACE(cInterface))->ControlRequestAsyncTO (IOINTERFACE(cInterface), pipeRef,
2454
+ &(tpriv->req), darwin_async_io_callback, itransfer);
2201
2455
  } else
2202
2456
  /* control request on endpoint 0 */
2203
- kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
2457
+ kresult = (*dpriv->device)->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
2204
2458
 
2205
2459
  if (kresult != kIOReturnSuccess)
2206
2460
  usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult));
@@ -2220,7 +2474,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) {
2220
2474
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2221
2475
  return submit_iso_transfer(itransfer);
2222
2476
  case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2223
- #if InterfaceVersion >= 550
2477
+ #if MAX_INTERFACE_VERSION >= 550
2224
2478
  return submit_stream_transfer(itransfer);
2225
2479
  #else
2226
2480
  usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers");
@@ -2239,10 +2493,11 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) {
2239
2493
 
2240
2494
  usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe");
2241
2495
 
2242
- if (!dpriv->device)
2496
+ if (!dpriv->device) {
2243
2497
  return LIBUSB_ERROR_NO_DEVICE;
2498
+ }
2244
2499
 
2245
- kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device);
2500
+ kresult = (*dpriv->device)->USBDeviceAbortPipeZero (dpriv->device);
2246
2501
 
2247
2502
  return darwin_to_libusb (kresult);
2248
2503
  }
@@ -2262,23 +2517,29 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
2262
2517
  return LIBUSB_ERROR_NOT_FOUND;
2263
2518
  }
2264
2519
 
2265
- if (!dpriv->device)
2520
+ if (!dpriv->device) {
2266
2521
  return LIBUSB_ERROR_NO_DEVICE;
2522
+ }
2267
2523
 
2268
2524
  usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef);
2269
2525
 
2270
2526
  /* abort transactions */
2271
- #if InterfaceVersion >= 550
2272
- if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type)
2273
- (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id);
2274
- else
2527
+ #if MAX_INTERFACE_VERSION >= 550
2528
+ if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type && get_interface_interface_version() >= 550) {
2529
+ kresult = (*IOINTERFACE_V(cInterface, 550))->AbortStreamsPipe (IOINTERFACE(cInterface), pipeRef, itransfer->stream_id);
2530
+ } else
2275
2531
  #endif
2276
- (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef);
2532
+ {
2533
+ kresult = (*IOINTERFACE(cInterface))->AbortPipe (IOINTERFACE(cInterface), pipeRef);
2534
+ }
2277
2535
 
2278
- usbi_dbg (ctx, "calling clear pipe stall to clear the data toggle bit");
2279
2536
 
2280
- /* newer versions of darwin support clearing additional bits on the device's endpoint */
2281
- kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
2537
+ if (get_interface_interface_version() <= 245) {
2538
+ /* with older releases of IOUSBFamily the OS always clears the host side data toggle. for
2539
+ consistency also clear the data toggle on the device. */
2540
+ usbi_dbg (ctx, "calling ClearPipeStallBothEnds to clear the data toggle bit");
2541
+ kresult = (*IOINTERFACE(cInterface))->ClearPipeStallBothEnds(IOINTERFACE(cInterface), pipeRef);
2542
+ }
2282
2543
 
2283
2544
  return darwin_to_libusb (kresult);
2284
2545
  }
@@ -2313,7 +2574,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
2313
2574
 
2314
2575
  (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface);
2315
2576
 
2316
- (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
2577
+ (*IOINTERFACE(cInterface))->WritePipe (IOINTERFACE(cInterface), pipeRef, transfer->buffer, 0);
2317
2578
  }
2318
2579
 
2319
2580
  tpriv->result = result;
@@ -2389,29 +2650,38 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
2389
2650
  return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
2390
2651
  }
2391
2652
 
2392
- #if !defined(HAVE_CLOCK_GETTIME)
2393
2653
  void usbi_get_monotonic_time(struct timespec *tp) {
2394
- mach_timespec_t sys_time;
2654
+ /* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */
2655
+ #if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
2656
+ clock_gettime(CLOCK_MONOTONIC, tp);
2657
+ #else
2658
+ mach_timebase_info_data_t machTimeBaseInfo;
2659
+ mach_timebase_info(&machTimeBaseInfo);
2395
2660
 
2396
- /* use system boot time as reference for the monotonic clock */
2397
- clock_get_time (clock_monotonic, &sys_time);
2661
+ uint64_t uptime = mach_absolute_time();
2662
+ uint64_t uptimeNano = uptime * machTimeBaseInfo.numer / machTimeBaseInfo.denom;
2398
2663
 
2399
- tp->tv_sec = sys_time.tv_sec;
2400
- tp->tv_nsec = sys_time.tv_nsec;
2664
+ uint64_t uptimeSeconds = uptimeNano / NSEC_PER_SEC;
2665
+ uint64_t uptimeNanoRemainder = uptimeNano - (uptimeSeconds * NSEC_PER_SEC);
2666
+
2667
+ tp->tv_sec = uptimeSeconds;
2668
+ tp->tv_nsec = uptimeNanoRemainder;
2669
+ #endif
2401
2670
  }
2402
2671
 
2403
2672
  void usbi_get_real_time(struct timespec *tp) {
2404
- mach_timespec_t sys_time;
2405
-
2406
- /* CLOCK_REALTIME represents time since the epoch */
2407
- clock_get_time (clock_realtime, &sys_time);
2408
-
2409
- tp->tv_sec = sys_time.tv_sec;
2410
- tp->tv_nsec = sys_time.tv_nsec;
2411
- }
2673
+ /* Check if the SDK is new enough to declare clock_gettime(), and the deployment target is at least 10.12. */
2674
+ #if ((MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
2675
+ clock_gettime(CLOCK_REALTIME, tp);
2676
+ #else
2677
+ struct timeval tv;
2678
+ gettimeofday(&tv, NULL);
2679
+ tp->tv_sec = tv.tv_sec;
2680
+ tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
2412
2681
  #endif
2682
+ }
2413
2683
 
2414
- #if InterfaceVersion >= 550
2684
+ #if MAX_INTERFACE_VERSION >= 550
2415
2685
  static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
2416
2686
  int num_endpoints) {
2417
2687
  struct darwin_interface *cInterface;
@@ -2425,7 +2695,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
2425
2695
  return rc;
2426
2696
  }
2427
2697
 
2428
- (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
2698
+ (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
2429
2699
  if (num_streams > supportsStreams)
2430
2700
  num_streams = supportsStreams;
2431
2701
  }
@@ -2438,7 +2708,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
2438
2708
  for (i = 0 ; i < num_endpoints ; ++i) {
2439
2709
  (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
2440
2710
 
2441
- rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams);
2711
+ rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, num_streams);
2442
2712
  if (kIOReturnSuccess != rc)
2443
2713
  return darwin_to_libusb(rc);
2444
2714
  }
@@ -2457,11 +2727,11 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
2457
2727
  if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
2458
2728
  return rc;
2459
2729
 
2460
- (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
2730
+ (*IOINTERFACE_V(cInterface, 550))->SupportsStreams (IOINTERFACE(cInterface), pipeRef, &supportsStreams);
2461
2731
  if (0 == supportsStreams)
2462
2732
  return LIBUSB_ERROR_INVALID_PARAM;
2463
2733
 
2464
- rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0);
2734
+ rc = (*IOINTERFACE_V(cInterface, 550))->CreateStreams (IOINTERFACE(cInterface), pipeRef, 0);
2465
2735
  if (kIOReturnSuccess != rc)
2466
2736
  return darwin_to_libusb(rc);
2467
2737
  }
@@ -2470,7 +2740,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
2470
2740
  }
2471
2741
  #endif
2472
2742
 
2473
- #if InterfaceVersion >= 700
2743
+ #if MAX_INTERFACE_VERSION >= 700
2474
2744
 
2475
2745
  /* macOS APIs for getting entitlement values */
2476
2746
 
@@ -2504,15 +2774,10 @@ static int darwin_reload_device (struct libusb_device_handle *dev_handle) {
2504
2774
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2505
2775
  enum libusb_error err;
2506
2776
 
2507
- usbi_mutex_lock(&darwin_cached_devices_lock);
2508
- (*(dpriv->device))->Release(dpriv->device);
2509
- dpriv->device = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service);
2510
- if (!dpriv->device) {
2511
- err = LIBUSB_ERROR_NO_DEVICE;
2512
- } else {
2513
- err = LIBUSB_SUCCESS;
2514
- }
2515
- usbi_mutex_unlock(&darwin_cached_devices_lock);
2777
+ usbi_mutex_lock(&darwin_cached_devices_mutex);
2778
+ (*dpriv->device)->Release(dpriv->device);
2779
+ err = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service, &dpriv->device);
2780
+ usbi_mutex_unlock(&darwin_cached_devices_mutex);
2516
2781
 
2517
2782
  return err;
2518
2783
  }
@@ -2526,8 +2791,7 @@ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle,
2526
2791
  enum libusb_error err;
2527
2792
  struct libusb_context *ctx = HANDLE_CTX (dev_handle);
2528
2793
 
2529
- if (HAS_CAPTURE_DEVICE()) {
2530
- } else {
2794
+ if (get_interface_interface_version() < 700) {
2531
2795
  return LIBUSB_ERROR_NOT_SUPPORTED;
2532
2796
  }
2533
2797
 
@@ -2570,8 +2834,7 @@ static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle,
2570
2834
  UNUSED(interface);
2571
2835
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2572
2836
 
2573
- if (HAS_CAPTURE_DEVICE()) {
2574
- } else {
2837
+ if (get_interface_interface_version() < 700) {
2575
2838
  return LIBUSB_ERROR_NOT_SUPPORTED;
2576
2839
  }
2577
2840
 
@@ -2638,14 +2901,14 @@ const struct usbi_os_backend usbi_backend = {
2638
2901
  .clear_halt = darwin_clear_halt,
2639
2902
  .reset_device = darwin_reset_device,
2640
2903
 
2641
- #if InterfaceVersion >= 550
2904
+ #if MAX_INTERFACE_VERSION >= 550
2642
2905
  .alloc_streams = darwin_alloc_streams,
2643
2906
  .free_streams = darwin_free_streams,
2644
2907
  #endif
2645
2908
 
2646
2909
  .kernel_driver_active = darwin_kernel_driver_active,
2647
2910
 
2648
- #if InterfaceVersion >= 700
2911
+ #if MAX_INTERFACE_VERSION >= 700
2649
2912
  .detach_kernel_driver = darwin_detach_kernel_driver,
2650
2913
  .attach_kernel_driver = darwin_attach_kernel_driver,
2651
2914
  .claim_interface = darwin_capture_claim_interface,