usb 2.1.3 → 2.2.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 (279) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -0
  3. package/dist/index.d.ts +2 -1
  4. package/dist/index.js +3 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/usb/bindings.d.ts +4 -0
  7. package/dist/usb/device.js +5 -0
  8. package/dist/usb/device.js.map +1 -1
  9. package/libusb/.gitattributes +2 -6
  10. package/libusb/.private/appveyor_build.sh +22 -0
  11. package/libusb/.private/bm.sh +1 -1
  12. package/libusb/.private/ci-build.sh +67 -0
  13. package/libusb/.private/post-rewrite.sh +5 -1
  14. package/libusb/.private/pre-commit.sh +5 -1
  15. package/libusb/.private/wbs.txt +4 -19
  16. package/libusb/.travis.yml +32 -23
  17. package/libusb/AUTHORS +76 -3
  18. package/libusb/ChangeLog +41 -3
  19. package/libusb/INSTALL_WIN.txt +22 -44
  20. package/libusb/Makefile.am +32 -10
  21. package/libusb/{README.md → README} +2 -2
  22. package/libusb/README.git +3 -3
  23. package/libusb/Xcode/common.xcconfig +23 -19
  24. package/libusb/Xcode/config.h +25 -13
  25. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +511 -109
  26. package/libusb/android/README +90 -54
  27. package/libusb/android/config.h +23 -43
  28. package/libusb/android/examples/unrooted_android.c +301 -0
  29. package/libusb/android/examples/unrooted_android.h +36 -0
  30. package/libusb/android/jni/Android.mk +1 -1
  31. package/libusb/android/jni/Application.mk +16 -0
  32. package/libusb/android/jni/examples.mk +63 -29
  33. package/libusb/android/jni/libusb.mk +14 -8
  34. package/libusb/android/jni/tests.mk +13 -24
  35. package/libusb/appveyor.yml +69 -30
  36. package/libusb/autogen.sh +5 -3
  37. package/libusb/bootstrap.sh +6 -2
  38. package/libusb/configure.ac +302 -228
  39. package/libusb/doc/Makefile.in +22 -0
  40. package/libusb/doc/doxygen.cfg.in +460 -223
  41. package/libusb/examples/Makefile.am +6 -13
  42. package/libusb/examples/dpfp.c +276 -73
  43. package/libusb/examples/ezusb.c +18 -8
  44. package/libusb/examples/ezusb.h +6 -17
  45. package/libusb/examples/fxload.c +4 -5
  46. package/libusb/examples/hotplugtest.c +1 -1
  47. package/libusb/examples/sam3u_benchmark.c +59 -24
  48. package/libusb/examples/testlibusb.c +138 -104
  49. package/libusb/examples/xusb.c +26 -22
  50. package/libusb/libusb/Makefile.am +57 -70
  51. package/libusb/libusb/Makefile.am.extra +26 -0
  52. package/libusb/libusb/core.c +420 -423
  53. package/libusb/libusb/descriptor.c +365 -419
  54. package/libusb/libusb/hotplug.c +197 -104
  55. package/libusb/libusb/io.c +491 -528
  56. package/libusb/libusb/libusb-1.0.def +7 -3
  57. package/libusb/libusb/libusb-1.0.rc +1 -9
  58. package/libusb/libusb/libusb.h +295 -226
  59. package/libusb/libusb/libusbi.h +587 -314
  60. package/libusb/libusb/os/darwin_usb.c +634 -317
  61. package/libusb/libusb/os/darwin_usb.h +39 -15
  62. package/libusb/libusb/os/events_posix.c +300 -0
  63. package/libusb/libusb/os/events_posix.h +59 -0
  64. package/libusb/libusb/os/events_windows.c +214 -0
  65. package/libusb/{msvc/missing.h → libusb/os/events_windows.h} +25 -11
  66. package/libusb/libusb/os/haiku_pollfs.cpp +14 -9
  67. package/libusb/libusb/os/haiku_usb.h +12 -12
  68. package/libusb/libusb/os/haiku_usb_backend.cpp +36 -37
  69. package/libusb/libusb/os/haiku_usb_raw.cpp +80 -116
  70. package/libusb/libusb/os/linux_netlink.c +55 -63
  71. package/libusb/libusb/os/linux_udev.c +61 -69
  72. package/libusb/libusb/os/linux_usbfs.c +926 -1015
  73. package/libusb/libusb/os/linux_usbfs.h +74 -57
  74. package/libusb/libusb/os/netbsd_usb.c +103 -168
  75. package/libusb/libusb/os/null_usb.c +111 -0
  76. package/libusb/libusb/os/openbsd_usb.c +71 -120
  77. package/libusb/libusb/os/sunos_usb.c +289 -375
  78. package/libusb/libusb/os/sunos_usb.h +0 -1
  79. package/libusb/libusb/os/threads_posix.c +81 -32
  80. package/libusb/libusb/os/threads_posix.h +19 -23
  81. package/libusb/libusb/os/threads_windows.c +9 -95
  82. package/libusb/libusb/os/threads_windows.h +33 -31
  83. package/libusb/libusb/os/windows_common.c +904 -0
  84. package/libusb/libusb/os/windows_common.h +329 -42
  85. package/libusb/libusb/os/windows_usbdk.c +161 -267
  86. package/libusb/libusb/os/windows_usbdk.h +5 -2
  87. package/libusb/libusb/os/windows_winusb.c +1326 -1190
  88. package/libusb/libusb/os/windows_winusb.h +167 -167
  89. package/libusb/libusb/strerror.c +20 -30
  90. package/libusb/libusb/sync.c +20 -21
  91. package/libusb/libusb/version.h +1 -1
  92. package/libusb/libusb/version_nano.h +1 -1
  93. package/libusb/msvc/.gitattributes +3 -0
  94. package/libusb/msvc/config.h +27 -20
  95. package/libusb/msvc/{hotplugtest_2012.vcxproj → dpfp_2013.vcxproj} +14 -10
  96. package/libusb/msvc/dpfp_2013.vcxproj.filters +26 -0
  97. package/libusb/msvc/{listdevs_2010.vcxproj → dpfp_2015.vcxproj} +14 -9
  98. package/libusb/msvc/dpfp_2015.vcxproj.filters +26 -0
  99. package/libusb/msvc/dpfp_2017.vcxproj +106 -0
  100. package/libusb/msvc/dpfp_2017.vcxproj.filters +26 -0
  101. package/libusb/msvc/dpfp_2019.vcxproj +106 -0
  102. package/libusb/msvc/dpfp_2019.vcxproj.filters +26 -0
  103. package/libusb/msvc/dpfp_threaded_2013.vcxproj +87 -0
  104. package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +26 -0
  105. package/libusb/msvc/dpfp_threaded_2015.vcxproj +87 -0
  106. package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +26 -0
  107. package/libusb/msvc/dpfp_threaded_2017.vcxproj +106 -0
  108. package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +26 -0
  109. package/libusb/msvc/{fxload_2012.vcxproj → dpfp_threaded_2019.vcxproj} +32 -17
  110. package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +26 -0
  111. package/libusb/msvc/fxload_2013.vcxproj +6 -3
  112. package/libusb/msvc/fxload_2013.vcxproj.filters +35 -0
  113. package/libusb/msvc/fxload_2015.vcxproj +6 -3
  114. package/libusb/msvc/fxload_2015.vcxproj.filters +35 -0
  115. package/libusb/msvc/fxload_2017.vcxproj +6 -7
  116. package/libusb/msvc/fxload_2017.vcxproj.filters +35 -0
  117. package/libusb/msvc/{fxload_2010.vcxproj → fxload_2019.vcxproj} +29 -6
  118. package/libusb/msvc/fxload_2019.vcxproj.filters +35 -0
  119. package/libusb/{examples → msvc}/getopt/getopt.c +0 -0
  120. package/libusb/{examples → msvc}/getopt/getopt.h +0 -0
  121. package/libusb/{examples → msvc}/getopt/getopt1.c +0 -0
  122. package/libusb/msvc/getopt_2013.vcxproj +4 -5
  123. package/libusb/msvc/getopt_2013.vcxproj.filters +26 -0
  124. package/libusb/msvc/getopt_2015.vcxproj +4 -4
  125. package/libusb/msvc/getopt_2015.vcxproj.filters +26 -0
  126. package/libusb/msvc/getopt_2017.vcxproj +4 -10
  127. package/libusb/msvc/getopt_2017.vcxproj.filters +26 -0
  128. package/libusb/msvc/{getopt_2012.vcxproj → getopt_2019.vcxproj} +25 -6
  129. package/libusb/msvc/getopt_2019.vcxproj.filters +26 -0
  130. package/libusb/msvc/hotplugtest_2013.vcxproj +6 -3
  131. package/libusb/msvc/hotplugtest_2013.vcxproj.filters +23 -0
  132. package/libusb/msvc/hotplugtest_2015.vcxproj +6 -3
  133. package/libusb/msvc/hotplugtest_2015.vcxproj.filters +23 -0
  134. package/libusb/msvc/hotplugtest_2017.vcxproj +6 -7
  135. package/libusb/msvc/hotplugtest_2017.vcxproj.filters +23 -0
  136. package/libusb/msvc/hotplugtest_2019.vcxproj +105 -0
  137. package/libusb/msvc/hotplugtest_2019.vcxproj.filters +23 -0
  138. package/libusb/msvc/libusb_2013.sln +50 -20
  139. package/libusb/msvc/libusb_2015.sln +51 -21
  140. package/libusb/msvc/libusb_2017.sln +90 -36
  141. package/libusb/msvc/libusb_2019.sln +240 -0
  142. package/libusb/msvc/libusb_dll_2013.vcxproj +6 -9
  143. package/libusb/msvc/libusb_dll_2013.vcxproj.filters +94 -0
  144. package/libusb/msvc/libusb_dll_2015.vcxproj +6 -8
  145. package/libusb/msvc/libusb_dll_2015.vcxproj.filters +94 -0
  146. package/libusb/msvc/libusb_dll_2017.vcxproj +6 -16
  147. package/libusb/msvc/libusb_dll_2017.vcxproj.filters +94 -0
  148. package/libusb/msvc/{libusb_dll_2010.vcxproj → libusb_dll_2019.vcxproj} +27 -9
  149. package/libusb/msvc/libusb_dll_2019.vcxproj.filters +94 -0
  150. package/libusb/msvc/libusb_static_2013.vcxproj +5 -9
  151. package/libusb/msvc/libusb_static_2013.vcxproj.filters +80 -0
  152. package/libusb/msvc/libusb_static_2015.vcxproj +5 -8
  153. package/libusb/msvc/libusb_static_2015.vcxproj.filters +80 -0
  154. package/libusb/msvc/libusb_static_2017.vcxproj +5 -8
  155. package/libusb/msvc/libusb_static_2017.vcxproj.filters +80 -0
  156. package/libusb/msvc/{libusb_static_2010.vcxproj → libusb_static_2019.vcxproj} +26 -9
  157. package/libusb/msvc/libusb_static_2019.vcxproj.filters +80 -0
  158. package/libusb/msvc/listdevs_2013.vcxproj +6 -3
  159. package/libusb/msvc/listdevs_2013.vcxproj.filters +23 -0
  160. package/libusb/msvc/listdevs_2015.vcxproj +6 -3
  161. package/libusb/msvc/listdevs_2015.vcxproj.filters +23 -0
  162. package/libusb/msvc/listdevs_2017.vcxproj +6 -7
  163. package/libusb/msvc/listdevs_2017.vcxproj.filters +23 -0
  164. package/libusb/msvc/listdevs_2019.vcxproj +105 -0
  165. package/libusb/msvc/listdevs_2019.vcxproj.filters +23 -0
  166. package/libusb/msvc/{listdevs_2012.vcxproj → sam3u_benchmark_2013.vcxproj} +13 -9
  167. package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +26 -0
  168. package/libusb/msvc/{hotplugtest_2010.vcxproj → sam3u_benchmark_2015.vcxproj} +13 -8
  169. package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +26 -0
  170. package/libusb/msvc/sam3u_benchmark_2017.vcxproj +106 -0
  171. package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +26 -0
  172. package/libusb/msvc/sam3u_benchmark_2019.vcxproj +106 -0
  173. package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +26 -0
  174. package/libusb/msvc/stress_2013.vcxproj +4 -2
  175. package/libusb/msvc/stress_2013.vcxproj.filters +32 -0
  176. package/libusb/msvc/stress_2015.vcxproj +4 -2
  177. package/libusb/msvc/stress_2015.vcxproj.filters +32 -0
  178. package/libusb/msvc/stress_2017.vcxproj +4 -6
  179. package/libusb/msvc/stress_2017.vcxproj.filters +32 -0
  180. package/libusb/msvc/{stress_2010.vcxproj → stress_2019.vcxproj} +26 -4
  181. package/libusb/msvc/stress_2019.vcxproj.filters +32 -0
  182. package/libusb/msvc/testlibusb_2013.vcxproj +6 -3
  183. package/libusb/msvc/testlibusb_2013.vcxproj.filters +23 -0
  184. package/libusb/msvc/testlibusb_2015.vcxproj +6 -3
  185. package/libusb/msvc/testlibusb_2015.vcxproj.filters +23 -0
  186. package/libusb/msvc/testlibusb_2017.vcxproj +6 -7
  187. package/libusb/msvc/testlibusb_2017.vcxproj.filters +23 -0
  188. package/libusb/msvc/{testlibusb_2010.vcxproj → testlibusb_2019.vcxproj} +28 -5
  189. package/libusb/msvc/testlibusb_2019.vcxproj.filters +23 -0
  190. package/libusb/msvc/xusb_2013.vcxproj +6 -3
  191. package/libusb/msvc/xusb_2013.vcxproj.filters +23 -0
  192. package/libusb/msvc/xusb_2015.vcxproj +6 -3
  193. package/libusb/msvc/xusb_2015.vcxproj.filters +23 -0
  194. package/libusb/msvc/xusb_2017.vcxproj +6 -7
  195. package/libusb/msvc/xusb_2017.vcxproj.filters +23 -0
  196. package/libusb/msvc/{xusb_2010.vcxproj → xusb_2019.vcxproj} +28 -5
  197. package/libusb/msvc/xusb_2019.vcxproj.filters +23 -0
  198. package/libusb/tests/Makefile.am +1 -0
  199. package/libusb/tests/libusb_testlib.h +12 -43
  200. package/libusb/tests/stress.c +59 -50
  201. package/libusb/tests/testlib.c +78 -171
  202. package/libusb.gypi +10 -11
  203. package/package.json +1 -1
  204. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  205. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  206. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  207. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  208. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  209. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  210. package/prebuilds/linux-ia32/node.napi.node +0 -0
  211. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  212. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  213. package/prebuilds/win32-ia32/node.napi.node +0 -0
  214. package/prebuilds/win32-x64/node.napi.node +0 -0
  215. package/src/device.cc +12 -7
  216. package/src/node_usb.cc +10 -0
  217. package/test/usb.coffee +6 -0
  218. package/tsc/index.ts +2 -0
  219. package/tsc/usb/bindings.ts +5 -0
  220. package/tsc/usb/device.ts +6 -0
  221. package/libusb/.private/bd.cmd +0 -89
  222. package/libusb/.private/bwince.cmd +0 -57
  223. package/libusb/.private/wbs_wince.txt +0 -42
  224. package/libusb/Brewfile +0 -4
  225. package/libusb/appveyor_cygwin.bat +0 -11
  226. package/libusb/appveyor_minGW.bat +0 -19
  227. package/libusb/doc/Makefile.am +0 -9
  228. package/libusb/examples/dpfp_threaded.c +0 -557
  229. package/libusb/libusb/hotplug.h +0 -99
  230. package/libusb/libusb/os/poll_posix.c +0 -84
  231. package/libusb/libusb/os/poll_posix.h +0 -14
  232. package/libusb/libusb/os/poll_windows.c +0 -447
  233. package/libusb/libusb/os/poll_windows.h +0 -98
  234. package/libusb/libusb/os/wince_usb.c +0 -888
  235. package/libusb/libusb/os/wince_usb.h +0 -126
  236. package/libusb/libusb/os/windows_nt_common.c +0 -1010
  237. package/libusb/libusb/os/windows_nt_common.h +0 -110
  238. package/libusb/libusb/os/windows_nt_shared_types.h +0 -147
  239. package/libusb/msvc/appveyor.bat +0 -27
  240. package/libusb/msvc/ddk_build.cmd +0 -219
  241. package/libusb/msvc/errno.h +0 -102
  242. package/libusb/msvc/fxload_sources +0 -23
  243. package/libusb/msvc/getopt_2005.vcproj +0 -288
  244. package/libusb/msvc/getopt_2010.vcxproj +0 -72
  245. package/libusb/msvc/getopt_sources +0 -24
  246. package/libusb/msvc/hotplugtest_sources +0 -20
  247. package/libusb/msvc/inttypes.h +0 -295
  248. package/libusb/msvc/libusb.dsw +0 -71
  249. package/libusb/msvc/libusb_2005.sln +0 -95
  250. package/libusb/msvc/libusb_2010.sln +0 -105
  251. package/libusb/msvc/libusb_2012.sln +0 -105
  252. package/libusb/msvc/libusb_dll.dsp +0 -194
  253. package/libusb/msvc/libusb_dll_2005.vcproj +0 -464
  254. package/libusb/msvc/libusb_dll_2012.vcxproj +0 -107
  255. package/libusb/msvc/libusb_dll_wince.vcproj +0 -1251
  256. package/libusb/msvc/libusb_sources +0 -43
  257. package/libusb/msvc/libusb_static.dsp +0 -174
  258. package/libusb/msvc/libusb_static_2005.vcproj +0 -390
  259. package/libusb/msvc/libusb_static_2012.vcxproj +0 -98
  260. package/libusb/msvc/libusb_static_wince.vcproj +0 -1179
  261. package/libusb/msvc/libusb_wince.sln +0 -246
  262. package/libusb/msvc/listdevs.dsp +0 -103
  263. package/libusb/msvc/listdevs_2005.vcproj +0 -360
  264. package/libusb/msvc/listdevs_sources +0 -20
  265. package/libusb/msvc/listdevs_wince.vcproj +0 -1120
  266. package/libusb/msvc/missing.c +0 -80
  267. package/libusb/msvc/stdint.h +0 -256
  268. package/libusb/msvc/stress_2005.vcproj +0 -390
  269. package/libusb/msvc/stress_2012.vcxproj +0 -87
  270. package/libusb/msvc/stress_sources +0 -21
  271. package/libusb/msvc/stress_wince.vcproj +0 -1128
  272. package/libusb/msvc/testlibusb_2012.vcxproj +0 -83
  273. package/libusb/msvc/testlibusb_sources +0 -20
  274. package/libusb/msvc/xusb.dsp +0 -102
  275. package/libusb/msvc/xusb_2005.vcproj +0 -344
  276. package/libusb/msvc/xusb_2012.vcxproj +0 -83
  277. package/libusb/msvc/xusb_sources +0 -20
  278. package/libusb/msvc/xusb_wince.vcproj +0 -1120
  279. package/libusb/travis-autogen.sh +0 -39
@@ -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-2019 Nathan Hjelm <hjelmn@users.sourceforge.net>
5
- * Copyright © 2019 Google LLC. All rights reserved.
4
+ * Copyright © 2008-2021 Nathan Hjelm <hjelmn@cs.unm.edu>
5
+ * Copyright © 2019-2021 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
@@ -19,11 +19,10 @@
19
19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
  */
21
21
 
22
- #include "config.h"
22
+ #include <config.h>
23
23
  #include <assert.h>
24
24
  #include <time.h>
25
25
  #include <ctype.h>
26
- #include <errno.h>
27
26
  #include <pthread.h>
28
27
  #include <stdio.h>
29
28
  #include <stdlib.h>
@@ -42,61 +41,50 @@
42
41
  * function. Its use is also conditionalized to only older deployment targets. */
43
42
  #define OBJC_SILENCE_GC_DEPRECATIONS 1
44
43
 
44
+ /* Default timeout to 10s for reenumerate. This is needed because USBDeviceReEnumerate
45
+ * does not return error status on macOS. */
46
+ #define DARWIN_REENUMERATE_TIMEOUT_US 10000000
47
+
45
48
  #include <AvailabilityMacros.h>
46
49
  #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
47
50
  #include <objc/objc-auto.h>
48
51
  #endif
49
52
 
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
53
+ #include "darwin_usb.h"
66
54
 
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
55
+ static int init_count = 0;
73
56
 
74
- #include "darwin_usb.h"
57
+ /* Both kIOMasterPortDefault or kIOMainPortDefault are synonyms for 0. */
58
+ static const mach_port_t darwin_default_master_port = 0;
75
59
 
76
60
  /* async event thread */
77
61
  static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
78
62
  static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
79
63
 
80
- #if !OSX_USE_CLOCK_GETTIME
64
+ #if !defined(HAVE_CLOCK_GETTIME)
81
65
  static clock_serv_t clock_realtime;
82
66
  static clock_serv_t clock_monotonic;
83
67
  #endif
84
68
 
69
+ #define LIBUSB_DARWIN_STARTUP_FAILURE ((CFRunLoopRef) -1)
70
+
85
71
  static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
86
72
  static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
87
73
 
88
74
  static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
89
- static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
90
- static const char *darwin_device_class = kIOUSBDeviceClassName;
75
+ static struct list_head darwin_cached_devices;
76
+ static const char *darwin_device_class = "IOUSBDevice";
91
77
 
92
- #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
78
+ #define DARWIN_CACHED_DEVICE(a) (((struct darwin_device_priv *)usbi_get_device_priv((a)))->dev)
93
79
 
94
80
  /* async event thread */
95
81
  static pthread_t libusb_darwin_at;
96
82
 
97
- static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian);
98
- static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface);
99
- static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface);
83
+ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len);
84
+ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
85
+ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface);
86
+ static int darwin_reenumerate_device(struct libusb_device_handle *dev_handle, bool capture);
87
+ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint);
100
88
  static int darwin_reset_device(struct libusb_device_handle *dev_handle);
101
89
  static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
102
90
 
@@ -104,7 +92,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx);
104
92
  static enum libusb_error process_new_device (struct libusb_context *ctx, struct darwin_cached_device *cached_device,
105
93
  UInt64 old_session_id);
106
94
 
107
- static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
95
+ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
108
96
  UInt64 *old_session_id);
109
97
 
110
98
  #if defined(ENABLE_LOGGING)
@@ -122,6 +110,9 @@ static const char *darwin_error_str (IOReturn result) {
122
110
  case kIOReturnExclusiveAccess:
123
111
  return "another process has device opened for exclusive access";
124
112
  case kIOUSBPipeStalled:
113
+ #if defined(kUSBHostReturnPipeStalled)
114
+ case kUSBHostReturnPipeStalled:
115
+ #endif
125
116
  return "pipe is stalled";
126
117
  case kIOReturnError:
127
118
  return "could not establish a connection to the Darwin kernel";
@@ -141,6 +132,8 @@ static const char *darwin_error_str (IOReturn result) {
141
132
  return "out of resources";
142
133
  case kIOUSBHighSpeedSplitError:
143
134
  return "high speed split error";
135
+ case kIOUSBUnknownPipeErr:
136
+ return "pipe ref not recognized";
144
137
  default:
145
138
  snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result);
146
139
  return string_buffer;
@@ -159,11 +152,16 @@ static enum libusb_error darwin_to_libusb (IOReturn result) {
159
152
  case kIOReturnExclusiveAccess:
160
153
  return LIBUSB_ERROR_ACCESS;
161
154
  case kIOUSBPipeStalled:
155
+ #if defined(kUSBHostReturnPipeStalled)
156
+ case kUSBHostReturnPipeStalled:
157
+ #endif
162
158
  return LIBUSB_ERROR_PIPE;
163
159
  case kIOReturnBadArgument:
164
160
  return LIBUSB_ERROR_INVALID_PARAM;
165
161
  case kIOUSBTransactionTimeout:
166
162
  return LIBUSB_ERROR_TIMEOUT;
163
+ case kIOUSBUnknownPipeErr:
164
+ return LIBUSB_ERROR_NOT_FOUND;
167
165
  case kIOReturnNotResponding:
168
166
  case kIOReturnAborted:
169
167
  case kIOReturnError:
@@ -184,6 +182,7 @@ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev)
184
182
  (*(cached_dev->device))->Release(cached_dev->device);
185
183
  cached_dev->device = NULL;
186
184
  }
185
+ IOObjectRelease (cached_dev->service);
187
186
  free (cached_dev);
188
187
  }
189
188
  }
@@ -193,14 +192,16 @@ static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) {
193
192
  }
194
193
 
195
194
  static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) {
196
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
195
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
197
196
 
198
197
  /* current interface */
199
198
  struct darwin_interface *cInterface;
200
199
 
201
200
  uint8_t i, iface;
202
201
 
203
- usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep);
202
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
203
+
204
+ usbi_dbg (ctx, "converting ep address 0x%02x to pipeRef and interface", ep);
204
205
 
205
206
  for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) {
206
207
  cInterface = &priv->interfaces[iface];
@@ -216,7 +217,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
216
217
  if (interface_out)
217
218
  *interface_out = cInterface;
218
219
 
219
- usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
220
+ usbi_dbg (ctx, "pipe %d on interface %d matches", *pipep, iface);
220
221
  return LIBUSB_SUCCESS;
221
222
  }
222
223
  }
@@ -257,7 +258,7 @@ static IOReturn usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32
257
258
  CFRelease (locationCF);
258
259
  }
259
260
 
260
- return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
261
+ return IOServiceGetMatchingServices(darwin_default_master_port, matchingDict, deviceIterator);
261
262
  }
262
263
 
263
264
  /* Returns 1 on success, 0 on failure. */
@@ -298,7 +299,7 @@ static bool get_ioregistry_value_data (io_service_t service, CFStringRef propert
298
299
  return success;
299
300
  }
300
301
 
301
- static usb_device_t **darwin_device_from_service (io_service_t service)
302
+ static usb_device_t **darwin_device_from_service (struct libusb_context *ctx, io_service_t service)
302
303
  {
303
304
  io_cf_plugin_ref_t *plugInInterface = NULL;
304
305
  usb_device_t **device;
@@ -317,14 +318,14 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
317
318
  break;
318
319
  }
319
320
 
320
- usbi_dbg ("set up plugin for service retry: %s", darwin_error_str (kresult));
321
+ usbi_dbg (ctx, "set up plugin for service retry: %s", darwin_error_str (kresult));
321
322
 
322
323
  /* sleep for a little while before trying again */
323
324
  nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 1000}, NULL);
324
325
  }
325
326
 
326
327
  if (kIOReturnSuccess != kresult || !plugInInterface) {
327
- usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (kresult));
328
+ usbi_dbg (ctx, "could not set up plugin for service: %s", darwin_error_str (kresult));
328
329
  return NULL;
329
330
  }
330
331
 
@@ -347,18 +348,18 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
347
348
  usbi_mutex_lock(&active_contexts_lock);
348
349
 
349
350
  while ((service = IOIteratorNext(add_devices))) {
350
- ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
351
+ ret = darwin_get_cached_device (NULL, service, &cached_device, &old_session_id);
351
352
  if (ret < 0 || !cached_device->can_enumerate) {
352
353
  continue;
353
354
  }
354
355
 
355
356
  /* add this device to each active context's device list */
356
- list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
357
+ for_each_context(ctx) {
357
358
  process_new_device (ctx, cached_device, old_session_id);
358
359
  }
359
360
 
360
361
  if (cached_device->in_reenumerate) {
361
- usbi_dbg ("cached device in reset state. reset complete...");
362
+ usbi_dbg (NULL, "cached device in reset state. reset complete...");
362
363
  cached_device->in_reenumerate = false;
363
364
  }
364
365
 
@@ -375,7 +376,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
375
376
  struct darwin_cached_device *old_device;
376
377
 
377
378
  io_service_t device;
378
- UInt64 session;
379
+ UInt64 session, locationID;
379
380
  int ret;
380
381
 
381
382
  usbi_mutex_lock(&active_contexts_lock);
@@ -385,6 +386,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
385
386
 
386
387
  /* get the location from the i/o registry */
387
388
  ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
389
+ (void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
388
390
  IOObjectRelease (device);
389
391
  if (!ret)
390
392
  continue;
@@ -397,7 +399,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
397
399
  if (old_device->in_reenumerate) {
398
400
  /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
399
401
  * will deref if needed. */
400
- usbi_dbg ("detected device detatched due to re-enumeration");
402
+ usbi_dbg (NULL, "detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 ", locationID: 0x%" PRIx64,
403
+ session, locationID);
401
404
 
402
405
  /* the device object is no longer usable so go ahead and release it */
403
406
  if (old_device->device) {
@@ -419,8 +422,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
419
422
  continue;
420
423
  }
421
424
 
422
- list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
423
- usbi_dbg ("notifying context %p of device disconnect", ctx);
425
+ for_each_context(ctx) {
426
+ usbi_dbg (ctx, "notifying context %p of device disconnect", ctx);
424
427
 
425
428
  dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
426
429
  if (dev) {
@@ -443,7 +446,7 @@ static void darwin_hotplug_poll (void)
443
446
  /* since a kernel thread may notify the IOIterators used for
444
447
  * hotplug notification we can't just clear the iterators.
445
448
  * instead just wait until all IOService providers are quiet */
446
- (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout);
449
+ (void) IOKitWaitQuiet (darwin_default_master_port, &timeout);
447
450
  }
448
451
 
449
452
  static void darwin_clear_iterator (io_iterator_t iter) {
@@ -453,10 +456,20 @@ static void darwin_clear_iterator (io_iterator_t iter) {
453
456
  IOObjectRelease (device);
454
457
  }
455
458
 
459
+ static void darwin_fail_startup(void) {
460
+ pthread_mutex_lock (&libusb_darwin_at_mutex);
461
+ libusb_darwin_acfl = LIBUSB_DARWIN_STARTUP_FAILURE;
462
+ pthread_cond_signal (&libusb_darwin_at_cond);
463
+ pthread_mutex_unlock (&libusb_darwin_at_mutex);
464
+ pthread_exit (NULL);
465
+ }
466
+
456
467
  static void *darwin_event_thread_main (void *arg0) {
457
468
  IOReturn kresult;
458
469
  struct libusb_context *ctx = (struct libusb_context *)arg0;
459
470
  CFRunLoopRef runloop;
471
+ CFRunLoopSourceRef libusb_shutdown_cfsource;
472
+ CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
460
473
 
461
474
  #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
462
475
  /* Set this thread's name, so it can be seen in the debugger
@@ -475,13 +488,12 @@ static void *darwin_event_thread_main (void *arg0) {
475
488
  #endif
476
489
 
477
490
  /* hotplug (device arrival/removal) sources */
478
- CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
479
491
  CFRunLoopSourceRef libusb_notification_cfsource;
480
492
  io_notification_port_t libusb_notification_port;
481
493
  io_iterator_t libusb_rem_device_iterator;
482
494
  io_iterator_t libusb_add_device_iterator;
483
495
 
484
- usbi_dbg ("creating hotplug event source");
496
+ usbi_dbg (ctx, "creating hotplug event source");
485
497
 
486
498
  runloop = CFRunLoopGetCurrent ();
487
499
  CFRetain (runloop);
@@ -490,11 +502,11 @@ static void *darwin_event_thread_main (void *arg0) {
490
502
  memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
491
503
  libusb_shutdown_cfsourcectx.info = runloop;
492
504
  libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
493
- libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
494
- CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
505
+ libusb_shutdown_cfsource = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
506
+ CFRunLoopAddSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
495
507
 
496
508
  /* add the notification port to the run loop */
497
- libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault);
509
+ libusb_notification_port = IONotificationPortCreate (darwin_default_master_port);
498
510
  libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
499
511
  CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
500
512
 
@@ -506,8 +518,9 @@ static void *darwin_event_thread_main (void *arg0) {
506
518
 
507
519
  if (kresult != kIOReturnSuccess) {
508
520
  usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
509
-
510
- pthread_exit (NULL);
521
+ CFRelease (libusb_shutdown_cfsource);
522
+ CFRelease (runloop);
523
+ darwin_fail_startup ();
511
524
  }
512
525
 
513
526
  /* create notifications for attached devices */
@@ -518,32 +531,41 @@ static void *darwin_event_thread_main (void *arg0) {
518
531
 
519
532
  if (kresult != kIOReturnSuccess) {
520
533
  usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
521
-
522
- pthread_exit (NULL);
534
+ CFRelease (libusb_shutdown_cfsource);
535
+ CFRelease (runloop);
536
+ darwin_fail_startup ();
523
537
  }
524
538
 
525
539
  /* arm notifiers */
526
540
  darwin_clear_iterator (libusb_rem_device_iterator);
527
541
  darwin_clear_iterator (libusb_add_device_iterator);
528
542
 
529
- usbi_dbg ("darwin event thread ready to receive events");
543
+ usbi_dbg (ctx, "darwin event thread ready to receive events");
530
544
 
531
545
  /* signal the main thread that the hotplug runloop has been created. */
532
546
  pthread_mutex_lock (&libusb_darwin_at_mutex);
533
547
  libusb_darwin_acfl = runloop;
548
+ libusb_darwin_acfls = libusb_shutdown_cfsource;
534
549
  pthread_cond_signal (&libusb_darwin_at_cond);
535
550
  pthread_mutex_unlock (&libusb_darwin_at_mutex);
536
551
 
537
552
  /* run the runloop */
538
553
  CFRunLoopRun();
539
554
 
540
- usbi_dbg ("darwin event thread exiting");
555
+ usbi_dbg (ctx, "darwin event thread exiting");
556
+
557
+ /* signal the main thread that the hotplug runloop has finished. */
558
+ pthread_mutex_lock (&libusb_darwin_at_mutex);
559
+ libusb_darwin_acfls = NULL;
560
+ libusb_darwin_acfl = NULL;
561
+ pthread_cond_signal (&libusb_darwin_at_cond);
562
+ pthread_mutex_unlock (&libusb_darwin_at_mutex);
541
563
 
542
564
  /* remove the notification cfsource */
543
565
  CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
544
566
 
545
567
  /* remove the shutdown cfsource */
546
- CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
568
+ CFRunLoopRemoveSource(runloop, libusb_shutdown_cfsource, kCFRunLoopDefaultMode);
547
569
 
548
570
  /* delete notification port */
549
571
  IONotificationPortDestroy (libusb_notification_port);
@@ -552,51 +574,79 @@ static void *darwin_event_thread_main (void *arg0) {
552
574
  IOObjectRelease (libusb_rem_device_iterator);
553
575
  IOObjectRelease (libusb_add_device_iterator);
554
576
 
555
- CFRelease (libusb_darwin_acfls);
577
+ CFRelease (libusb_shutdown_cfsource);
556
578
  CFRelease (runloop);
557
579
 
558
- libusb_darwin_acfls = NULL;
559
- libusb_darwin_acfl = NULL;
560
-
561
580
  pthread_exit (NULL);
562
581
  }
563
582
 
564
583
  /* cleanup function to destroy cached devices */
565
- static void __attribute__((destructor)) _darwin_finalize(void) {
584
+ static void darwin_cleanup_devices(void) {
566
585
  struct darwin_cached_device *dev, *next;
567
586
 
568
- usbi_mutex_lock(&darwin_cached_devices_lock);
569
587
  list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
570
588
  darwin_deref_cached_device(dev);
571
589
  }
572
- usbi_mutex_unlock(&darwin_cached_devices_lock);
573
590
  }
574
591
 
575
592
  static int darwin_init(struct libusb_context *ctx) {
593
+ bool first_init;
576
594
  int rc;
577
595
 
578
- rc = darwin_scan_devices (ctx);
579
- if (LIBUSB_SUCCESS != rc) {
580
- return rc;
581
- }
582
-
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;
596
+ first_init = (1 == ++init_count);
587
597
 
588
- host_self = mach_host_self();
589
- host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
590
- host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
591
- mach_port_deallocate(mach_task_self(), host_self);
598
+ do {
599
+ if (first_init) {
600
+ if (NULL == darwin_cached_devices.next) {
601
+ list_init (&darwin_cached_devices);
602
+ }
603
+ assert(list_empty(&darwin_cached_devices));
604
+ #if !defined(HAVE_CLOCK_GETTIME)
605
+ /* create the clocks that will be used if clock_gettime() is not available */
606
+ host_name_port_t host_self;
607
+
608
+ host_self = mach_host_self();
609
+ host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
610
+ host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
611
+ mach_port_deallocate(mach_task_self(), host_self);
592
612
  #endif
613
+ }
614
+
615
+ rc = darwin_scan_devices (ctx);
616
+ if (LIBUSB_SUCCESS != rc)
617
+ break;
593
618
 
594
- pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
619
+ if (first_init) {
620
+ rc = pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
621
+ if (0 != rc) {
622
+ usbi_err (ctx, "could not create event thread, error %d", rc);
623
+ rc = LIBUSB_ERROR_OTHER;
624
+ break;
625
+ }
595
626
 
596
- pthread_mutex_lock (&libusb_darwin_at_mutex);
597
- while (!libusb_darwin_acfl)
598
- pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
599
- pthread_mutex_unlock (&libusb_darwin_at_mutex);
627
+ pthread_mutex_lock (&libusb_darwin_at_mutex);
628
+ while (!libusb_darwin_acfl)
629
+ pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
630
+ if (libusb_darwin_acfl == LIBUSB_DARWIN_STARTUP_FAILURE) {
631
+ libusb_darwin_acfl = NULL;
632
+ rc = LIBUSB_ERROR_OTHER;
633
+ }
634
+ pthread_mutex_unlock (&libusb_darwin_at_mutex);
635
+
636
+ if (0 != rc)
637
+ pthread_join (libusb_darwin_at, NULL);
638
+ }
639
+ } while (0);
640
+
641
+ if (LIBUSB_SUCCESS != rc) {
642
+ if (first_init) {
643
+ darwin_cleanup_devices ();
644
+ #if !defined(HAVE_CLOCK_GETTIME)
645
+ mach_port_deallocate(mach_task_self(), clock_realtime);
646
+ mach_port_deallocate(mach_task_self(), clock_monotonic);
647
+ #endif
648
+ }
649
+ --init_count;
600
650
  }
601
651
 
602
652
  return rc;
@@ -604,31 +654,27 @@ static int darwin_init(struct libusb_context *ctx) {
604
654
 
605
655
  static void darwin_exit (struct libusb_context *ctx) {
606
656
  UNUSED(ctx);
607
- if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
608
- #if !OSX_USE_CLOCK_GETTIME
609
- mach_port_deallocate(mach_task_self(), clock_realtime);
610
- mach_port_deallocate(mach_task_self(), clock_monotonic);
611
- #endif
612
657
 
658
+ if (0 == --init_count) {
613
659
  /* stop the event runloop and wait for the thread to terminate. */
614
- CFRunLoopSourceSignal(libusb_darwin_acfls);
660
+ pthread_mutex_lock (&libusb_darwin_at_mutex);
661
+ CFRunLoopSourceSignal (libusb_darwin_acfls);
615
662
  CFRunLoopWakeUp (libusb_darwin_acfl);
663
+ while (libusb_darwin_acfl)
664
+ pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex);
665
+ pthread_mutex_unlock (&libusb_darwin_at_mutex);
616
666
  pthread_join (libusb_darwin_at, NULL);
617
- }
618
- }
619
667
 
620
- static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) {
621
- struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
622
-
623
- /* return cached copy */
624
- memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH);
668
+ darwin_cleanup_devices ();
625
669
 
626
- *host_endian = 0;
627
-
628
- return LIBUSB_SUCCESS;
670
+ #if !defined(HAVE_CLOCK_GETTIME)
671
+ mach_port_deallocate(mach_task_self(), clock_realtime);
672
+ mach_port_deallocate(mach_task_self(), clock_monotonic);
673
+ #endif
674
+ }
629
675
  }
630
676
 
631
- static int get_configuration_index (struct libusb_device *dev, int config_value) {
677
+ static int get_configuration_index (struct libusb_device *dev, UInt8 config_value) {
632
678
  struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
633
679
  UInt8 i, numConfig;
634
680
  IOUSBConfigurationDescriptorPtr desc;
@@ -650,7 +696,7 @@ static int get_configuration_index (struct libusb_device *dev, int config_value)
650
696
  return LIBUSB_ERROR_NOT_FOUND;
651
697
  }
652
698
 
653
- static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) {
699
+ static int darwin_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len) {
654
700
  struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
655
701
  int config_index;
656
702
 
@@ -662,10 +708,10 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign
662
708
  return config_index;
663
709
 
664
710
  assert(config_index >= 0 && config_index <= UINT8_MAX);
665
- return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len, host_endian);
711
+ return darwin_get_config_descriptor (dev, (UInt8)config_index, buffer, len);
666
712
  }
667
713
 
668
- static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) {
714
+ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len) {
669
715
  struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
670
716
  IOUSBConfigurationDescriptorPtr desc;
671
717
  IOReturn kresult;
@@ -681,9 +727,6 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
681
727
  len = libusb_le16_to_cpu(desc->wTotalLength);
682
728
 
683
729
  memmove (buffer, desc, len);
684
-
685
- /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */
686
- *host_endian = 0;
687
730
  }
688
731
 
689
732
  ret = darwin_to_libusb (kresult);
@@ -710,8 +753,9 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
710
753
 
711
754
  /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is
712
755
  not usable anyway */
713
- if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) {
714
- usbi_dbg ("ignoring configuration on root hub simulation");
756
+ if (0x05ac == libusb_le16_to_cpu (dev->dev_descriptor.idVendor) &&
757
+ 0x8005 == libusb_le16_to_cpu (dev->dev_descriptor.idProduct)) {
758
+ usbi_dbg (ctx, "ignoring configuration on root hub simulation");
715
759
  dev->active_config = 0;
716
760
  return LIBUSB_SUCCESS;
717
761
  }
@@ -753,8 +797,8 @@ static enum libusb_error darwin_check_configuration (struct libusb_context *ctx,
753
797
  } else
754
798
  /* not configured */
755
799
  dev->active_config = 0;
756
-
757
- usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
800
+
801
+ usbi_dbg (ctx, "active config: %u, first config: %u", dev->active_config, dev->first_config);
758
802
 
759
803
  return LIBUSB_SUCCESS;
760
804
  }
@@ -779,7 +823,7 @@ static IOReturn darwin_request_descriptor (usb_device_t **device, UInt8 desc, UI
779
823
  return (*device)->DeviceRequestTO (device, &req);
780
824
  }
781
825
 
782
- static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_device *dev) {
826
+ static enum libusb_error darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
783
827
  usb_device_t **device = dev->device;
784
828
  int retries = 1;
785
829
  long delay = 30000; // microseconds
@@ -817,7 +861,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
817
861
  0 == dev->dev_descriptor.bcdUSB)) {
818
862
  /* work around for incorrectly configured devices */
819
863
  if (try_reconfigure && is_open) {
820
- usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
864
+ usbi_dbg(ctx, "descriptor appears to be invalid. resetting configuration before trying again...");
821
865
 
822
866
  /* set the first configuration */
823
867
  (*device)->SetConfiguration(device, 1);
@@ -848,7 +892,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
848
892
  if (kIOReturnSuccess != ret2) {
849
893
  /* prevent log spew from poorly behaving devices. this indicates the
850
894
  os actually had trouble communicating with the device */
851
- usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
895
+ usbi_dbg(ctx, "could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
852
896
  } else
853
897
  unsuspended = 1;
854
898
 
@@ -857,7 +901,7 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
857
901
  }
858
902
 
859
903
  if (kIOReturnSuccess != ret) {
860
- usbi_dbg("kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
904
+ usbi_dbg(ctx, "kernel responded with code: 0x%08x. sleeping for %ld ms before trying again", ret, delay/1000);
861
905
  /* sleep for a little while before trying again */
862
906
  nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000}, NULL);
863
907
  }
@@ -873,10 +917,10 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
873
917
  if (ret != kIOReturnSuccess) {
874
918
  /* a debug message was already printed out for this error */
875
919
  if (LIBUSB_CLASS_HUB == bDeviceClass)
876
- usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
920
+ usbi_dbg (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
877
921
  idVendor, idProduct, darwin_error_str (ret), ret);
878
922
  else
879
- usbi_warn (NULL, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
923
+ usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
880
924
  idVendor, idProduct, darwin_error_str (ret), ret);
881
925
  return darwin_to_libusb (ret);
882
926
  }
@@ -889,20 +933,20 @@ static enum libusb_error darwin_cache_device_descriptor (struct darwin_cached_de
889
933
  return LIBUSB_ERROR_NO_DEVICE;
890
934
  }
891
935
 
892
- usbi_dbg ("cached device descriptor:");
893
- usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType);
894
- usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB);
895
- usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass);
896
- usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass);
897
- usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol);
898
- usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0);
899
- usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor);
900
- usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct);
901
- usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice);
902
- usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer);
903
- usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct);
904
- usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber);
905
- usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
936
+ usbi_dbg (ctx, "cached device descriptor:");
937
+ usbi_dbg (ctx, " bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType);
938
+ usbi_dbg (ctx, " bcdUSB: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdUSB));
939
+ usbi_dbg (ctx, " bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass);
940
+ usbi_dbg (ctx, " bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass);
941
+ usbi_dbg (ctx, " bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol);
942
+ usbi_dbg (ctx, " bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0);
943
+ usbi_dbg (ctx, " idVendor: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idVendor));
944
+ usbi_dbg (ctx, " idProduct: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
945
+ usbi_dbg (ctx, " bcdDevice: 0x%04x", libusb_le16_to_cpu (dev->dev_descriptor.bcdDevice));
946
+ usbi_dbg (ctx, " iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer);
947
+ usbi_dbg (ctx, " iProduct: 0x%02x", dev->dev_descriptor.iProduct);
948
+ usbi_dbg (ctx, " iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber);
949
+ usbi_dbg (ctx, " bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
906
950
 
907
951
  dev->can_enumerate = 1;
908
952
 
@@ -946,7 +990,7 @@ static bool get_device_parent_sessionID(io_service_t service, UInt64 *parent_ses
946
990
  return false;
947
991
  }
948
992
 
949
- static enum libusb_error darwin_get_cached_device(io_service_t service, struct darwin_cached_device **cached_out,
993
+ static enum libusb_error darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out,
950
994
  UInt64 *old_session_id) {
951
995
  struct darwin_cached_device *new_device;
952
996
  UInt64 sessionID = 0, parent_sessionID = 0;
@@ -963,28 +1007,28 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
963
1007
  (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
964
1008
  (void) get_ioregistry_value_number (service, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
965
1009
  if (!get_device_port (service, &port)) {
966
- usbi_dbg("could not get connected port number");
1010
+ usbi_dbg(ctx, "could not get connected port number");
967
1011
  }
968
1012
 
969
- usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
1013
+ usbi_dbg(ctx, "finding cached device for sessionID 0x%" PRIx64, sessionID);
970
1014
 
971
1015
  if (get_device_parent_sessionID(service, &parent_sessionID)) {
972
- usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
1016
+ usbi_dbg(ctx, "parent sessionID: 0x%" PRIx64, parent_sessionID);
973
1017
  }
974
1018
 
975
1019
  usbi_mutex_lock(&darwin_cached_devices_lock);
976
1020
  do {
977
1021
  list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
978
- usbi_dbg("matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
1022
+ usbi_dbg(ctx, "matching sessionID/locationID 0x%" PRIx64 "/0x%x against cached device with sessionID/locationID 0x%" PRIx64 "/0x%x",
979
1023
  sessionID, locationID, new_device->session, new_device->location);
980
1024
  if (new_device->location == locationID && new_device->in_reenumerate) {
981
- usbi_dbg ("found cached device with matching location that is being re-enumerated");
1025
+ usbi_dbg (ctx, "found cached device with matching location that is being re-enumerated");
982
1026
  *old_session_id = new_device->session;
983
1027
  break;
984
1028
  }
985
1029
 
986
1030
  if (new_device->session == sessionID) {
987
- usbi_dbg("using cached device for device");
1031
+ usbi_dbg(ctx, "using cached device for device");
988
1032
  *cached_out = new_device;
989
1033
  break;
990
1034
  }
@@ -993,9 +1037,9 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
993
1037
  if (*cached_out)
994
1038
  break;
995
1039
 
996
- usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID);
1040
+ usbi_dbg(ctx, "caching new device with sessionID 0x%" PRIx64, sessionID);
997
1041
 
998
- device = darwin_device_from_service (service);
1042
+ device = darwin_device_from_service (ctx, service);
999
1043
  if (!device) {
1000
1044
  ret = LIBUSB_ERROR_NO_DEVICE;
1001
1045
  break;
@@ -1019,6 +1063,9 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
1019
1063
  (*device)->GetLocationID (device, &new_device->location);
1020
1064
  new_device->port = port;
1021
1065
  new_device->parent_session = parent_sessionID;
1066
+ } else {
1067
+ /* release the ref to old device's service */
1068
+ IOObjectRelease (new_device->service);
1022
1069
  }
1023
1070
 
1024
1071
  /* keep track of devices regardless of if we successfully enumerate them to
@@ -1027,15 +1074,20 @@ static enum libusb_error darwin_get_cached_device(io_service_t service, struct d
1027
1074
 
1028
1075
  new_device->session = sessionID;
1029
1076
  new_device->device = device;
1077
+ new_device->service = service;
1078
+
1079
+ /* retain the service */
1080
+ IOObjectRetain (service);
1030
1081
 
1031
1082
  /* cache the device descriptor */
1032
- ret = darwin_cache_device_descriptor(new_device);
1083
+ ret = darwin_cache_device_descriptor(ctx, new_device);
1033
1084
  if (ret)
1034
1085
  break;
1035
1086
 
1036
1087
  if (new_device->can_enumerate) {
1037
1088
  snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address,
1038
- new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct,
1089
+ libusb_le16_to_cpu (new_device->dev_descriptor.idVendor),
1090
+ libusb_le16_to_cpu (new_device->dev_descriptor.idProduct),
1039
1091
  new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass);
1040
1092
  }
1041
1093
  } while (0);
@@ -1060,14 +1112,14 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1060
1112
  break;
1061
1113
 
1062
1114
  if (0 != old_session_id) {
1063
- usbi_dbg ("re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
1115
+ usbi_dbg (ctx, "re-using existing device from context %p for with session 0x%" PRIx64 " new session 0x%" PRIx64,
1064
1116
  ctx, old_session_id, cached_device->session);
1065
1117
  /* save the libusb device before the session id is updated */
1066
1118
  dev = usbi_get_device_by_session_id (ctx, (unsigned long) old_session_id);
1067
1119
  }
1068
1120
 
1069
1121
  if (!dev) {
1070
- usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64,
1122
+ usbi_dbg (ctx, "allocating new device in context %p for with session 0x%" PRIx64,
1071
1123
  ctx, cached_device->session);
1072
1124
 
1073
1125
  dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
@@ -1075,22 +1127,33 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1075
1127
  return LIBUSB_ERROR_NO_MEM;
1076
1128
  }
1077
1129
 
1078
- priv = (struct darwin_device_priv *)dev->os_priv;
1130
+ priv = usbi_get_device_priv(dev);
1079
1131
 
1080
1132
  priv->dev = cached_device;
1081
1133
  darwin_ref_cached_device (priv->dev);
1082
1134
  dev->port_number = cached_device->port;
1135
+ /* the location ID encodes the path to the device. the top byte of the location ID contains the bus number
1136
+ (numbered from 0). the remaining bytes can be used to construct the device tree for that bus. */
1083
1137
  dev->bus_number = cached_device->location >> 24;
1084
1138
  assert(cached_device->address <= UINT8_MAX);
1085
1139
  dev->device_address = (uint8_t)cached_device->address;
1086
1140
  } else {
1087
- priv = (struct darwin_device_priv *)dev->os_priv;
1141
+ priv = usbi_get_device_priv(dev);
1142
+ }
1143
+
1144
+ static_assert(sizeof(dev->device_descriptor) == sizeof(cached_device->dev_descriptor),
1145
+ "mismatch between libusb and IOKit device descriptor sizes");
1146
+ memcpy(&dev->device_descriptor, &cached_device->dev_descriptor, LIBUSB_DT_DEVICE_SIZE);
1147
+ usbi_localize_device_descriptor(&dev->device_descriptor);
1148
+ dev->session_data = cached_device->session;
1149
+
1150
+ if (NULL != dev->parent_dev) {
1151
+ libusb_unref_device(dev->parent_dev);
1152
+ dev->parent_dev = NULL;
1088
1153
  }
1089
1154
 
1090
1155
  if (cached_device->parent_session > 0) {
1091
1156
  dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
1092
- } else {
1093
- dev->parent_dev = NULL;
1094
1157
  }
1095
1158
 
1096
1159
  (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
@@ -1099,7 +1162,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1099
1162
  case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
1100
1163
  case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
1101
1164
  case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
1102
- #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
1165
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1103
1166
  case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
1104
1167
  #endif
1105
1168
  #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
@@ -1113,7 +1176,7 @@ static enum libusb_error process_new_device (struct libusb_context *ctx, struct
1113
1176
  if (ret < 0)
1114
1177
  break;
1115
1178
 
1116
- usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
1179
+ usbi_dbg (ctx, "found device with address %d port = %d parent = %p at %p", dev->device_address,
1117
1180
  dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
1118
1181
 
1119
1182
  } while (0);
@@ -1140,7 +1203,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
1140
1203
  return darwin_to_libusb (kresult);
1141
1204
 
1142
1205
  while ((service = IOIteratorNext (deviceIterator))) {
1143
- ret = darwin_get_cached_device (service, &cached_device, &old_session_id);
1206
+ ret = darwin_get_cached_device (ctx, service, &cached_device, &old_session_id);
1144
1207
  if (ret < 0 || !cached_device->can_enumerate) {
1145
1208
  continue;
1146
1209
  }
@@ -1156,7 +1219,7 @@ static enum libusb_error darwin_scan_devices(struct libusb_context *ctx) {
1156
1219
  }
1157
1220
 
1158
1221
  static int darwin_open (struct libusb_device_handle *dev_handle) {
1159
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1222
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1160
1223
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1161
1224
  IOReturn kresult;
1162
1225
 
@@ -1192,20 +1255,20 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
1192
1255
 
1193
1256
  CFRetain (libusb_darwin_acfl);
1194
1257
 
1195
- /* add the cfSource to the aync run loop */
1258
+ /* add the cfSource to the async run loop */
1196
1259
  CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes);
1197
1260
  }
1198
1261
 
1199
1262
  /* device opened successfully */
1200
1263
  dpriv->open_count++;
1201
1264
 
1202
- usbi_dbg ("device open for access");
1265
+ usbi_dbg (HANDLE_CTX(dev_handle), "device open for access");
1203
1266
 
1204
1267
  return 0;
1205
1268
  }
1206
1269
 
1207
1270
  static void darwin_close (struct libusb_device_handle *dev_handle) {
1208
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1271
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1209
1272
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1210
1273
  IOReturn kresult;
1211
1274
  int i;
@@ -1217,6 +1280,10 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
1217
1280
  }
1218
1281
 
1219
1282
  dpriv->open_count--;
1283
+ if (NULL == dpriv->device) {
1284
+ usbi_warn (HANDLE_CTX (dev_handle), "darwin_close device missing IOService");
1285
+ return;
1286
+ }
1220
1287
 
1221
1288
  /* make sure all interfaces are released */
1222
1289
  for (i = 0 ; i < USB_MAXINTERFACES ; i++)
@@ -1244,10 +1311,10 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
1244
1311
  }
1245
1312
  }
1246
1313
 
1247
- static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
1314
+ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config) {
1248
1315
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1249
1316
 
1250
- *config = (int) dpriv->active_config;
1317
+ *config = dpriv->active_config;
1251
1318
 
1252
1319
  return LIBUSB_SUCCESS;
1253
1320
  }
@@ -1255,9 +1322,10 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int
1255
1322
  static enum libusb_error darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
1256
1323
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1257
1324
  IOReturn kresult;
1258
- int i;
1325
+ uint8_t i;
1259
1326
 
1260
- assert(config >= 0 && config <= UINT8_MAX);
1327
+ if (config == -1)
1328
+ config = 0;
1261
1329
 
1262
1330
  /* Setting configuration will invalidate the interface, so we need
1263
1331
  to reclaim it. First, dispose of existing interfaces, if any. */
@@ -1279,7 +1347,7 @@ static enum libusb_error darwin_set_configuration(struct libusb_device_handle *d
1279
1347
  return LIBUSB_SUCCESS;
1280
1348
  }
1281
1349
 
1282
- static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_service_t *usbInterfacep) {
1350
+ static IOReturn darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
1283
1351
  IOUSBFindInterfaceRequest request;
1284
1352
  IOReturn kresult;
1285
1353
  io_iterator_t interface_iterator;
@@ -1316,8 +1384,8 @@ static IOReturn darwin_get_interface (usb_device_t **darwin_device, int ifc, io_
1316
1384
  return kIOReturnSuccess;
1317
1385
  }
1318
1386
 
1319
- static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
1320
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1387
+ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle, uint8_t iface) {
1388
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1321
1389
 
1322
1390
  /* current interface */
1323
1391
  struct darwin_interface *cInterface = &priv->interfaces[iface];
@@ -1328,13 +1396,15 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
1328
1396
  UInt8 dont_care1, dont_care3;
1329
1397
  UInt16 dont_care2;
1330
1398
  int rc;
1399
+ struct libusb_context *ctx = HANDLE_CTX (dev_handle);
1400
+
1331
1401
 
1332
- usbi_dbg ("building table of endpoints.");
1402
+ usbi_dbg (ctx, "building table of endpoints.");
1333
1403
 
1334
1404
  /* retrieve the total number of endpoints on this interface */
1335
1405
  kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep);
1336
1406
  if (kresult != kIOReturnSuccess) {
1337
- usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
1407
+ usbi_err (ctx, "can't get number of endpoints for interface: %s", darwin_error_str(kresult));
1338
1408
  return darwin_to_libusb (kresult);
1339
1409
  }
1340
1410
 
@@ -1367,7 +1437,7 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
1367
1437
  cInterface->endpoint_addrs[i - 1] = (UInt8)(((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
1368
1438
  }
1369
1439
 
1370
- usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
1440
+ usbi_dbg (ctx, "interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift,
1371
1441
  cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK);
1372
1442
  }
1373
1443
 
@@ -1376,44 +1446,44 @@ static enum libusb_error get_endpoints (struct libusb_device_handle *dev_handle,
1376
1446
  return LIBUSB_SUCCESS;
1377
1447
  }
1378
1448
 
1379
- static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) {
1449
+ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
1380
1450
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1381
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1451
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1382
1452
  io_service_t usbInterface = IO_OBJECT_NULL;
1383
1453
  IOReturn kresult;
1384
1454
  enum libusb_error ret;
1385
1455
  IOCFPlugInInterface **plugInInterface = NULL;
1386
1456
  SInt32 score;
1387
1457
 
1388
- assert(iface >= 0 && iface <= UINT8_MAX);
1389
-
1390
1458
  /* current interface */
1391
1459
  struct darwin_interface *cInterface = &priv->interfaces[iface];
1392
1460
 
1393
- kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
1461
+ struct libusb_context *ctx = HANDLE_CTX (dev_handle);
1462
+
1463
+ kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
1394
1464
  if (kresult != kIOReturnSuccess)
1395
1465
  return darwin_to_libusb (kresult);
1396
1466
 
1397
1467
  /* make sure we have an interface */
1398
1468
  if (!usbInterface && dpriv->first_config != 0) {
1399
- usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config);
1469
+ usbi_info (ctx, "no interface found; setting configuration: %d", dpriv->first_config);
1400
1470
 
1401
1471
  /* set the configuration */
1402
- ret = darwin_set_configuration (dev_handle, dpriv->first_config);
1472
+ ret = darwin_set_configuration (dev_handle, (int) dpriv->first_config);
1403
1473
  if (ret != LIBUSB_SUCCESS) {
1404
- usbi_err (HANDLE_CTX (dev_handle), "could not set configuration");
1474
+ usbi_err (ctx, "could not set configuration");
1405
1475
  return ret;
1406
1476
  }
1407
1477
 
1408
- kresult = darwin_get_interface (dpriv->device, (uint8_t)iface, &usbInterface);
1478
+ kresult = darwin_get_interface (dpriv->device, iface, &usbInterface);
1409
1479
  if (kresult != kIOReturnSuccess) {
1410
- usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
1480
+ usbi_err (ctx, "darwin_get_interface: %s", darwin_error_str(kresult));
1411
1481
  return darwin_to_libusb (kresult);
1412
1482
  }
1413
1483
  }
1414
1484
 
1415
1485
  if (!usbInterface) {
1416
- usbi_err (HANDLE_CTX (dev_handle), "interface not found");
1486
+ usbi_info (ctx, "interface not found");
1417
1487
  return LIBUSB_ERROR_NOT_FOUND;
1418
1488
  }
1419
1489
 
@@ -1425,12 +1495,12 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1425
1495
  (void)IOObjectRelease (usbInterface);
1426
1496
 
1427
1497
  if (kresult != kIOReturnSuccess) {
1428
- usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
1498
+ usbi_err (ctx, "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult));
1429
1499
  return darwin_to_libusb (kresult);
1430
1500
  }
1431
1501
 
1432
1502
  if (!plugInInterface) {
1433
- usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found");
1503
+ usbi_err (ctx, "plugin interface not found");
1434
1504
  return LIBUSB_ERROR_NOT_FOUND;
1435
1505
  }
1436
1506
 
@@ -1442,14 +1512,14 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1442
1512
  /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
1443
1513
  (*plugInInterface)->Release (plugInInterface);
1444
1514
  if (kresult != kIOReturnSuccess || !cInterface->interface) {
1445
- usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult));
1515
+ usbi_err (ctx, "QueryInterface: %s", darwin_error_str(kresult));
1446
1516
  return darwin_to_libusb (kresult);
1447
1517
  }
1448
1518
 
1449
1519
  /* claim the interface */
1450
1520
  kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface);
1451
1521
  if (kresult != kIOReturnSuccess) {
1452
- usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult));
1522
+ usbi_info (ctx, "USBInterfaceOpen: %s", darwin_error_str(kresult));
1453
1523
  return darwin_to_libusb (kresult);
1454
1524
  }
1455
1525
 
@@ -1458,7 +1528,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1458
1528
  if (ret) {
1459
1529
  /* this should not happen */
1460
1530
  darwin_release_interface (dev_handle, iface);
1461
- usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
1531
+ usbi_err (ctx, "could not build endpoint table");
1462
1532
  return ret;
1463
1533
  }
1464
1534
 
@@ -1467,7 +1537,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1467
1537
  /* create async event source */
1468
1538
  kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource);
1469
1539
  if (kresult != kIOReturnSuccess) {
1470
- usbi_err (HANDLE_CTX (dev_handle), "could not create async event source");
1540
+ usbi_err (ctx, "could not create async event source");
1471
1541
 
1472
1542
  /* can't continue without an async event source */
1473
1543
  (void)darwin_release_interface (dev_handle, iface);
@@ -1478,13 +1548,13 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1478
1548
  /* add the cfSource to the async thread's run loop */
1479
1549
  CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
1480
1550
 
1481
- usbi_dbg ("interface opened");
1551
+ usbi_dbg (ctx, "interface opened");
1482
1552
 
1483
1553
  return LIBUSB_SUCCESS;
1484
1554
  }
1485
1555
 
1486
- static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) {
1487
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1556
+ static int darwin_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
1557
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1488
1558
  IOReturn kresult;
1489
1559
 
1490
1560
  /* current interface */
@@ -1501,6 +1571,7 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
1501
1571
  if (cInterface->cfSource) {
1502
1572
  CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode);
1503
1573
  CFRelease (cInterface->cfSource);
1574
+ cInterface->cfSource = NULL;
1504
1575
  }
1505
1576
 
1506
1577
  kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface);
@@ -1516,8 +1587,32 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
1516
1587
  return darwin_to_libusb (kresult);
1517
1588
  }
1518
1589
 
1519
- static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) {
1520
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1590
+ static int check_alt_setting_and_clear_halt(struct libusb_device_handle *dev_handle, uint8_t altsetting, struct darwin_interface *cInterface) {
1591
+ enum libusb_error ret;
1592
+ IOReturn kresult;
1593
+ uint8_t current_alt_setting;
1594
+
1595
+ kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &current_alt_setting);
1596
+ if (kresult == kIOReturnSuccess && altsetting != current_alt_setting) {
1597
+ return LIBUSB_ERROR_PIPE;
1598
+ }
1599
+
1600
+ for (int i = 0 ; i < cInterface->num_endpoints ; i++) {
1601
+ ret = darwin_clear_halt(dev_handle, cInterface->endpoint_addrs[i]);
1602
+ if (LIBUSB_SUCCESS != ret) {
1603
+ usbi_warn(HANDLE_CTX (dev_handle), "error clearing pipe halt for endpoint %d", i);
1604
+ if (LIBUSB_ERROR_NOT_FOUND == ret) {
1605
+ /* may need to re-open the interface */
1606
+ return ret;
1607
+ }
1608
+ }
1609
+ }
1610
+
1611
+ return LIBUSB_SUCCESS;
1612
+ }
1613
+
1614
+ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting) {
1615
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1521
1616
  IOReturn kresult;
1522
1617
  enum libusb_error ret;
1523
1618
 
@@ -1527,21 +1622,42 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
1527
1622
  if (!cInterface->interface)
1528
1623
  return LIBUSB_ERROR_NO_DEVICE;
1529
1624
 
1530
- assert(altsetting >= 0 && altsetting <= UINT8_MAX);
1531
- kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, (UInt8)altsetting);
1532
- if (kresult != kIOReturnSuccess)
1533
- darwin_reset_device (dev_handle);
1625
+ kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting);
1626
+ if (kresult == kIOReturnSuccess) {
1627
+ /* update the list of endpoints */
1628
+ ret = get_endpoints (dev_handle, iface);
1629
+ if (ret) {
1630
+ /* this should not happen */
1631
+ darwin_release_interface (dev_handle, iface);
1632
+ usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
1633
+ }
1634
+ return ret;
1635
+ }
1534
1636
 
1535
- /* update list of endpoints */
1536
- ret = get_endpoints (dev_handle, iface);
1537
- if (ret) {
1538
- /* this should not happen */
1539
- darwin_release_interface (dev_handle, iface);
1540
- usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table");
1637
+ usbi_warn (HANDLE_CTX (dev_handle), "SetAlternateInterface: %s", darwin_error_str(kresult));
1638
+
1639
+ ret = darwin_to_libusb(kresult);
1640
+ if (ret != LIBUSB_ERROR_PIPE) {
1541
1641
  return ret;
1542
1642
  }
1543
1643
 
1544
- return darwin_to_libusb (kresult);
1644
+ /* If a device only supports a default setting for the specified interface, then a STALL
1645
+ (kIOUSBPipeStalled) may be returned. Ref: USB 2.0 specs 9.4.10.
1646
+ Mimic the behaviour in e.g. the Linux kernel: in such case, reset all endpoints
1647
+ of the interface (as would have been done per 9.1.1.5) and return success. */
1648
+
1649
+ ret = check_alt_setting_and_clear_halt(dev_handle, altsetting, cInterface);
1650
+ if (LIBUSB_ERROR_NOT_FOUND == ret) {
1651
+ /* For some reason we need to reclaim the interface after the pipe error with some versions of macOS */
1652
+ ret = darwin_claim_interface (dev_handle, iface);
1653
+ if (LIBUSB_SUCCESS != ret) {
1654
+ darwin_release_interface (dev_handle, iface);
1655
+ usbi_err (HANDLE_CTX (dev_handle), "could not reclaim interface: %s", darwin_error_str(kresult));
1656
+ }
1657
+ ret = check_alt_setting_and_clear_halt(dev_handle, altsetting, cInterface);
1658
+ }
1659
+
1660
+ return ret;
1545
1661
  }
1546
1662
 
1547
1663
  static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) {
@@ -1568,10 +1684,12 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1568
1684
  static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t active_config,
1569
1685
  unsigned long claimed_interfaces) {
1570
1686
  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;
1687
+ struct darwin_device_handle_priv *priv = usbi_get_device_handle_priv(dev_handle);
1572
1688
  int open_count = dpriv->open_count;
1573
1689
  int ret;
1574
1690
 
1691
+ struct libusb_context *ctx = HANDLE_CTX (dev_handle);
1692
+
1575
1693
  /* clear claimed interfaces temporarily */
1576
1694
  dev_handle->claimed_interfaces = 0;
1577
1695
 
@@ -1591,28 +1709,28 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
1591
1709
  }
1592
1710
 
1593
1711
  if (dpriv->active_config != active_config) {
1594
- usbi_dbg ("darwin/restore_state: restoring configuration %d...", active_config);
1712
+ usbi_dbg (ctx, "darwin/restore_state: restoring configuration %d...", active_config);
1595
1713
 
1596
1714
  ret = darwin_set_configuration (dev_handle, active_config);
1597
1715
  if (LIBUSB_SUCCESS != ret) {
1598
- usbi_dbg ("darwin/restore_state: could not restore configuration");
1716
+ usbi_dbg (ctx, "darwin/restore_state: could not restore configuration");
1599
1717
  return LIBUSB_ERROR_NOT_FOUND;
1600
1718
  }
1601
1719
  }
1602
1720
 
1603
- usbi_dbg ("darwin/restore_state: reclaiming interfaces");
1721
+ usbi_dbg (ctx, "darwin/restore_state: reclaiming interfaces");
1604
1722
 
1605
1723
  if (claimed_interfaces) {
1606
- for (int iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
1724
+ for (uint8_t iface = 0 ; iface < USB_MAXINTERFACES ; ++iface) {
1607
1725
  if (!(claimed_interfaces & (1U << iface))) {
1608
1726
  continue;
1609
1727
  }
1610
1728
 
1611
- usbi_dbg ("darwin/restore_state: re-claiming interface %d", iface);
1729
+ usbi_dbg (ctx, "darwin/restore_state: re-claiming interface %u", iface);
1612
1730
 
1613
1731
  ret = darwin_claim_interface (dev_handle, iface);
1614
1732
  if (LIBUSB_SUCCESS != ret) {
1615
- usbi_dbg ("darwin/restore_state: could not claim interface %d", iface);
1733
+ usbi_dbg (ctx, "darwin/restore_state: could not claim interface %u", iface);
1616
1734
  return LIBUSB_ERROR_NOT_FOUND;
1617
1735
  }
1618
1736
 
@@ -1620,21 +1738,24 @@ static int darwin_restore_state (struct libusb_device_handle *dev_handle, int8_t
1620
1738
  }
1621
1739
  }
1622
1740
 
1623
- usbi_dbg ("darwin/restore_state: device state restored");
1741
+ usbi_dbg (ctx, "darwin/restore_state: device state restored");
1624
1742
 
1625
1743
  return LIBUSB_SUCCESS;
1626
1744
  }
1627
1745
 
1628
- static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
1746
+ static int darwin_reenumerate_device (struct libusb_device_handle *dev_handle, bool capture) {
1629
1747
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1630
1748
  unsigned long claimed_interfaces = dev_handle->claimed_interfaces;
1631
1749
  int8_t active_config = dpriv->active_config;
1750
+ UInt32 options = 0;
1632
1751
  IOUSBDeviceDescriptor descriptor;
1633
1752
  IOUSBConfigurationDescriptorPtr cached_configuration;
1634
1753
  IOUSBConfigurationDescriptor *cached_configurations;
1635
1754
  IOReturn kresult;
1636
1755
  UInt8 i;
1637
1756
 
1757
+ struct libusb_context *ctx = HANDLE_CTX (dev_handle);
1758
+
1638
1759
  if (dpriv->in_reenumerate) {
1639
1760
  /* ack, two (or more) threads are trying to reset the device! abort! */
1640
1761
  return LIBUSB_ERROR_NOT_FOUND;
@@ -1651,63 +1772,125 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
1651
1772
  memcpy (cached_configurations + i, cached_configuration, sizeof (cached_configurations[i]));
1652
1773
  }
1653
1774
 
1775
+ /* if we need to release capture */
1776
+ if (HAS_CAPTURE_DEVICE()) {
1777
+ if (capture) {
1778
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
1779
+ options |= kUSBReEnumerateCaptureDeviceMask;
1780
+ #endif
1781
+ }
1782
+ } else {
1783
+ capture = false;
1784
+ }
1785
+
1654
1786
  /* from macOS 10.11 ResetDevice no longer does anything so just use USBDeviceReEnumerate */
1655
- kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
1787
+ kresult = (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, options);
1656
1788
  if (kresult != kIOReturnSuccess) {
1657
- usbi_err (HANDLE_CTX (dev_handle), "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
1789
+ usbi_err (ctx, "USBDeviceReEnumerate: %s", darwin_error_str (kresult));
1658
1790
  dpriv->in_reenumerate = false;
1659
1791
  return darwin_to_libusb (kresult);
1660
1792
  }
1661
1793
 
1662
- usbi_dbg ("darwin/reset_device: waiting for re-enumeration to complete...");
1794
+ /* capture mode does not re-enumerate but it does require re-open */
1795
+ if (capture) {
1796
+ usbi_dbg (ctx, "darwin/reenumerate_device: restoring state...");
1797
+ dpriv->in_reenumerate = false;
1798
+ return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
1799
+ }
1800
+
1801
+ usbi_dbg (ctx, "darwin/reenumerate_device: waiting for re-enumeration to complete...");
1802
+
1803
+ struct timespec start;
1804
+ clock_gettime(CLOCK_MONOTONIC, &start);
1663
1805
 
1664
1806
  while (dpriv->in_reenumerate) {
1665
1807
  struct timespec delay = {.tv_sec = 0, .tv_nsec = 1000};
1666
1808
  nanosleep (&delay, NULL);
1809
+
1810
+ struct timespec now;
1811
+ clock_gettime(CLOCK_MONOTONIC, &now);
1812
+ UInt32 elapsed = (now.tv_sec - start.tv_sec) * 1000000 + (now.tv_nsec - start.tv_nsec) / 1000;
1813
+
1814
+ if (elapsed >= DARWIN_REENUMERATE_TIMEOUT_US) {
1815
+ usbi_err (ctx, "darwin/reenumerate_device: timeout waiting for reenumerate");
1816
+ dpriv->in_reenumerate = false;
1817
+ return LIBUSB_ERROR_TIMEOUT;
1818
+ }
1667
1819
  }
1668
1820
 
1669
1821
  /* compare descriptors */
1670
- usbi_dbg ("darwin/reset_device: checking whether descriptors changed");
1822
+ usbi_dbg (ctx, "darwin/reenumerate_device: checking whether descriptors changed");
1671
1823
 
1672
1824
  if (memcmp (&descriptor, &dpriv->dev_descriptor, sizeof (descriptor))) {
1673
1825
  /* device descriptor changed. need to return not found. */
1674
- usbi_dbg ("darwin/reset_device: device descriptor changed");
1826
+ usbi_dbg (ctx, "darwin/reenumerate_device: device descriptor changed");
1675
1827
  return LIBUSB_ERROR_NOT_FOUND;
1676
1828
  }
1677
1829
 
1678
1830
  for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1679
1831
  (void) (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1680
1832
  if (memcmp (cached_configuration, cached_configurations + i, sizeof (cached_configurations[i]))) {
1681
- usbi_dbg ("darwin/reset_device: configuration descriptor %d changed", i);
1833
+ usbi_dbg (ctx, "darwin/reenumerate_device: configuration descriptor %d changed", i);
1682
1834
  return LIBUSB_ERROR_NOT_FOUND;
1683
1835
  }
1684
1836
  }
1685
1837
 
1686
- usbi_dbg ("darwin/reset_device: device reset complete. restoring state...");
1838
+ usbi_dbg (ctx, "darwin/reenumerate_device: device reset complete. restoring state...");
1687
1839
 
1688
1840
  return darwin_restore_state (dev_handle, active_config, claimed_interfaces);
1689
1841
  }
1690
1842
 
1691
- static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) {
1843
+ static int darwin_reset_device (struct libusb_device_handle *dev_handle) {
1692
1844
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1693
- io_service_t usbInterface;
1694
- CFTypeRef driver;
1695
1845
  IOReturn kresult;
1696
1846
 
1697
- assert(interface >= 0 && interface <= UINT8_MAX);
1698
- kresult = darwin_get_interface (dpriv->device, (uint8_t)interface, &usbInterface);
1699
- if (kresult != kIOReturnSuccess) {
1700
- usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult));
1701
-
1847
+ if (dpriv->capture_count > 0) {
1848
+ /* we have to use ResetDevice as USBDeviceReEnumerate() loses the authorization for capture */
1849
+ kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
1702
1850
  return darwin_to_libusb (kresult);
1851
+ } else {
1852
+ return darwin_reenumerate_device (dev_handle, false);
1703
1853
  }
1854
+ }
1704
1855
 
1705
- driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0);
1706
- IOObjectRelease (usbInterface);
1856
+ static io_service_t usb_find_interface_matching_location (const io_name_t class_name, UInt8 interface_number, UInt32 location) {
1857
+ CFMutableDictionaryRef matchingDict = IOServiceMatching (class_name);
1858
+ CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0,
1859
+ &kCFTypeDictionaryKeyCallBacks,
1860
+ &kCFTypeDictionaryValueCallBacks);
1861
+ CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
1862
+ CFTypeRef interfaceCF = CFNumberCreate (NULL, kCFNumberSInt8Type, &interface_number);
1707
1863
 
1708
- if (driver) {
1709
- CFRelease (driver);
1864
+ CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
1865
+ CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
1866
+ CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBHostMatchingPropertyInterfaceNumber), interfaceCF);
1710
1867
 
1868
+ CFRelease (interfaceCF);
1869
+ CFRelease (locationCF);
1870
+ CFRelease (propertyMatchDict);
1871
+
1872
+ return IOServiceGetMatchingService (darwin_default_master_port, matchingDict);
1873
+ }
1874
+
1875
+ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, uint8_t interface) {
1876
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1877
+ io_service_t usb_interface, child = IO_OBJECT_NULL;
1878
+
1879
+ /* locate the IO registry entry for this interface */
1880
+ usb_interface = usb_find_interface_matching_location (kIOUSBHostInterfaceClassName, interface, dpriv->location);
1881
+ if (0 == usb_interface) {
1882
+ /* check for the legacy class entry */
1883
+ usb_interface = usb_find_interface_matching_location (kIOUSBInterfaceClassName, interface, dpriv->location);
1884
+ if (0 == usb_interface) {
1885
+ return LIBUSB_ERROR_NOT_FOUND;
1886
+ }
1887
+ }
1888
+
1889
+ /* if the IO object has a child entry in the IO Registry it has a kernel driver attached */
1890
+ (void) IORegistryEntryGetChildEntry (usb_interface, kIOServicePlane, &child);
1891
+ IOObjectRelease (usb_interface);
1892
+ if (IO_OBJECT_NULL != child) {
1893
+ IOObjectRelease (child);
1711
1894
  return 1;
1712
1895
  }
1713
1896
 
@@ -1715,21 +1898,8 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle,
1715
1898
  return 0;
1716
1899
  }
1717
1900
 
1718
- /* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */
1719
- static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
1720
- UNUSED(dev_handle);
1721
- UNUSED(interface);
1722
- return LIBUSB_ERROR_NOT_SUPPORTED;
1723
- }
1724
-
1725
- static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) {
1726
- UNUSED(dev_handle);
1727
- UNUSED(interface);
1728
- return LIBUSB_ERROR_NOT_SUPPORTED;
1729
- }
1730
-
1731
1901
  static void darwin_destroy_device(struct libusb_device *dev) {
1732
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv;
1902
+ struct darwin_device_priv *dpriv = usbi_get_device_priv(dev);
1733
1903
 
1734
1904
  if (dpriv->dev) {
1735
1905
  /* need to hold the lock in case this is the last reference to the device */
@@ -1745,11 +1915,16 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1745
1915
 
1746
1916
  IOReturn ret;
1747
1917
  uint8_t transferType;
1748
- /* None of the values below are used in libusbx for bulk transfers */
1749
- uint8_t direction, number, interval, pipeRef;
1918
+ uint8_t pipeRef;
1750
1919
  uint16_t maxPacketSize;
1751
1920
 
1752
1921
  struct darwin_interface *cInterface;
1922
+ #if InterfaceVersion >= 550
1923
+ IOUSBEndpointProperties pipeProperties = {.bVersion = kUSBEndpointPropertiesVersion3};
1924
+ #else
1925
+ /* None of the values below are used in libusb for bulk transfers */
1926
+ uint8_t direction, number, interval;
1927
+ #endif
1753
1928
 
1754
1929
  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
1755
1930
  usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
@@ -1757,8 +1932,15 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1757
1932
  return LIBUSB_ERROR_NOT_FOUND;
1758
1933
  }
1759
1934
 
1935
+ #if InterfaceVersion >= 550
1936
+ ret = (*(cInterface->interface))->GetPipePropertiesV3 (cInterface->interface, pipeRef, &pipeProperties);
1937
+
1938
+ transferType = pipeProperties.bTransferType;
1939
+ maxPacketSize = pipeProperties.wMaxPacketSize;
1940
+ #else
1760
1941
  ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
1761
1942
  &transferType, &maxPacketSize, &interval);
1943
+ #endif
1762
1944
 
1763
1945
  if (ret) {
1764
1946
  usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
@@ -1834,7 +2016,7 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
1834
2016
 
1835
2017
  static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1836
2018
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1837
- struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
2019
+ struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
1838
2020
 
1839
2021
  IOReturn kresult;
1840
2022
  uint8_t direction, number, interval, pipeRef, transferType;
@@ -1926,7 +2108,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
1926
2108
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1927
2109
  struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer;
1928
2110
  struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
1929
- struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
2111
+ struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
1930
2112
 
1931
2113
  IOReturn kresult;
1932
2114
 
@@ -2015,8 +2197,10 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
2015
2197
  uint8_t pipeRef, iface;
2016
2198
  IOReturn kresult;
2017
2199
 
2200
+ struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
2201
+
2018
2202
  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) {
2019
- usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
2203
+ usbi_err (ctx, "endpoint not found on any open interface");
2020
2204
 
2021
2205
  return LIBUSB_ERROR_NOT_FOUND;
2022
2206
  }
@@ -2024,7 +2208,7 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
2024
2208
  if (!dpriv->device)
2025
2209
  return LIBUSB_ERROR_NO_DEVICE;
2026
2210
 
2027
- usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef);
2211
+ usbi_warn (ctx, "aborting all transactions on interface %d pipe %d", iface, pipeRef);
2028
2212
 
2029
2213
  /* abort transactions */
2030
2214
  #if InterfaceVersion >= 550
@@ -2034,7 +2218,7 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
2034
2218
  #endif
2035
2219
  (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef);
2036
2220
 
2037
- usbi_dbg ("calling clear pipe stall to clear the data toggle bit");
2221
+ usbi_dbg (ctx, "calling clear pipe stall to clear the data toggle bit");
2038
2222
 
2039
2223
  /* newer versions of darwin support clearing additional bits on the device's endpoint */
2040
2224
  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
@@ -2058,22 +2242,12 @@ static int darwin_cancel_transfer(struct usbi_transfer *itransfer) {
2058
2242
  }
2059
2243
  }
2060
2244
 
2061
- static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) {
2062
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2063
- struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
2064
-
2065
- if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) {
2066
- free (tpriv->isoc_framelist);
2067
- tpriv->isoc_framelist = NULL;
2068
- }
2069
- }
2070
-
2071
2245
  static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) {
2072
2246
  struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
2073
2247
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2074
- struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
2248
+ struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2075
2249
 
2076
- usbi_dbg ("an async io operation has completed");
2250
+ usbi_dbg (TRANSFER_CTX(transfer), "an async io operation has completed");
2077
2251
 
2078
2252
  /* if requested write a zero packet */
2079
2253
  if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
@@ -2096,6 +2270,8 @@ static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer
2096
2270
  if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT)
2097
2271
  result = kIOUSBTransactionTimeout;
2098
2272
 
2273
+ struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
2274
+
2099
2275
  switch (result) {
2100
2276
  case kIOReturnUnderrun:
2101
2277
  case kIOReturnSuccess:
@@ -2103,90 +2279,80 @@ static enum libusb_transfer_status darwin_transfer_status (struct usbi_transfer
2103
2279
  case kIOReturnAborted:
2104
2280
  return LIBUSB_TRANSFER_CANCELLED;
2105
2281
  case kIOUSBPipeStalled:
2106
- usbi_dbg ("transfer error: pipe is stalled");
2282
+ usbi_dbg (ctx, "transfer error: pipe is stalled");
2107
2283
  return LIBUSB_TRANSFER_STALL;
2108
2284
  case kIOReturnOverrun:
2109
- usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun");
2285
+ usbi_warn (ctx, "transfer error: data overrun");
2110
2286
  return LIBUSB_TRANSFER_OVERFLOW;
2111
2287
  case kIOUSBTransactionTimeout:
2112
- usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out");
2288
+ usbi_warn (ctx, "transfer error: timed out");
2113
2289
  itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT;
2114
2290
  return LIBUSB_TRANSFER_TIMED_OUT;
2115
2291
  default:
2116
- usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
2292
+ usbi_warn (ctx, "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
2117
2293
  return LIBUSB_TRANSFER_ERROR;
2118
2294
  }
2119
2295
  }
2120
2296
 
2121
2297
  static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
2122
2298
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2123
- struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
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;
2128
- int i;
2299
+ struct darwin_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2300
+ const unsigned char max_transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
2301
+ const char *transfer_types[] = {"control", "isoc", "bulk", "interrupt", "bulk-stream", NULL};
2302
+ bool is_isoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type;
2303
+ struct libusb_context *ctx = ITRANSFER_CTX (itransfer);
2304
+
2305
+ if (transfer->type > max_transfer_type) {
2306
+ usbi_err (ctx, "unknown endpoint type %d", transfer->type);
2307
+ return LIBUSB_ERROR_INVALID_PARAM;
2308
+ }
2129
2309
 
2130
- if (!isIsoc && !isBulk && !isControl && !isInterrupt) {
2131
- usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
2310
+ if (NULL == tpriv) {
2311
+ usbi_err (ctx, "malformed request is missing transfer priv");
2132
2312
  return LIBUSB_ERROR_INVALID_PARAM;
2133
2313
  }
2134
2314
 
2135
- usbi_dbg ("handling %s completion with kernel status %d",
2136
- isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result);
2315
+ usbi_dbg (ctx, "handling transfer completion type %s with kernel status %d", transfer_types[transfer->type], tpriv->result);
2137
2316
 
2138
- if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) {
2139
- if (isIsoc && tpriv->isoc_framelist) {
2317
+ if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result || kIOUSBTransactionTimeout == tpriv->result) {
2318
+ if (is_isoc && tpriv->isoc_framelist) {
2140
2319
  /* copy isochronous results back */
2141
2320
 
2142
- for (i = 0; i < transfer->num_iso_packets ; i++) {
2321
+ for (int i = 0; i < transfer->num_iso_packets ; i++) {
2143
2322
  struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
2144
2323
  lib_desc->status = darwin_transfer_status (itransfer, tpriv->isoc_framelist[i].frStatus);
2145
2324
  lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
2146
2325
  }
2147
- } else if (!isIsoc)
2326
+ } else if (!is_isoc) {
2148
2327
  itransfer->transferred += tpriv->size;
2328
+ }
2149
2329
  }
2150
2330
 
2151
2331
  /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */
2152
2332
  return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result));
2153
2333
  }
2154
2334
 
2155
- static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
2156
- #if !OSX_USE_CLOCK_GETTIME
2335
+ #if !defined(HAVE_CLOCK_GETTIME)
2336
+ void usbi_get_monotonic_time(struct timespec *tp) {
2157
2337
  mach_timespec_t sys_time;
2158
- clock_serv_t clock_ref;
2159
-
2160
- switch (clk_id) {
2161
- case USBI_CLOCK_REALTIME:
2162
- /* CLOCK_REALTIME represents time since the epoch */
2163
- clock_ref = clock_realtime;
2164
- break;
2165
- case USBI_CLOCK_MONOTONIC:
2166
- /* use system boot time as reference for the monotonic clock */
2167
- clock_ref = clock_monotonic;
2168
- break;
2169
- default:
2170
- return LIBUSB_ERROR_INVALID_PARAM;
2171
- }
2172
2338
 
2173
- clock_get_time (clock_ref, &sys_time);
2339
+ /* use system boot time as reference for the monotonic clock */
2340
+ clock_get_time (clock_monotonic, &sys_time);
2174
2341
 
2175
2342
  tp->tv_sec = sys_time.tv_sec;
2176
2343
  tp->tv_nsec = sys_time.tv_nsec;
2344
+ }
2177
2345
 
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
2346
+ void usbi_get_real_time(struct timespec *tp) {
2347
+ mach_timespec_t sys_time;
2348
+
2349
+ /* CLOCK_REALTIME represents time since the epoch */
2350
+ clock_get_time (clock_realtime, &sys_time);
2351
+
2352
+ tp->tv_sec = sys_time.tv_sec;
2353
+ tp->tv_nsec = sys_time.tv_nsec;
2189
2354
  }
2355
+ #endif
2190
2356
 
2191
2357
  #if InterfaceVersion >= 550
2192
2358
  static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
@@ -2196,7 +2362,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
2196
2362
  uint8_t pipeRef;
2197
2363
  int rc, i;
2198
2364
 
2199
- /* find the mimimum number of supported streams on the endpoint list */
2365
+ /* find the minimum number of supported streams on the endpoint list */
2200
2366
  for (i = 0 ; i < num_endpoints ; ++i) {
2201
2367
  if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
2202
2368
  return rc;
@@ -2247,13 +2413,161 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
2247
2413
  }
2248
2414
  #endif
2249
2415
 
2416
+ #if InterfaceVersion >= 700
2417
+
2418
+ /* macOS APIs for getting entitlement values */
2419
+
2420
+ #if TARGET_OS_OSX
2421
+ #include <Security/Security.h>
2422
+ #else
2423
+ typedef struct __SecTask *SecTaskRef;
2424
+ extern SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator);
2425
+ extern CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error);
2426
+ #endif
2427
+
2428
+ static bool darwin_has_capture_entitlements (void) {
2429
+ SecTaskRef task;
2430
+ CFTypeRef value;
2431
+ bool entitled;
2432
+
2433
+ task = SecTaskCreateFromSelf (kCFAllocatorDefault);
2434
+ if (task == NULL) {
2435
+ return false;
2436
+ }
2437
+ value = SecTaskCopyValueForEntitlement(task, CFSTR("com.apple.vm.device-access"), NULL);
2438
+ CFRelease (task);
2439
+ entitled = value && (CFGetTypeID (value) == CFBooleanGetTypeID ()) && CFBooleanGetValue (value);
2440
+ if (value) {
2441
+ CFRelease (value);
2442
+ }
2443
+ return entitled;
2444
+ }
2445
+
2446
+ static int darwin_reload_device (struct libusb_device_handle *dev_handle) {
2447
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2448
+ enum libusb_error err;
2449
+
2450
+ usbi_mutex_lock(&darwin_cached_devices_lock);
2451
+ (*(dpriv->device))->Release(dpriv->device);
2452
+ dpriv->device = darwin_device_from_service (HANDLE_CTX (dev_handle), dpriv->service);
2453
+ if (!dpriv->device) {
2454
+ err = LIBUSB_ERROR_NO_DEVICE;
2455
+ } else {
2456
+ err = LIBUSB_SUCCESS;
2457
+ }
2458
+ usbi_mutex_unlock(&darwin_cached_devices_lock);
2459
+
2460
+ return err;
2461
+ }
2462
+
2463
+ /* On macOS, we capture an entire device at once, not individual interfaces. */
2464
+
2465
+ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, uint8_t interface) {
2466
+ UNUSED(interface);
2467
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2468
+ IOReturn kresult;
2469
+ enum libusb_error err;
2470
+ struct libusb_context *ctx = HANDLE_CTX (dev_handle);
2471
+
2472
+ if (HAS_CAPTURE_DEVICE()) {
2473
+ } else {
2474
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2475
+ }
2476
+
2477
+ if (dpriv->capture_count == 0) {
2478
+ usbi_dbg (ctx, "attempting to detach kernel driver from device");
2479
+
2480
+ if (darwin_has_capture_entitlements ()) {
2481
+ /* request authorization */
2482
+ kresult = IOServiceAuthorize (dpriv->service, kIOServiceInteractionAllowed);
2483
+ if (kresult != kIOReturnSuccess) {
2484
+ usbi_warn (ctx, "IOServiceAuthorize: %s", darwin_error_str(kresult));
2485
+ return darwin_to_libusb (kresult);
2486
+ }
2487
+
2488
+ /* we need start() to be called again for authorization status to refresh */
2489
+ err = darwin_reload_device (dev_handle);
2490
+ if (err != LIBUSB_SUCCESS) {
2491
+ return err;
2492
+ }
2493
+ } else {
2494
+ usbi_info (ctx, "no capture entitlements. may not be able to detach the kernel driver for this device");
2495
+ if (0 != geteuid()) {
2496
+ usbi_warn (ctx, "USB device capture requires either an entitlement (com.apple.vm.device-access) or root privilege");
2497
+ return LIBUSB_ERROR_ACCESS;
2498
+ }
2499
+ }
2500
+
2501
+ /* reset device to release existing drivers */
2502
+ err = darwin_reenumerate_device (dev_handle, true);
2503
+ if (err != LIBUSB_SUCCESS) {
2504
+ return err;
2505
+ }
2506
+ }
2507
+ dpriv->capture_count++;
2508
+ return LIBUSB_SUCCESS;
2509
+ }
2510
+
2511
+
2512
+ static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, uint8_t interface) {
2513
+ UNUSED(interface);
2514
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2515
+
2516
+ if (HAS_CAPTURE_DEVICE()) {
2517
+ } else {
2518
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2519
+ }
2520
+
2521
+ dpriv->capture_count--;
2522
+ if (dpriv->capture_count > 0) {
2523
+ return LIBUSB_SUCCESS;
2524
+ }
2525
+
2526
+ usbi_dbg (HANDLE_CTX (dev_handle), "reenumerating device for kernel driver attach");
2527
+
2528
+ /* reset device to attach kernel drivers */
2529
+ return darwin_reenumerate_device (dev_handle, false);
2530
+ }
2531
+
2532
+ static int darwin_capture_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
2533
+ enum libusb_error ret;
2534
+ if (dev_handle->auto_detach_kernel_driver && darwin_kernel_driver_active(dev_handle, iface)) {
2535
+ ret = darwin_detach_kernel_driver (dev_handle, iface);
2536
+ if (ret != LIBUSB_SUCCESS) {
2537
+ usbi_info (HANDLE_CTX (dev_handle), "failed to auto-detach the kernel driver for this device, ret=%d", ret);
2538
+ }
2539
+ }
2540
+
2541
+ return darwin_claim_interface (dev_handle, iface);
2542
+ }
2543
+
2544
+ static int darwin_capture_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface) {
2545
+ enum libusb_error ret;
2546
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
2547
+
2548
+ ret = darwin_release_interface (dev_handle, iface);
2549
+ if (ret != LIBUSB_SUCCESS) {
2550
+ return ret;
2551
+ }
2552
+
2553
+ if (dev_handle->auto_detach_kernel_driver && dpriv->capture_count > 0) {
2554
+ ret = darwin_attach_kernel_driver (dev_handle, iface);
2555
+ if (LIBUSB_SUCCESS != ret) {
2556
+ usbi_info (HANDLE_CTX (dev_handle), "on attempt to reattach the kernel driver got ret=%d", ret);
2557
+ }
2558
+ /* ignore the error as the interface was successfully released */
2559
+ }
2560
+
2561
+ return LIBUSB_SUCCESS;
2562
+ }
2563
+
2564
+ #endif
2565
+
2250
2566
  const struct usbi_os_backend usbi_backend = {
2251
2567
  .name = "Darwin",
2252
- .caps = 0,
2568
+ .caps = USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
2253
2569
  .init = darwin_init,
2254
2570
  .exit = darwin_exit,
2255
- .get_device_list = NULL, /* not needed */
2256
- .get_device_descriptor = darwin_get_device_descriptor,
2257
2571
  .get_active_config_descriptor = darwin_get_active_config_descriptor,
2258
2572
  .get_config_descriptor = darwin_get_config_descriptor,
2259
2573
  .hotplug_poll = darwin_hotplug_poll,
@@ -2262,8 +2576,6 @@ const struct usbi_os_backend usbi_backend = {
2262
2576
  .close = darwin_close,
2263
2577
  .get_configuration = darwin_get_configuration,
2264
2578
  .set_configuration = darwin_set_configuration,
2265
- .claim_interface = darwin_claim_interface,
2266
- .release_interface = darwin_release_interface,
2267
2579
 
2268
2580
  .set_interface_altsetting = darwin_set_interface_altsetting,
2269
2581
  .clear_halt = darwin_clear_halt,
@@ -2275,19 +2587,24 @@ const struct usbi_os_backend usbi_backend = {
2275
2587
  #endif
2276
2588
 
2277
2589
  .kernel_driver_active = darwin_kernel_driver_active,
2590
+
2591
+ #if InterfaceVersion >= 700
2278
2592
  .detach_kernel_driver = darwin_detach_kernel_driver,
2279
2593
  .attach_kernel_driver = darwin_attach_kernel_driver,
2594
+ .claim_interface = darwin_capture_claim_interface,
2595
+ .release_interface = darwin_capture_release_interface,
2596
+ #else
2597
+ .claim_interface = darwin_claim_interface,
2598
+ .release_interface = darwin_release_interface,
2599
+ #endif
2280
2600
 
2281
2601
  .destroy_device = darwin_destroy_device,
2282
2602
 
2283
2603
  .submit_transfer = darwin_submit_transfer,
2284
2604
  .cancel_transfer = darwin_cancel_transfer,
2285
- .clear_transfer_priv = darwin_clear_transfer_priv,
2286
2605
 
2287
2606
  .handle_transfer_completion = darwin_handle_transfer_completion,
2288
2607
 
2289
- .clock_gettime = darwin_clock_gettime,
2290
-
2291
2608
  .device_priv_size = sizeof(struct darwin_device_priv),
2292
2609
  .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
2293
2610
  .transfer_priv_size = sizeof(struct darwin_transfer_priv),