usb 2.1.1 → 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 (287) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +4 -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/dist/usb/interface.d.ts +1 -1
  10. package/dist/usb/interface.js +1 -5
  11. package/dist/usb/interface.js.map +1 -1
  12. package/dist/webusb/webusb-device.d.ts +2 -1
  13. package/dist/webusb/webusb-device.js +21 -14
  14. package/dist/webusb/webusb-device.js.map +1 -1
  15. package/libusb/.gitattributes +2 -6
  16. package/libusb/.private/appveyor_build.sh +22 -0
  17. package/libusb/.private/bm.sh +1 -1
  18. package/libusb/.private/ci-build.sh +67 -0
  19. package/libusb/.private/post-rewrite.sh +5 -1
  20. package/libusb/.private/pre-commit.sh +5 -1
  21. package/libusb/.private/wbs.txt +4 -19
  22. package/libusb/.travis.yml +32 -23
  23. package/libusb/AUTHORS +76 -3
  24. package/libusb/ChangeLog +41 -3
  25. package/libusb/INSTALL_WIN.txt +22 -44
  26. package/libusb/Makefile.am +32 -10
  27. package/libusb/{README.md → README} +2 -2
  28. package/libusb/README.git +3 -3
  29. package/libusb/Xcode/common.xcconfig +23 -19
  30. package/libusb/Xcode/config.h +25 -13
  31. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +511 -109
  32. package/libusb/android/README +90 -54
  33. package/libusb/android/config.h +23 -43
  34. package/libusb/android/examples/unrooted_android.c +301 -0
  35. package/libusb/android/examples/unrooted_android.h +36 -0
  36. package/libusb/android/jni/Android.mk +1 -1
  37. package/libusb/android/jni/Application.mk +16 -0
  38. package/libusb/android/jni/examples.mk +63 -29
  39. package/libusb/android/jni/libusb.mk +14 -8
  40. package/libusb/android/jni/tests.mk +13 -24
  41. package/libusb/appveyor.yml +69 -30
  42. package/libusb/autogen.sh +5 -3
  43. package/libusb/bootstrap.sh +6 -2
  44. package/libusb/configure.ac +302 -228
  45. package/libusb/doc/Makefile.in +22 -0
  46. package/libusb/doc/doxygen.cfg.in +460 -223
  47. package/libusb/examples/Makefile.am +6 -13
  48. package/libusb/examples/dpfp.c +276 -73
  49. package/libusb/examples/ezusb.c +18 -8
  50. package/libusb/examples/ezusb.h +6 -17
  51. package/libusb/examples/fxload.c +4 -5
  52. package/libusb/examples/hotplugtest.c +1 -1
  53. package/libusb/examples/sam3u_benchmark.c +59 -24
  54. package/libusb/examples/testlibusb.c +138 -104
  55. package/libusb/examples/xusb.c +26 -22
  56. package/libusb/libusb/Makefile.am +57 -70
  57. package/libusb/libusb/Makefile.am.extra +26 -0
  58. package/libusb/libusb/core.c +420 -423
  59. package/libusb/libusb/descriptor.c +365 -419
  60. package/libusb/libusb/hotplug.c +197 -104
  61. package/libusb/libusb/io.c +491 -528
  62. package/libusb/libusb/libusb-1.0.def +7 -3
  63. package/libusb/libusb/libusb-1.0.rc +1 -9
  64. package/libusb/libusb/libusb.h +295 -226
  65. package/libusb/libusb/libusbi.h +587 -314
  66. package/libusb/libusb/os/darwin_usb.c +634 -317
  67. package/libusb/libusb/os/darwin_usb.h +39 -15
  68. package/libusb/libusb/os/events_posix.c +300 -0
  69. package/libusb/libusb/os/events_posix.h +59 -0
  70. package/libusb/libusb/os/events_windows.c +214 -0
  71. package/libusb/{msvc/missing.h → libusb/os/events_windows.h} +25 -11
  72. package/libusb/libusb/os/haiku_pollfs.cpp +14 -9
  73. package/libusb/libusb/os/haiku_usb.h +12 -12
  74. package/libusb/libusb/os/haiku_usb_backend.cpp +36 -37
  75. package/libusb/libusb/os/haiku_usb_raw.cpp +80 -116
  76. package/libusb/libusb/os/linux_netlink.c +55 -63
  77. package/libusb/libusb/os/linux_udev.c +61 -69
  78. package/libusb/libusb/os/linux_usbfs.c +926 -1015
  79. package/libusb/libusb/os/linux_usbfs.h +74 -57
  80. package/libusb/libusb/os/netbsd_usb.c +103 -168
  81. package/libusb/libusb/os/null_usb.c +111 -0
  82. package/libusb/libusb/os/openbsd_usb.c +71 -120
  83. package/libusb/libusb/os/sunos_usb.c +289 -375
  84. package/libusb/libusb/os/sunos_usb.h +0 -1
  85. package/libusb/libusb/os/threads_posix.c +81 -32
  86. package/libusb/libusb/os/threads_posix.h +19 -23
  87. package/libusb/libusb/os/threads_windows.c +9 -95
  88. package/libusb/libusb/os/threads_windows.h +33 -31
  89. package/libusb/libusb/os/windows_common.c +904 -0
  90. package/libusb/libusb/os/windows_common.h +329 -42
  91. package/libusb/libusb/os/windows_usbdk.c +161 -267
  92. package/libusb/libusb/os/windows_usbdk.h +5 -2
  93. package/libusb/libusb/os/windows_winusb.c +1326 -1190
  94. package/libusb/libusb/os/windows_winusb.h +167 -167
  95. package/libusb/libusb/strerror.c +20 -30
  96. package/libusb/libusb/sync.c +20 -21
  97. package/libusb/libusb/version.h +1 -1
  98. package/libusb/libusb/version_nano.h +1 -1
  99. package/libusb/msvc/.gitattributes +3 -0
  100. package/libusb/msvc/config.h +27 -20
  101. package/libusb/msvc/{hotplugtest_2012.vcxproj → dpfp_2013.vcxproj} +14 -10
  102. package/libusb/msvc/dpfp_2013.vcxproj.filters +26 -0
  103. package/libusb/msvc/{listdevs_2010.vcxproj → dpfp_2015.vcxproj} +14 -9
  104. package/libusb/msvc/dpfp_2015.vcxproj.filters +26 -0
  105. package/libusb/msvc/dpfp_2017.vcxproj +106 -0
  106. package/libusb/msvc/dpfp_2017.vcxproj.filters +26 -0
  107. package/libusb/msvc/dpfp_2019.vcxproj +106 -0
  108. package/libusb/msvc/dpfp_2019.vcxproj.filters +26 -0
  109. package/libusb/msvc/dpfp_threaded_2013.vcxproj +87 -0
  110. package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +26 -0
  111. package/libusb/msvc/dpfp_threaded_2015.vcxproj +87 -0
  112. package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +26 -0
  113. package/libusb/msvc/dpfp_threaded_2017.vcxproj +106 -0
  114. package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +26 -0
  115. package/libusb/msvc/{fxload_2012.vcxproj → dpfp_threaded_2019.vcxproj} +32 -17
  116. package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +26 -0
  117. package/libusb/msvc/fxload_2013.vcxproj +6 -3
  118. package/libusb/msvc/fxload_2013.vcxproj.filters +35 -0
  119. package/libusb/msvc/fxload_2015.vcxproj +6 -3
  120. package/libusb/msvc/fxload_2015.vcxproj.filters +35 -0
  121. package/libusb/msvc/fxload_2017.vcxproj +6 -7
  122. package/libusb/msvc/fxload_2017.vcxproj.filters +35 -0
  123. package/libusb/msvc/{fxload_2010.vcxproj → fxload_2019.vcxproj} +29 -6
  124. package/libusb/msvc/fxload_2019.vcxproj.filters +35 -0
  125. package/libusb/{examples → msvc}/getopt/getopt.c +0 -0
  126. package/libusb/{examples → msvc}/getopt/getopt.h +0 -0
  127. package/libusb/{examples → msvc}/getopt/getopt1.c +0 -0
  128. package/libusb/msvc/getopt_2013.vcxproj +4 -5
  129. package/libusb/msvc/getopt_2013.vcxproj.filters +26 -0
  130. package/libusb/msvc/getopt_2015.vcxproj +4 -4
  131. package/libusb/msvc/getopt_2015.vcxproj.filters +26 -0
  132. package/libusb/msvc/getopt_2017.vcxproj +4 -10
  133. package/libusb/msvc/getopt_2017.vcxproj.filters +26 -0
  134. package/libusb/msvc/{getopt_2012.vcxproj → getopt_2019.vcxproj} +25 -6
  135. package/libusb/msvc/getopt_2019.vcxproj.filters +26 -0
  136. package/libusb/msvc/hotplugtest_2013.vcxproj +6 -3
  137. package/libusb/msvc/hotplugtest_2013.vcxproj.filters +23 -0
  138. package/libusb/msvc/hotplugtest_2015.vcxproj +6 -3
  139. package/libusb/msvc/hotplugtest_2015.vcxproj.filters +23 -0
  140. package/libusb/msvc/hotplugtest_2017.vcxproj +6 -7
  141. package/libusb/msvc/hotplugtest_2017.vcxproj.filters +23 -0
  142. package/libusb/msvc/hotplugtest_2019.vcxproj +105 -0
  143. package/libusb/msvc/hotplugtest_2019.vcxproj.filters +23 -0
  144. package/libusb/msvc/libusb_2013.sln +50 -20
  145. package/libusb/msvc/libusb_2015.sln +51 -21
  146. package/libusb/msvc/libusb_2017.sln +90 -36
  147. package/libusb/msvc/libusb_2019.sln +240 -0
  148. package/libusb/msvc/libusb_dll_2013.vcxproj +6 -9
  149. package/libusb/msvc/libusb_dll_2013.vcxproj.filters +94 -0
  150. package/libusb/msvc/libusb_dll_2015.vcxproj +6 -8
  151. package/libusb/msvc/libusb_dll_2015.vcxproj.filters +94 -0
  152. package/libusb/msvc/libusb_dll_2017.vcxproj +6 -16
  153. package/libusb/msvc/libusb_dll_2017.vcxproj.filters +94 -0
  154. package/libusb/msvc/{libusb_dll_2010.vcxproj → libusb_dll_2019.vcxproj} +27 -9
  155. package/libusb/msvc/libusb_dll_2019.vcxproj.filters +94 -0
  156. package/libusb/msvc/libusb_static_2013.vcxproj +5 -9
  157. package/libusb/msvc/libusb_static_2013.vcxproj.filters +80 -0
  158. package/libusb/msvc/libusb_static_2015.vcxproj +5 -8
  159. package/libusb/msvc/libusb_static_2015.vcxproj.filters +80 -0
  160. package/libusb/msvc/libusb_static_2017.vcxproj +5 -8
  161. package/libusb/msvc/libusb_static_2017.vcxproj.filters +80 -0
  162. package/libusb/msvc/{libusb_static_2010.vcxproj → libusb_static_2019.vcxproj} +26 -9
  163. package/libusb/msvc/libusb_static_2019.vcxproj.filters +80 -0
  164. package/libusb/msvc/listdevs_2013.vcxproj +6 -3
  165. package/libusb/msvc/listdevs_2013.vcxproj.filters +23 -0
  166. package/libusb/msvc/listdevs_2015.vcxproj +6 -3
  167. package/libusb/msvc/listdevs_2015.vcxproj.filters +23 -0
  168. package/libusb/msvc/listdevs_2017.vcxproj +6 -7
  169. package/libusb/msvc/listdevs_2017.vcxproj.filters +23 -0
  170. package/libusb/msvc/listdevs_2019.vcxproj +105 -0
  171. package/libusb/msvc/listdevs_2019.vcxproj.filters +23 -0
  172. package/libusb/msvc/{listdevs_2012.vcxproj → sam3u_benchmark_2013.vcxproj} +13 -9
  173. package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +26 -0
  174. package/libusb/msvc/{hotplugtest_2010.vcxproj → sam3u_benchmark_2015.vcxproj} +13 -8
  175. package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +26 -0
  176. package/libusb/msvc/sam3u_benchmark_2017.vcxproj +106 -0
  177. package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +26 -0
  178. package/libusb/msvc/sam3u_benchmark_2019.vcxproj +106 -0
  179. package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +26 -0
  180. package/libusb/msvc/stress_2013.vcxproj +4 -2
  181. package/libusb/msvc/stress_2013.vcxproj.filters +32 -0
  182. package/libusb/msvc/stress_2015.vcxproj +4 -2
  183. package/libusb/msvc/stress_2015.vcxproj.filters +32 -0
  184. package/libusb/msvc/stress_2017.vcxproj +4 -6
  185. package/libusb/msvc/stress_2017.vcxproj.filters +32 -0
  186. package/libusb/msvc/{stress_2010.vcxproj → stress_2019.vcxproj} +26 -4
  187. package/libusb/msvc/stress_2019.vcxproj.filters +32 -0
  188. package/libusb/msvc/testlibusb_2013.vcxproj +6 -3
  189. package/libusb/msvc/testlibusb_2013.vcxproj.filters +23 -0
  190. package/libusb/msvc/testlibusb_2015.vcxproj +6 -3
  191. package/libusb/msvc/testlibusb_2015.vcxproj.filters +23 -0
  192. package/libusb/msvc/testlibusb_2017.vcxproj +6 -7
  193. package/libusb/msvc/testlibusb_2017.vcxproj.filters +23 -0
  194. package/libusb/msvc/{testlibusb_2010.vcxproj → testlibusb_2019.vcxproj} +28 -5
  195. package/libusb/msvc/testlibusb_2019.vcxproj.filters +23 -0
  196. package/libusb/msvc/xusb_2013.vcxproj +6 -3
  197. package/libusb/msvc/xusb_2013.vcxproj.filters +23 -0
  198. package/libusb/msvc/xusb_2015.vcxproj +6 -3
  199. package/libusb/msvc/xusb_2015.vcxproj.filters +23 -0
  200. package/libusb/msvc/xusb_2017.vcxproj +6 -7
  201. package/libusb/msvc/xusb_2017.vcxproj.filters +23 -0
  202. package/libusb/msvc/{xusb_2010.vcxproj → xusb_2019.vcxproj} +28 -5
  203. package/libusb/msvc/xusb_2019.vcxproj.filters +23 -0
  204. package/libusb/tests/Makefile.am +1 -0
  205. package/libusb/tests/libusb_testlib.h +12 -43
  206. package/libusb/tests/stress.c +59 -50
  207. package/libusb/tests/testlib.c +78 -171
  208. package/libusb.gypi +10 -11
  209. package/package.json +2 -2
  210. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  211. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  212. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  213. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  214. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  215. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  216. package/prebuilds/linux-ia32/node.napi.node +0 -0
  217. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  218. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  219. package/prebuilds/win32-ia32/node.napi.node +0 -0
  220. package/prebuilds/win32-x64/node.napi.node +0 -0
  221. package/src/device.cc +12 -7
  222. package/src/node_usb.cc +10 -0
  223. package/test/usb.coffee +6 -0
  224. package/tsc/index.ts +2 -0
  225. package/tsc/usb/bindings.ts +5 -0
  226. package/tsc/usb/device.ts +6 -0
  227. package/tsc/usb/interface.ts +2 -7
  228. package/tsc/webusb/webusb-device.ts +12 -8
  229. package/libusb/.private/bd.cmd +0 -89
  230. package/libusb/.private/bwince.cmd +0 -57
  231. package/libusb/.private/wbs_wince.txt +0 -42
  232. package/libusb/Brewfile +0 -4
  233. package/libusb/appveyor_cygwin.bat +0 -11
  234. package/libusb/appveyor_minGW.bat +0 -19
  235. package/libusb/doc/Makefile.am +0 -9
  236. package/libusb/examples/dpfp_threaded.c +0 -557
  237. package/libusb/libusb/hotplug.h +0 -99
  238. package/libusb/libusb/os/poll_posix.c +0 -84
  239. package/libusb/libusb/os/poll_posix.h +0 -14
  240. package/libusb/libusb/os/poll_windows.c +0 -447
  241. package/libusb/libusb/os/poll_windows.h +0 -98
  242. package/libusb/libusb/os/wince_usb.c +0 -888
  243. package/libusb/libusb/os/wince_usb.h +0 -126
  244. package/libusb/libusb/os/windows_nt_common.c +0 -1010
  245. package/libusb/libusb/os/windows_nt_common.h +0 -110
  246. package/libusb/libusb/os/windows_nt_shared_types.h +0 -147
  247. package/libusb/msvc/appveyor.bat +0 -27
  248. package/libusb/msvc/ddk_build.cmd +0 -219
  249. package/libusb/msvc/errno.h +0 -102
  250. package/libusb/msvc/fxload_sources +0 -23
  251. package/libusb/msvc/getopt_2005.vcproj +0 -288
  252. package/libusb/msvc/getopt_2010.vcxproj +0 -72
  253. package/libusb/msvc/getopt_sources +0 -24
  254. package/libusb/msvc/hotplugtest_sources +0 -20
  255. package/libusb/msvc/inttypes.h +0 -295
  256. package/libusb/msvc/libusb.dsw +0 -71
  257. package/libusb/msvc/libusb_2005.sln +0 -95
  258. package/libusb/msvc/libusb_2010.sln +0 -105
  259. package/libusb/msvc/libusb_2012.sln +0 -105
  260. package/libusb/msvc/libusb_dll.dsp +0 -194
  261. package/libusb/msvc/libusb_dll_2005.vcproj +0 -464
  262. package/libusb/msvc/libusb_dll_2012.vcxproj +0 -107
  263. package/libusb/msvc/libusb_dll_wince.vcproj +0 -1251
  264. package/libusb/msvc/libusb_sources +0 -43
  265. package/libusb/msvc/libusb_static.dsp +0 -174
  266. package/libusb/msvc/libusb_static_2005.vcproj +0 -390
  267. package/libusb/msvc/libusb_static_2012.vcxproj +0 -98
  268. package/libusb/msvc/libusb_static_wince.vcproj +0 -1179
  269. package/libusb/msvc/libusb_wince.sln +0 -246
  270. package/libusb/msvc/listdevs.dsp +0 -103
  271. package/libusb/msvc/listdevs_2005.vcproj +0 -360
  272. package/libusb/msvc/listdevs_sources +0 -20
  273. package/libusb/msvc/listdevs_wince.vcproj +0 -1120
  274. package/libusb/msvc/missing.c +0 -80
  275. package/libusb/msvc/stdint.h +0 -256
  276. package/libusb/msvc/stress_2005.vcproj +0 -390
  277. package/libusb/msvc/stress_2012.vcxproj +0 -87
  278. package/libusb/msvc/stress_sources +0 -21
  279. package/libusb/msvc/stress_wince.vcproj +0 -1128
  280. package/libusb/msvc/testlibusb_2012.vcxproj +0 -83
  281. package/libusb/msvc/testlibusb_sources +0 -20
  282. package/libusb/msvc/xusb.dsp +0 -102
  283. package/libusb/msvc/xusb_2005.vcproj +0 -344
  284. package/libusb/msvc/xusb_2012.vcxproj +0 -83
  285. package/libusb/msvc/xusb_sources +0 -20
  286. package/libusb/msvc/xusb_wince.vcproj +0 -1120
  287. package/libusb/travis-autogen.sh +0 -39
@@ -28,28 +28,14 @@
28
28
  #include <windows.h>
29
29
  #include <setupapi.h>
30
30
  #include <ctype.h>
31
- #include <errno.h>
32
- #include <fcntl.h>
33
- #include <process.h>
34
31
  #include <stdio.h>
35
- #include <inttypes.h>
36
- #include <objbase.h>
37
- #include <winioctl.h>
38
32
 
39
33
  #include "libusbi.h"
40
- #include "windows_common.h"
41
- #include "windows_nt_common.h"
42
34
  #include "windows_winusb.h"
43
35
 
44
36
  #define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
45
37
 
46
- // The 2 macros below are used in conjunction with safe loops.
47
- #define LOOP_CHECK(fcall) \
48
- { \
49
- r = fcall; \
50
- if (r != LIBUSB_SUCCESS) \
51
- continue; \
52
- }
38
+ // The below macro is used in conjunction with safe loops.
53
39
  #define LOOP_BREAK(err) \
54
40
  { \
55
41
  r = err; \
@@ -57,78 +43,73 @@
57
43
  }
58
44
 
59
45
  // WinUSB-like API prototypes
60
- static int winusbx_init(struct libusb_context *ctx);
46
+ static bool winusbx_init(struct libusb_context *ctx);
61
47
  static void winusbx_exit(void);
62
48
  static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
63
49
  static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
64
- static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
65
- static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
66
- static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
50
+ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
51
+ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
52
+ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
67
53
  static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
68
- static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
54
+ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
69
55
  static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
70
56
  static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
71
57
  static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
72
- static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
73
- static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
58
+ static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
74
59
  static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
75
- static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
60
+ static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
76
61
  // HID API prototypes
77
- static int hid_init(struct libusb_context *ctx);
62
+ static bool hid_init(struct libusb_context *ctx);
78
63
  static void hid_exit(void);
79
64
  static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
80
65
  static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
81
- static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
82
- static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
83
- static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
66
+ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
67
+ static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
68
+ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
84
69
  static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
85
70
  static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
86
71
  static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
87
- static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
88
72
  static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
89
- static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
73
+ static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
90
74
  // Composite API prototypes
91
75
  static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
92
76
  static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
93
- static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
94
- static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
95
- static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
77
+ static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
78
+ static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting);
79
+ static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface);
96
80
  static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
97
81
  static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
98
82
  static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
99
83
  static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
100
- static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
101
- static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
84
+ static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
102
85
  static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
103
- static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
86
+ static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
104
87
 
105
88
  static usbi_mutex_t autoclaim_lock;
106
89
 
107
90
  // API globals
108
- static HMODULE WinUSBX_handle = NULL;
109
91
  static struct winusb_interface WinUSBX[SUB_API_MAX];
110
92
  #define CHECK_WINUSBX_AVAILABLE(sub_api) \
111
93
  do { \
112
94
  if (sub_api == SUB_API_NOTSET) \
113
95
  sub_api = priv->sub_api; \
114
- if (!WinUSBX[sub_api].initialized) \
96
+ if (WinUSBX[sub_api].hDll == NULL) \
115
97
  return LIBUSB_ERROR_ACCESS; \
116
98
  } while (0)
117
99
 
118
- static bool api_hid_available = false;
119
100
  #define CHECK_HID_AVAILABLE \
120
101
  do { \
121
- if (!api_hid_available) \
102
+ if (DLL_HANDLE_NAME(hid) == NULL) \
122
103
  return LIBUSB_ERROR_ACCESS; \
123
104
  } while (0)
124
105
 
125
106
  #if defined(ENABLE_LOGGING)
126
- static const char *guid_to_string(const GUID *guid)
107
+ static const char *guid_to_string(const GUID *guid, char guid_string[MAX_GUID_STRING_LENGTH])
127
108
  {
128
- static char guid_string[MAX_GUID_STRING_LENGTH];
129
-
130
- if (guid == NULL)
131
- return "";
109
+ if (guid == NULL) {
110
+ guid_string[0] = '\0';
111
+ return guid_string;
112
+ }
132
113
 
133
114
  sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
134
115
  (unsigned int)guid->Data1, guid->Data2, guid->Data3,
@@ -139,44 +120,51 @@ static const char *guid_to_string(const GUID *guid)
139
120
  }
140
121
  #endif
141
122
 
142
- /*
143
- * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
144
- * Return an allocated sanitized string or NULL on error.
145
- */
146
- static char *sanitize_path(const char *path)
123
+ static bool string_to_guid(const char guid_string[MAX_GUID_STRING_LENGTH], GUID *guid)
147
124
  {
148
- const char root_prefix[] = {'\\', '\\', '.', '\\'};
149
- size_t j, size;
150
- char *ret_path;
151
- size_t add_root = 0;
125
+ unsigned short tmp[4];
126
+ int num_chars = -1;
127
+ char extra;
128
+ int r;
152
129
 
153
- if (path == NULL)
154
- return NULL;
130
+ // Unfortunately MinGW complains that '%hhx' is not a valid format specifier,
131
+ // even though Visual Studio 2013 and later support it. Rather than complicating
132
+ // the logic in this function with '#ifdef's, use a temporary array on the stack
133
+ // to store the conversions.
134
+ r = sscanf(guid_string, "{%8x-%4hx-%4hx-%4hx-%4hx%4hx%4hx}%n%c",
135
+ (unsigned int *)&guid->Data1, &guid->Data2, &guid->Data3,
136
+ &tmp[0], &tmp[1], &tmp[2], &tmp[3], &num_chars, &extra);
155
137
 
156
- size = strlen(path) + 1;
138
+ if ((r != 7) || (num_chars != 38))
139
+ return false;
157
140
 
158
- // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
159
- if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\'))
160
- || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
161
- add_root = sizeof(root_prefix);
162
- size += add_root;
163
- }
141
+ // Extract the bytes from the 2-byte shorts
142
+ guid->Data4[0] = (unsigned char)((tmp[0] >> 8) & 0xFF);
143
+ guid->Data4[1] = (unsigned char)(tmp[0] & 0xFF);
144
+ guid->Data4[2] = (unsigned char)((tmp[1] >> 8) & 0xFF);
145
+ guid->Data4[3] = (unsigned char)(tmp[1] & 0xFF);
146
+ guid->Data4[4] = (unsigned char)((tmp[2] >> 8) & 0xFF);
147
+ guid->Data4[5] = (unsigned char)(tmp[2] & 0xFF);
148
+ guid->Data4[6] = (unsigned char)((tmp[3] >> 8) & 0xFF);
149
+ guid->Data4[7] = (unsigned char)(tmp[3] & 0xFF);
164
150
 
165
- ret_path = malloc(size);
166
- if (ret_path == NULL)
167
- return NULL;
151
+ return true;
152
+ }
168
153
 
169
- strcpy(&ret_path[add_root], path);
154
+ /*
155
+ * Normalize Microsoft's paths: return a duplicate of the given path
156
+ * with all characters converted to uppercase
157
+ */
158
+ static char *normalize_path(const char *path)
159
+ {
160
+ char *ret_path = _strdup(path);
161
+ char *p;
170
162
 
171
- // Ensure consistency with root prefix
172
- memcpy(ret_path, root_prefix, sizeof(root_prefix));
163
+ if (ret_path == NULL)
164
+ return NULL;
173
165
 
174
- // Same goes for '\' and '#' after the root prefix. Ensure '#' is used
175
- for (j = sizeof(root_prefix); j < size; j++) {
176
- ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too
177
- if (ret_path[j] == '\\')
178
- ret_path[j] = '#';
179
- }
166
+ for (p = ret_path; *p != '\0'; p++)
167
+ *p = (char)toupper((unsigned char)*p);
180
168
 
181
169
  return ret_path;
182
170
  }
@@ -184,40 +172,36 @@ static char *sanitize_path(const char *path)
184
172
  /*
185
173
  * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions
186
174
  */
187
- static BOOL init_dlls(void)
175
+ static bool init_dlls(struct libusb_context *ctx)
188
176
  {
189
- DLL_GET_HANDLE(Cfgmgr32);
190
- DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
191
- DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE);
177
+ DLL_GET_HANDLE(ctx, Cfgmgr32);
178
+ DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, true);
179
+ DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, true);
192
180
 
193
181
  // Prefixed to avoid conflict with header files
194
- DLL_GET_HANDLE(AdvAPI32);
195
- DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
196
- DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
197
-
198
- DLL_GET_HANDLE(OLE32);
199
- DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE);
200
-
201
- DLL_GET_HANDLE(SetupAPI);
202
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE);
203
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE);
204
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE);
205
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE);
206
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
207
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
208
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE);
209
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
210
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
211
-
212
- return TRUE;
182
+ DLL_GET_HANDLE(ctx, AdvAPI32);
183
+ DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExA, true);
184
+ DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, true);
185
+
186
+ DLL_GET_HANDLE(ctx, SetupAPI);
187
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, true);
188
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, true);
189
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, true);
190
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, true);
191
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, true);
192
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, true);
193
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, true);
194
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, true);
195
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, true);
196
+
197
+ return true;
213
198
  }
214
199
 
215
200
  static void exit_dlls(void)
216
201
  {
217
- DLL_FREE_HANDLE(Cfgmgr32);
218
- DLL_FREE_HANDLE(AdvAPI32);
219
- DLL_FREE_HANDLE(OLE32);
220
202
  DLL_FREE_HANDLE(SetupAPI);
203
+ DLL_FREE_HANDLE(AdvAPI32);
204
+ DLL_FREE_HANDLE(Cfgmgr32);
221
205
  }
222
206
 
223
207
  /*
@@ -276,6 +260,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
276
260
  {
277
261
  SP_DEVICE_INTERFACE_DATA dev_interface_data;
278
262
  PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
263
+ char guid_string[MAX_GUID_STRING_LENGTH];
279
264
  DWORD size;
280
265
 
281
266
  dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
@@ -284,7 +269,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
284
269
  if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) {
285
270
  if (GetLastError() != ERROR_NO_MORE_ITEMS) {
286
271
  usbi_err(ctx, "Could not obtain device info data for %s index %lu: %s",
287
- guid_to_string(guid), *_index, windows_error_str(0));
272
+ guid_to_string(guid, guid_string), ULONG_CAST(*_index), windows_error_str(0));
288
273
  return LIBUSB_ERROR_OTHER;
289
274
  }
290
275
 
@@ -300,7 +285,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
300
285
 
301
286
  if (GetLastError() != ERROR_NO_MORE_ITEMS) {
302
287
  usbi_err(ctx, "Could not obtain interface data for %s devInst %lX: %s",
303
- guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
288
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
304
289
  return LIBUSB_ERROR_OTHER;
305
290
  }
306
291
 
@@ -312,7 +297,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
312
297
  // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
313
298
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
314
299
  usbi_err(ctx, "could not access interface data (dummy) for %s devInst %lX: %s",
315
- guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
300
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
316
301
  return LIBUSB_ERROR_OTHER;
317
302
  }
318
303
  } else {
@@ -323,7 +308,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
323
308
  dev_interface_details = malloc(size);
324
309
  if (dev_interface_details == NULL) {
325
310
  usbi_err(ctx, "could not allocate interface data for %s devInst %lX",
326
- guid_to_string(guid), dev_info_data->DevInst);
311
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst));
327
312
  return LIBUSB_ERROR_NO_MEM;
328
313
  }
329
314
 
@@ -331,17 +316,17 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
331
316
  if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data,
332
317
  dev_interface_details, size, NULL, NULL)) {
333
318
  usbi_err(ctx, "could not access interface data (actual) for %s devInst %lX: %s",
334
- guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
319
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
335
320
  free(dev_interface_details);
336
321
  return LIBUSB_ERROR_OTHER;
337
322
  }
338
323
 
339
- *dev_interface_path = sanitize_path(dev_interface_details->DevicePath);
324
+ *dev_interface_path = normalize_path(dev_interface_details->DevicePath);
340
325
  free(dev_interface_details);
341
326
 
342
327
  if (*dev_interface_path == NULL) {
343
328
  usbi_err(ctx, "could not allocate interface path for %s devInst %lX",
344
- guid_to_string(guid), dev_info_data->DevInst);
329
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst));
345
330
  return LIBUSB_ERROR_NO_MEM;
346
331
  }
347
332
 
@@ -349,95 +334,106 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
349
334
  }
350
335
 
351
336
  /* For libusb0 filter */
352
- static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
353
- HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path)
337
+ static int get_interface_details_filter(struct libusb_context *ctx, HDEVINFO *dev_info,
338
+ DWORD _index, char *filter_path, char **dev_interface_path)
354
339
  {
340
+ const GUID *libusb0_guid = &GUID_DEVINTERFACE_LIBUSB0_FILTER;
355
341
  SP_DEVICE_INTERFACE_DATA dev_interface_data;
356
- SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details;
342
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
343
+ HKEY hkey_dev_interface;
357
344
  DWORD size;
345
+ int err = LIBUSB_ERROR_OTHER;
358
346
 
359
- if (_index == 0)
360
- *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
361
-
362
- if (dev_info_data != NULL) {
363
- dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
364
- if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
365
- if (GetLastError() != ERROR_NO_MORE_ITEMS)
366
- usbi_err(ctx, "Could not obtain device info data for index %u: %s",
367
- _index, windows_error_str(0));
368
-
369
- pSetupDiDestroyDeviceInfoList(*dev_info);
370
- *dev_info = INVALID_HANDLE_VALUE;
371
- return NULL;
347
+ if (_index == 0) {
348
+ *dev_info = pSetupDiGetClassDevsA(libusb0_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
349
+ if (*dev_info == INVALID_HANDLE_VALUE) {
350
+ usbi_err(ctx, "could not obtain device info set: %s", windows_error_str(0));
351
+ return LIBUSB_ERROR_OTHER;
372
352
  }
373
353
  }
374
354
 
375
355
  dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
376
- if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
377
- if (GetLastError() != ERROR_NO_MORE_ITEMS)
378
- usbi_err(ctx, "Could not obtain interface data for index %u: %s",
379
- _index, windows_error_str(0));
356
+ if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, libusb0_guid, _index, &dev_interface_data)) {
357
+ if (GetLastError() != ERROR_NO_MORE_ITEMS) {
358
+ usbi_err(ctx, "Could not obtain interface data for index %lu: %s",
359
+ ULONG_CAST(_index), windows_error_str(0));
360
+ goto err_exit;
361
+ }
380
362
 
381
363
  pSetupDiDestroyDeviceInfoList(*dev_info);
382
364
  *dev_info = INVALID_HANDLE_VALUE;
383
- return NULL;
365
+ return LIBUSB_SUCCESS;
384
366
  }
385
367
 
386
368
  // Read interface data (dummy + actual) to access the device path
387
369
  if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
388
370
  // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
389
371
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
390
- usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
391
- _index, windows_error_str(0));
372
+ usbi_err(ctx, "could not access interface data (dummy) for index %lu: %s",
373
+ ULONG_CAST(_index), windows_error_str(0));
392
374
  goto err_exit;
393
375
  }
394
376
  } else {
395
- usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
377
+ usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong");
396
378
  goto err_exit;
397
379
  }
398
380
 
399
- dev_interface_details = calloc(1, size);
381
+ dev_interface_details = malloc(size);
400
382
  if (dev_interface_details == NULL) {
401
- usbi_err(ctx, "could not allocate interface data for index %u.", _index);
383
+ usbi_err(ctx, "could not allocate interface data for index %lu", ULONG_CAST(_index));
384
+ err = LIBUSB_ERROR_NO_MEM;
402
385
  goto err_exit;
403
386
  }
404
387
 
405
388
  dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
406
- if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL))
407
- usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
408
- _index, windows_error_str(0));
389
+ if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, NULL, NULL)) {
390
+ usbi_err(ctx, "could not access interface data (actual) for index %lu: %s",
391
+ ULONG_CAST(_index), windows_error_str(0));
392
+ free(dev_interface_details);
393
+ goto err_exit;
394
+ }
395
+
396
+ *dev_interface_path = normalize_path(dev_interface_details->DevicePath);
397
+ free(dev_interface_details);
398
+
399
+ if (*dev_interface_path == NULL) {
400
+ usbi_err(ctx, "could not allocate interface path for index %lu", ULONG_CAST(_index));
401
+ err = LIBUSB_ERROR_NO_MEM;
402
+ goto err_exit;
403
+ }
409
404
 
410
405
  // [trobinso] lookup the libusb0 symbolic index.
411
- if (dev_interface_details) {
412
- HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
413
- if (hkey_device_interface != INVALID_HANDLE_VALUE) {
414
- DWORD libusb0_symboliclink_index = 0;
415
- DWORD value_length = sizeof(DWORD);
416
- DWORD value_type = 0;
417
- LONG status;
418
-
419
- status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type,
420
- (LPBYTE)&libusb0_symboliclink_index, &value_length);
421
- if (status == ERROR_SUCCESS) {
422
- if (libusb0_symboliclink_index < 256) {
423
- // libusb0.sys is connected to this device instance.
424
- // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
425
- sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
426
- usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
427
- } else {
428
- // libusb0.sys was connected to this device instance at one time; but not anymore.
429
- }
406
+ hkey_dev_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
407
+ if (hkey_dev_interface != INVALID_HANDLE_VALUE) {
408
+ DWORD libusb0_symboliclink_index = 0;
409
+ DWORD value_length = sizeof(DWORD);
410
+ LONG status;
411
+
412
+ status = pRegQueryValueExA(hkey_dev_interface, "LUsb0", NULL, NULL,
413
+ (LPBYTE)&libusb0_symboliclink_index, &value_length);
414
+ if (status == ERROR_SUCCESS) {
415
+ if (libusb0_symboliclink_index < 256) {
416
+ // libusb0.sys is connected to this device instance.
417
+ // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
418
+ sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
419
+ usbi_dbg(ctx, "assigned libusb0 symbolic link %s", filter_path);
420
+ } else {
421
+ // libusb0.sys was connected to this device instance at one time; but not anymore.
430
422
  }
431
- pRegCloseKey(hkey_device_interface);
432
423
  }
424
+ pRegCloseKey(hkey_dev_interface);
425
+ } else {
426
+ usbi_warn(ctx, "could not open device interface registry key for index %lu: %s",
427
+ ULONG_CAST(_index), windows_error_str(0));
428
+ // TODO: should this be an error?
433
429
  }
434
430
 
435
- return dev_interface_details;
431
+ return LIBUSB_SUCCESS;
436
432
 
437
433
  err_exit:
438
434
  pSetupDiDestroyDeviceInfoList(*dev_info);
439
435
  *dev_info = INVALID_HANDLE_VALUE;
440
- return NULL;
436
+ return err;
441
437
  }
442
438
 
443
439
  /*
@@ -469,7 +465,8 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc,
469
465
  {
470
466
  const struct libusb_interface *intf;
471
467
  const struct libusb_interface_descriptor *intf_desc;
472
- int i, j, k;
468
+ uint8_t i, k;
469
+ int j;
473
470
 
474
471
  for (i = 0; i < conf_desc->bNumInterfaces; i++) {
475
472
  intf = &conf_desc->interface[i];
@@ -477,31 +474,52 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc,
477
474
  intf_desc = &intf->altsetting[j];
478
475
  for (k = 0; k < intf_desc->bNumEndpoints; k++) {
479
476
  if (intf_desc->endpoint[k].bEndpointAddress == ep) {
480
- usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
477
+ usbi_dbg(NULL, "found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
481
478
  return intf_desc->bInterfaceNumber;
482
479
  }
483
480
  }
484
481
  }
485
482
  }
486
483
 
487
- usbi_dbg("endpoint %02X not found on any interface", ep);
484
+ usbi_dbg(NULL, "endpoint %02X not found on any interface", ep);
488
485
  return LIBUSB_ERROR_NOT_FOUND;
489
486
  }
490
487
 
488
+ /*
489
+ * Open a device and associate the HANDLE with the context's I/O completion port
490
+ */
491
+ static HANDLE windows_open(struct libusb_device_handle *dev_handle, const char *path, DWORD access)
492
+ {
493
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
494
+ struct windows_context_priv *priv = usbi_get_context_priv(ctx);
495
+ HANDLE handle;
496
+
497
+ handle = CreateFileA(path, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
498
+ if (handle == INVALID_HANDLE_VALUE)
499
+ return handle;
500
+
501
+ if (CreateIoCompletionPort(handle, priv->completion_port, (ULONG_PTR)dev_handle, 0) == NULL) {
502
+ usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
503
+ CloseHandle(handle);
504
+ return INVALID_HANDLE_VALUE;
505
+ }
506
+
507
+ return handle;
508
+ }
509
+
491
510
  /*
492
511
  * Populate the endpoints addresses of the device_priv interface helper structs
493
512
  */
494
- static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
513
+ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
495
514
  {
496
- int i, r;
497
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
515
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
498
516
  struct libusb_config_descriptor *conf_desc;
499
517
  const struct libusb_interface_descriptor *if_desc;
500
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
518
+ int i, r;
501
519
 
502
520
  r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc);
503
521
  if (r != LIBUSB_SUCCESS) {
504
- usbi_warn(ctx, "could not read config descriptor: error %d", r);
522
+ usbi_warn(HANDLE_CTX(dev_handle), "could not read config descriptor: error %d", r);
505
523
  return r;
506
524
  }
507
525
 
@@ -509,22 +527,18 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
509
527
  safe_free(priv->usb_interface[iface].endpoint);
510
528
 
511
529
  if (if_desc->bNumEndpoints == 0) {
512
- usbi_dbg("no endpoints found for interface %d", iface);
513
- libusb_free_config_descriptor(conf_desc);
514
- priv->usb_interface[iface].current_altsetting = altsetting;
515
- return LIBUSB_SUCCESS;
516
- }
517
-
518
- priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
519
- if (priv->usb_interface[iface].endpoint == NULL) {
520
- libusb_free_config_descriptor(conf_desc);
521
- return LIBUSB_ERROR_NO_MEM;
522
- }
523
-
524
- priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
525
- for (i = 0; i < if_desc->bNumEndpoints; i++) {
526
- priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
527
- usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface);
530
+ usbi_dbg(HANDLE_CTX(dev_handle), "no endpoints found for interface %u", iface);
531
+ } else {
532
+ priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
533
+ if (priv->usb_interface[iface].endpoint == NULL) {
534
+ libusb_free_config_descriptor(conf_desc);
535
+ return LIBUSB_ERROR_NO_MEM;
536
+ }
537
+ priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
538
+ for (i = 0; i < if_desc->bNumEndpoints; i++) {
539
+ priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
540
+ usbi_dbg(HANDLE_CTX(dev_handle), "(re)assigned endpoint %02X to interface %u", priv->usb_interface[iface].endpoint[i], iface);
541
+ }
528
542
  }
529
543
  libusb_free_config_descriptor(conf_desc);
530
544
 
@@ -542,10 +556,10 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
542
556
  // return -1 if not found, driver match number otherwise
543
557
  static int get_sub_api(char *driver, int api)
544
558
  {
545
- int i;
546
559
  const char sep_str[2] = {LIST_SEPARATOR, 0};
547
560
  char *tok, *tmp_str;
548
561
  size_t len = strlen(driver);
562
+ int i;
549
563
 
550
564
  if (len == 0)
551
565
  return SUB_API_NOTSET;
@@ -574,10 +588,9 @@ static int get_sub_api(char *driver, int api)
574
588
  */
575
589
  static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
576
590
  {
577
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
578
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(
579
- transfer->dev_handle);
580
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
591
+ struct winusb_device_handle_priv *handle_priv =
592
+ get_winusb_device_handle_priv(transfer->dev_handle);
593
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
581
594
  int current_interface = *interface_number;
582
595
  int r = LIBUSB_SUCCESS;
583
596
 
@@ -595,15 +608,15 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i
595
608
  // Must claim an interface of the same API type
596
609
  if ((priv->usb_interface[current_interface].apib->id == api_type)
597
610
  && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
598
- usbi_dbg("auto-claimed interface %d for control request", current_interface);
611
+ usbi_dbg(TRANSFER_CTX(transfer), "auto-claimed interface %d for control request", current_interface);
599
612
  if (handle_priv->autoclaim_count[current_interface] != 0)
600
- usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
613
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - autoclaim_count was nonzero");
601
614
  handle_priv->autoclaim_count[current_interface]++;
602
615
  break;
603
616
  }
604
617
  }
605
618
  if (current_interface == USB_MAXINTERFACES) {
606
- usbi_err(ctx, "could not auto-claim any interface");
619
+ usbi_err(TRANSFER_CTX(transfer), "could not auto-claim any interface");
607
620
  r = LIBUSB_ERROR_NOT_FOUND;
608
621
  }
609
622
  } else {
@@ -620,10 +633,10 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i
620
633
 
621
634
  static void auto_release(struct usbi_transfer *itransfer)
622
635
  {
623
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
636
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
624
637
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
625
638
  libusb_device_handle *dev_handle = transfer->dev_handle;
626
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
639
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
627
640
  int r;
628
641
 
629
642
  usbi_mutex_lock(&autoclaim_lock);
@@ -632,9 +645,9 @@ static void auto_release(struct usbi_transfer *itransfer)
632
645
  if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
633
646
  r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
634
647
  if (r == LIBUSB_SUCCESS)
635
- usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
648
+ usbi_dbg(ITRANSFER_CTX(itransfer), "auto-released interface %d", transfer_priv->interface_number);
636
649
  else
637
- usbi_dbg("failed to auto-release interface %d (%s)",
650
+ usbi_dbg(ITRANSFER_CTX(itransfer), "failed to auto-release interface %d (%s)",
638
651
  transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
639
652
  }
640
653
  }
@@ -648,22 +661,22 @@ static int winusb_init(struct libusb_context *ctx)
648
661
  {
649
662
  int i;
650
663
 
651
- // We need a lock for proper auto-release
652
- usbi_mutex_init(&autoclaim_lock);
653
-
654
664
  // Load DLL imports
655
- if (!init_dlls()) {
665
+ if (!init_dlls(ctx)) {
656
666
  usbi_err(ctx, "could not resolve DLL functions");
657
667
  return LIBUSB_ERROR_OTHER;
658
668
  }
659
669
 
660
670
  // Initialize the low level APIs (we don't care about errors at this stage)
661
671
  for (i = 0; i < USB_API_MAX; i++) {
662
- if (usb_api_backend[i].init && usb_api_backend[i].init(ctx))
672
+ if (usb_api_backend[i].init && !usb_api_backend[i].init(ctx))
663
673
  usbi_warn(ctx, "error initializing %s backend",
664
674
  usb_api_backend[i].designation);
665
675
  }
666
676
 
677
+ // We need a lock for proper auto-release
678
+ usbi_mutex_init(&autoclaim_lock);
679
+
667
680
  return LIBUSB_SUCCESS;
668
681
  }
669
682
 
@@ -674,13 +687,16 @@ static void winusb_exit(struct libusb_context *ctx)
674
687
  {
675
688
  int i;
676
689
 
690
+ UNUSED(ctx);
691
+
692
+ usbi_mutex_destroy(&autoclaim_lock);
693
+
677
694
  for (i = 0; i < USB_API_MAX; i++) {
678
695
  if (usb_api_backend[i].exit)
679
696
  usb_api_backend[i].exit();
680
697
  }
681
698
 
682
699
  exit_dlls();
683
- usbi_mutex_destroy(&autoclaim_lock);
684
700
  }
685
701
 
686
702
  /*
@@ -689,31 +705,34 @@ static void winusb_exit(struct libusb_context *ctx)
689
705
  static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
690
706
  {
691
707
  struct libusb_context *ctx = DEVICE_CTX(dev);
692
- struct winusb_device_priv *priv = _device_priv(dev);
708
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
693
709
  DWORD size, ret_size;
694
- uint8_t i;
710
+ uint8_t i, num_configurations;
695
711
 
696
712
  USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
697
713
  PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request
698
714
  PUSB_CONFIGURATION_DESCRIPTOR cd_data;
699
715
 
700
- if (dev->num_configurations == 0)
716
+ num_configurations = dev->device_descriptor.bNumConfigurations;
717
+ if (num_configurations == 0)
701
718
  return;
702
719
 
703
- priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
720
+ assert(sizeof(USB_DESCRIPTOR_REQUEST) == USB_DESCRIPTOR_REQUEST_SIZE);
721
+
722
+ priv->config_descriptor = calloc(num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
704
723
  if (priv->config_descriptor == NULL) {
705
724
  usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
706
725
  return;
707
726
  }
708
727
 
709
- for (i = 0; i <= dev->num_configurations; i++) {
728
+ for (i = 0; i <= num_configurations; i++) {
710
729
  safe_free(cd_buf_actual);
711
730
 
712
- if (i == dev->num_configurations)
731
+ if (i == num_configurations)
713
732
  break;
714
733
 
715
734
  size = sizeof(cd_buf_short);
716
- memset(&cd_buf_short, 0, size);
735
+ memset(&cd_buf_short.desc, 0, sizeof(cd_buf_short.desc));
717
736
 
718
737
  cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number;
719
738
  cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
@@ -757,7 +776,7 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
757
776
  continue;
758
777
  }
759
778
 
760
- cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
779
+ cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + USB_DESCRIPTOR_REQUEST_SIZE);
761
780
 
762
781
  if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) {
763
782
  usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id);
@@ -769,17 +788,250 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
769
788
  continue;
770
789
  }
771
790
 
772
- usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
791
+ usbi_dbg(ctx, "cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
773
792
  i, cd_data->bConfigurationValue, cd_data->wTotalLength);
774
793
 
775
794
  // Cache the descriptor
776
- priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
777
- if (priv->config_descriptor[i] != NULL) {
778
- memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
779
- } else {
780
- usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
795
+ priv->config_descriptor[i] = cd_data;
796
+ cd_buf_actual = NULL;
797
+ }
798
+ }
799
+
800
+ #define ROOT_HUB_FS_CONFIG_DESC_LENGTH 0x19
801
+ #define ROOT_HUB_HS_CONFIG_DESC_LENGTH 0x19
802
+ #define ROOT_HUB_SS_CONFIG_DESC_LENGTH 0x1f
803
+ #define CONFIG_DESC_WTOTAL_LENGTH_OFFSET 0x02
804
+ #define CONFIG_DESC_EP_MAX_PACKET_OFFSET 0x16
805
+ #define CONFIG_DESC_EP_BINTERVAL_OFFSET 0x18
806
+
807
+ static const uint8_t root_hub_config_descriptor_template[] = {
808
+ // Configuration Descriptor
809
+ LIBUSB_DT_CONFIG_SIZE, // bLength
810
+ LIBUSB_DT_CONFIG, // bDescriptorType
811
+ 0x00, 0x00, // wTotalLength (filled in)
812
+ 0x01, // bNumInterfaces
813
+ 0x01, // bConfigurationValue
814
+ 0x00, // iConfiguration
815
+ 0xc0, // bmAttributes (reserved + self-powered)
816
+ 0x00, // bMaxPower
817
+ // Interface Descriptor
818
+ LIBUSB_DT_INTERFACE_SIZE, // bLength
819
+ LIBUSB_DT_INTERFACE, // bDescriptorType
820
+ 0x00, // bInterfaceNumber
821
+ 0x00, // bAlternateSetting
822
+ 0x01, // bNumEndpoints
823
+ LIBUSB_CLASS_HUB, // bInterfaceClass
824
+ 0x00, // bInterfaceSubClass
825
+ 0x00, // bInterfaceProtocol
826
+ 0x00, // iInterface
827
+ // Endpoint Descriptor
828
+ LIBUSB_DT_ENDPOINT_SIZE, // bLength
829
+ LIBUSB_DT_ENDPOINT, // bDescriptorType
830
+ 0x81, // bEndpointAddress
831
+ 0x03, // bmAttributes (Interrupt)
832
+ 0x00, 0x00, // wMaxPacketSize (filled in)
833
+ 0x00, // bInterval (filled in)
834
+ // SuperSpeed Endpoint Companion Descriptor
835
+ LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE, // bLength
836
+ LIBUSB_DT_SS_ENDPOINT_COMPANION, // bDescriptorType
837
+ 0x00, // bMaxBurst
838
+ 0x00, // bmAttributes
839
+ 0x02, 0x00 // wBytesPerInterval
840
+ };
841
+
842
+ static int alloc_root_hub_config_desc(struct libusb_device *dev, ULONG num_ports,
843
+ uint8_t config_desc_length, uint8_t ep_interval)
844
+ {
845
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
846
+ uint8_t *ptr;
847
+
848
+ priv->config_descriptor = malloc(sizeof(*priv->config_descriptor));
849
+ if (priv->config_descriptor == NULL)
850
+ return LIBUSB_ERROR_NO_MEM;
851
+
852
+ // Most config descriptors come from cache_config_descriptors() which obtains the
853
+ // descriptors from the hub using an allocated USB_DESCRIPTOR_REQUEST structure.
854
+ // To avoid an extra malloc + memcpy we just hold on to the USB_DESCRIPTOR_REQUEST
855
+ // structure we already have and back up the pointer in windows_device_priv_release()
856
+ // when freeing the descriptors. To keep a single execution path, we need to offset
857
+ // the pointer here by the same amount.
858
+ ptr = malloc(USB_DESCRIPTOR_REQUEST_SIZE + config_desc_length);
859
+ if (ptr == NULL)
860
+ return LIBUSB_ERROR_NO_MEM;
861
+
862
+ ptr += USB_DESCRIPTOR_REQUEST_SIZE;
863
+
864
+ memcpy(ptr, root_hub_config_descriptor_template, config_desc_length);
865
+ ptr[CONFIG_DESC_WTOTAL_LENGTH_OFFSET] = config_desc_length;
866
+ ptr[CONFIG_DESC_EP_MAX_PACKET_OFFSET] = (uint8_t)((num_ports + 7) / 8);
867
+ ptr[CONFIG_DESC_EP_BINTERVAL_OFFSET] = ep_interval;
868
+
869
+ priv->config_descriptor[0] = (PUSB_CONFIGURATION_DESCRIPTOR)ptr;
870
+ priv->active_config = 1;
871
+
872
+ return 0;
873
+ }
874
+
875
+ static int init_root_hub(struct libusb_device *dev)
876
+ {
877
+ struct libusb_context *ctx = DEVICE_CTX(dev);
878
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
879
+ USB_NODE_CONNECTION_INFORMATION_EX conn_info;
880
+ USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
881
+ USB_NODE_INFORMATION hub_info;
882
+ enum libusb_speed speed = LIBUSB_SPEED_UNKNOWN;
883
+ uint8_t config_desc_length;
884
+ uint8_t ep_interval;
885
+ HANDLE handle;
886
+ ULONG port_number, num_ports;
887
+ DWORD size;
888
+ int r;
889
+
890
+ // Determining the speed of a root hub is painful. Microsoft does not directly report the speed
891
+ // capabilities of the root hub itself, only its ports and/or connected devices. Therefore we
892
+ // are forced to query each individual port of the root hub to try and infer the root hub's
893
+ // speed. Note that we have to query all ports because the presence of a device on that port
894
+ // changes if/how Windows returns any useful speed information.
895
+ handle = CreateFileA(priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
896
+ if (handle == INVALID_HANDLE_VALUE) {
897
+ usbi_err(ctx, "could not open root hub %s: %s", priv->path, windows_error_str(0));
898
+ return LIBUSB_ERROR_ACCESS;
899
+ }
900
+
901
+ if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_INFORMATION, NULL, 0, &hub_info, sizeof(hub_info), &size, NULL)) {
902
+ usbi_warn(ctx, "could not get root hub info for '%s': %s", priv->dev_id, windows_error_str(0));
903
+ CloseHandle(handle);
904
+ return LIBUSB_ERROR_ACCESS;
905
+ }
906
+
907
+ num_ports = hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts;
908
+ usbi_dbg(ctx, "root hub '%s' reports %lu ports", priv->dev_id, ULONG_CAST(num_ports));
909
+
910
+ if (windows_version >= WINDOWS_8) {
911
+ // Windows 8 and later is better at reporting the speed capabilities of the root hub,
912
+ // but it is not perfect. If no device is attached to the port being queried, the
913
+ // returned information will only indicate whether that port supports USB 3.0 signalling.
914
+ // That is not enough information to distinguish between SuperSpeed and SuperSpeed Plus.
915
+ for (port_number = 1; port_number <= num_ports; port_number++) {
916
+ conn_info_v2.ConnectionIndex = port_number;
917
+ conn_info_v2.Length = sizeof(conn_info_v2);
918
+ conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
919
+ if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
920
+ &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) {
921
+ usbi_warn(ctx, "could not get node connection information (V2) for root hub '%s' port %lu: %s",
922
+ priv->dev_id, ULONG_CAST(port_number), windows_error_str(0));
923
+ break;
924
+ }
925
+
926
+ if (conn_info_v2.Flags.DeviceIsSuperSpeedPlusCapableOrHigher)
927
+ speed = MAX(speed, LIBUSB_SPEED_SUPER_PLUS);
928
+ else if (conn_info_v2.Flags.DeviceIsSuperSpeedCapableOrHigher || conn_info_v2.SupportedUsbProtocols.Usb300)
929
+ speed = MAX(speed, LIBUSB_SPEED_SUPER);
930
+ else if (conn_info_v2.SupportedUsbProtocols.Usb200)
931
+ speed = MAX(speed, LIBUSB_SPEED_HIGH);
932
+ else
933
+ speed = MAX(speed, LIBUSB_SPEED_FULL);
934
+ }
935
+
936
+ if (speed != LIBUSB_SPEED_UNKNOWN)
937
+ goto make_descriptors;
938
+ }
939
+
940
+ // At this point the speed is still not known, most likely because we are executing on
941
+ // Windows 7 or earlier. The following hackery peeks into the root hub's Device ID and
942
+ // tries to extract speed information from it, based on observed naming conventions.
943
+ // If this does not work, we will query individual ports of the root hub.
944
+ if (strstr(priv->dev_id, "ROOT_HUB31") != NULL)
945
+ speed = LIBUSB_SPEED_SUPER_PLUS;
946
+ else if (strstr(priv->dev_id, "ROOT_HUB30") != NULL)
947
+ speed = LIBUSB_SPEED_SUPER;
948
+ else if (strstr(priv->dev_id, "ROOT_HUB20") != NULL)
949
+ speed = LIBUSB_SPEED_HIGH;
950
+
951
+ if (speed != LIBUSB_SPEED_UNKNOWN)
952
+ goto make_descriptors;
953
+
954
+ // Windows only reports speed information about a connected device. This means that a root
955
+ // hub with no connected devices or devices that are all operating at a speed less than the
956
+ // highest speed that the root hub supports will not give us the correct speed.
957
+ for (port_number = 1; port_number <= num_ports; port_number++) {
958
+ conn_info.ConnectionIndex = port_number;
959
+ if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info),
960
+ &conn_info, sizeof(conn_info), &size, NULL)) {
961
+ usbi_warn(ctx, "could not get node connection information for root hub '%s' port %lu: %s",
962
+ priv->dev_id, ULONG_CAST(port_number), windows_error_str(0));
963
+ continue;
964
+ }
965
+
966
+ if (conn_info.ConnectionStatus != DeviceConnected)
967
+ continue;
968
+
969
+ if (conn_info.Speed == UsbHighSpeed) {
970
+ speed = LIBUSB_SPEED_HIGH;
971
+ break;
781
972
  }
782
973
  }
974
+
975
+ make_descriptors:
976
+ CloseHandle(handle);
977
+
978
+ dev->device_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE;
979
+ dev->device_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
980
+ dev->device_descriptor.bDeviceClass = LIBUSB_CLASS_HUB;
981
+ if ((dev->device_descriptor.idVendor == 0) && (dev->device_descriptor.idProduct == 0)) {
982
+ dev->device_descriptor.idVendor = 0x1d6b; // Linux Foundation
983
+ dev->device_descriptor.idProduct = (uint16_t)speed;
984
+ }
985
+ dev->device_descriptor.bcdDevice = 0x0100;
986
+ dev->device_descriptor.bNumConfigurations = 1;
987
+
988
+ switch (speed) {
989
+ case LIBUSB_SPEED_SUPER_PLUS:
990
+ dev->device_descriptor.bcdUSB = 0x0310;
991
+ config_desc_length = ROOT_HUB_SS_CONFIG_DESC_LENGTH;
992
+ ep_interval = 0x0c; // 256ms
993
+ break;
994
+ case LIBUSB_SPEED_SUPER:
995
+ dev->device_descriptor.bcdUSB = 0x0300;
996
+ config_desc_length = ROOT_HUB_SS_CONFIG_DESC_LENGTH;
997
+ ep_interval = 0x0c; // 256ms
998
+ break;
999
+ case LIBUSB_SPEED_HIGH:
1000
+ dev->device_descriptor.bcdUSB = 0x0200;
1001
+ config_desc_length = ROOT_HUB_HS_CONFIG_DESC_LENGTH;
1002
+ ep_interval = 0x0c; // 256ms
1003
+ break;
1004
+ case LIBUSB_SPEED_LOW: // Not used, but keeps compiler happy
1005
+ case LIBUSB_SPEED_UNKNOWN:
1006
+ // This case means absolutely no information about this root hub was determined.
1007
+ // There is not much choice than to be pessimistic and label this as a
1008
+ // full-speed device.
1009
+ speed = LIBUSB_SPEED_FULL;
1010
+ // fallthrough
1011
+ case LIBUSB_SPEED_FULL:
1012
+ dev->device_descriptor.bcdUSB = 0x0110;
1013
+ config_desc_length = ROOT_HUB_FS_CONFIG_DESC_LENGTH;
1014
+ ep_interval = 0xff; // 255ms
1015
+ break;
1016
+ default: // Impossible, buts keeps compiler happy
1017
+ usbi_err(ctx, "program assertion failed - unknown root hub speed");
1018
+ return LIBUSB_ERROR_INVALID_PARAM;
1019
+ }
1020
+
1021
+ if (speed >= LIBUSB_SPEED_SUPER) {
1022
+ dev->device_descriptor.bDeviceProtocol = 0x03; // USB 3.0 Hub
1023
+ dev->device_descriptor.bMaxPacketSize0 = 0x09; // 2^9 bytes
1024
+ } else {
1025
+ dev->device_descriptor.bMaxPacketSize0 = 0x40; // 64 bytes
1026
+ }
1027
+
1028
+ dev->speed = speed;
1029
+
1030
+ r = alloc_root_hub_config_desc(dev, num_ports, config_desc_length, ep_interval);
1031
+ if (r)
1032
+ usbi_err(ctx, "could not allocate config descriptor for root hub '%s'", priv->dev_id);
1033
+
1034
+ return r;
783
1035
  }
784
1036
 
785
1037
  /*
@@ -788,9 +1040,9 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
788
1040
  static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev,
789
1041
  uint8_t port_number, DEVINST devinst)
790
1042
  {
791
- struct libusb_context *ctx;
1043
+ struct libusb_context *ctx = NULL;
792
1044
  struct libusb_device *tmp_dev;
793
- struct winusb_device_priv *priv, *parent_priv;
1045
+ struct winusb_device_priv *priv, *parent_priv, *tmp_priv;
794
1046
  USB_NODE_CONNECTION_INFORMATION_EX conn_info;
795
1047
  USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
796
1048
  HANDLE hub_handle;
@@ -799,7 +1051,7 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
799
1051
  int r;
800
1052
  int ginfotimeout;
801
1053
 
802
- priv = _device_priv(dev);
1054
+ priv = usbi_get_device_priv(dev);
803
1055
 
804
1056
  // If the device is already initialized, we can stop here
805
1057
  if (priv->initialized)
@@ -807,7 +1059,7 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
807
1059
 
808
1060
  if (parent_dev != NULL) { // Not a HCD root hub
809
1061
  ctx = DEVICE_CTX(dev);
810
- parent_priv = _device_priv(parent_dev);
1062
+ parent_priv = usbi_get_device_priv(parent_dev);
811
1063
  if (parent_priv->apib->id != USB_API_HUB) {
812
1064
  usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id);
813
1065
  return LIBUSB_ERROR_NOT_FOUND;
@@ -825,9 +1077,14 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
825
1077
 
826
1078
  for (depth = 1; bus_number == 0; depth++) {
827
1079
  tmp_dev = get_ancestor(ctx, devinst, &devinst);
1080
+ if (tmp_dev == NULL) {
1081
+ usbi_warn(ctx, "ancestor for device '%s' not found at depth %u", priv->dev_id, depth);
1082
+ return LIBUSB_ERROR_NO_DEVICE;
1083
+ }
828
1084
  if (tmp_dev->bus_number != 0) {
829
1085
  bus_number = tmp_dev->bus_number;
830
- depth += _device_priv(tmp_dev)->depth;
1086
+ tmp_priv = usbi_get_device_priv(tmp_dev);
1087
+ depth += tmp_priv->depth;
831
1088
  }
832
1089
  libusb_unref_device(tmp_dev);
833
1090
  }
@@ -845,14 +1102,12 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
845
1102
  dev->parent_dev = parent_dev;
846
1103
  priv->depth = depth;
847
1104
 
848
- hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
849
- 0, NULL);
1105
+ hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
850
1106
  if (hub_handle == INVALID_HANDLE_VALUE) {
851
1107
  usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0));
852
1108
  return LIBUSB_ERROR_ACCESS;
853
1109
  }
854
1110
 
855
- memset(&conn_info, 0, sizeof(conn_info));
856
1111
  conn_info.ConnectionIndex = (ULONG)port_number;
857
1112
  // coverity[tainted_data_argument]
858
1113
  ginfotimeout = 20;
@@ -871,32 +1126,45 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
871
1126
  return LIBUSB_ERROR_NO_DEVICE;
872
1127
  }
873
1128
 
874
- memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
875
- dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
1129
+ if ((conn_info.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE)
1130
+ || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) {
1131
+ SleepEx(50, TRUE);
1132
+ continue;
1133
+ }
1134
+
1135
+ static_assert(sizeof(dev->device_descriptor) == sizeof(conn_info.DeviceDescriptor),
1136
+ "mismatch between libusb and OS device descriptor sizes");
1137
+ memcpy(&dev->device_descriptor, &conn_info.DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
1138
+ usbi_localize_device_descriptor(&dev->device_descriptor);
1139
+
876
1140
  priv->active_config = conn_info.CurrentConfigurationValue;
877
1141
  if (priv->active_config == 0) {
878
- usbi_dbg("0x%x:0x%x found %u configurations (active conf: %u) \n",
879
- priv->dev_descriptor.idVendor,
880
- priv->dev_descriptor.idProduct,
881
- dev->num_configurations,
882
- priv->active_config);
1142
+ usbi_dbg(ctx, "0x%x:0x%x found %u configurations (not configured)",
1143
+ dev->device_descriptor.idVendor,
1144
+ dev->device_descriptor.idProduct,
1145
+ dev->device_descriptor.bNumConfigurations);
1146
+ SleepEx(50, TRUE);
883
1147
  }
884
- if (priv->active_config == 0)
885
- Sleep(50);
886
1148
  } while (priv->active_config == 0 && --ginfotimeout >= 0);
887
1149
 
1150
+ if ((conn_info.DeviceDescriptor.bLength != LIBUSB_DT_DEVICE_SIZE)
1151
+ || (conn_info.DeviceDescriptor.bDescriptorType != LIBUSB_DT_DEVICE)) {
1152
+ usbi_err(ctx, "device '%s' has invalid descriptor!", priv->dev_id);
1153
+ CloseHandle(hub_handle);
1154
+ return LIBUSB_ERROR_OTHER;
1155
+ }
1156
+
888
1157
  if (priv->active_config == 0) {
889
- usbi_dbg("after try 0x%x:0x%x found %u configurations (active conf: %u) \n",
890
- priv->dev_descriptor.idVendor,
891
- priv->dev_descriptor.idProduct,
892
- dev->num_configurations,
893
- priv->active_config);
894
- usbi_dbg("Force this device active config to 1 in libusb! \nNOTICE: Should not reach this place!!!!!! \n");
1158
+ usbi_info(ctx, "0x%x:0x%x found %u configurations but device isn't configured, "
1159
+ "forcing current configuration to 1",
1160
+ dev->device_descriptor.idVendor,
1161
+ dev->device_descriptor.idProduct,
1162
+ dev->device_descriptor.bNumConfigurations);
895
1163
  priv->active_config = 1;
1164
+ } else {
1165
+ usbi_dbg(ctx, "found %u configurations (current config: %u)", dev->device_descriptor.bNumConfigurations, priv->active_config);
896
1166
  }
897
1167
 
898
- usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
899
-
900
1168
  // Cache as many config descriptors as we can
901
1169
  cache_config_descriptors(dev, hub_handle);
902
1170
 
@@ -908,11 +1176,11 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
908
1176
  if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
909
1177
  &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) {
910
1178
  usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
911
- priv->dev_id, windows_error_str(0));
1179
+ priv->dev_id, windows_error_str(0));
912
1180
  } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) {
913
- conn_info.Speed = 4;
1181
+ conn_info.Speed = UsbSuperSpeedPlus;
914
1182
  } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
915
- conn_info.Speed = 3;
1183
+ conn_info.Speed = UsbSuperSpeed;
916
1184
  }
917
1185
  }
918
1186
 
@@ -924,15 +1192,19 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
924
1192
  dev->device_address = (uint8_t)conn_info.DeviceAddress;
925
1193
 
926
1194
  switch (conn_info.Speed) {
927
- case 0: dev->speed = LIBUSB_SPEED_LOW; break;
928
- case 1: dev->speed = LIBUSB_SPEED_FULL; break;
929
- case 2: dev->speed = LIBUSB_SPEED_HIGH; break;
930
- case 3: dev->speed = LIBUSB_SPEED_SUPER; break;
931
- case 4: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
1195
+ case UsbLowSpeed: dev->speed = LIBUSB_SPEED_LOW; break;
1196
+ case UsbFullSpeed: dev->speed = LIBUSB_SPEED_FULL; break;
1197
+ case UsbHighSpeed: dev->speed = LIBUSB_SPEED_HIGH; break;
1198
+ case UsbSuperSpeed: dev->speed = LIBUSB_SPEED_SUPER; break;
1199
+ case UsbSuperSpeedPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
932
1200
  default:
933
1201
  usbi_warn(ctx, "unknown device speed %u", conn_info.Speed);
934
1202
  break;
935
1203
  }
1204
+ } else {
1205
+ r = init_root_hub(dev);
1206
+ if (r)
1207
+ return r;
936
1208
  }
937
1209
 
938
1210
  r = usbi_sanitize_device(dev);
@@ -941,12 +1213,53 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
941
1213
 
942
1214
  priv->initialized = true;
943
1215
 
944
- usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
1216
+ usbi_dbg(ctx, "(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
945
1217
  dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id);
946
1218
 
947
1219
  return LIBUSB_SUCCESS;
948
1220
  }
949
1221
 
1222
+ static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_data, DWORD *port_nr)
1223
+ {
1224
+ char buffer[MAX_KEY_LENGTH];
1225
+ DWORD size;
1226
+
1227
+ // First try SPDRP_LOCATION_INFORMATION, which returns a REG_SZ. The string *may* have a format
1228
+ // similar to "Port_#0002.Hub_#000D", in which case we can extract the port number. However, we
1229
+ // cannot extract the port if the returned string does not follow this format.
1230
+ if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_INFORMATION,
1231
+ NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
1232
+ // Check for the required format.
1233
+ if (strncmp(buffer, "Port_#", 6) == 0) {
1234
+ *port_nr = atoi(buffer + 6);
1235
+ return true;
1236
+ }
1237
+ }
1238
+
1239
+ // Next try SPDRP_LOCATION_PATHS, which returns a REG_MULTI_SZ (but we only examine the first
1240
+ // string in it). Each path has a format similar to,
1241
+ // "PCIROOT(B2)#PCI(0300)#PCI(0000)#USBROOT(0)#USB(1)#USB(2)#USBMI(3)", and the port number is
1242
+ // the number within the last "USB(x)" token.
1243
+ if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_PATHS,
1244
+ NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
1245
+ // Find the last "#USB(x)" substring
1246
+ for (char *token = strrchr(buffer, '#'); token != NULL; token = strrchr(buffer, '#')) {
1247
+ if (strncmp(token, "#USB(", 5) == 0) {
1248
+ *port_nr = atoi(token + 5);
1249
+ return true;
1250
+ }
1251
+ // Shorten the string and try again.
1252
+ *token = '\0';
1253
+ }
1254
+ }
1255
+
1256
+ // Lastly, try SPDRP_ADDRESS, which returns a REG_DWORD. The address *may* be the port number,
1257
+ // which is true for the Microsoft driver but may not be true for other drivers. However, we
1258
+ // have no other options here but to accept what it returns.
1259
+ return pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_ADDRESS,
1260
+ NULL, (PBYTE)port_nr, sizeof(*port_nr), &size) && (size == sizeof(*port_nr));
1261
+ }
1262
+
950
1263
  static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id,
951
1264
  uint8_t bus_number, DEVINST devinst)
952
1265
  {
@@ -955,7 +1268,7 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
955
1268
  unsigned long session_id;
956
1269
  DEVINST child_devinst;
957
1270
 
958
- if ((CM_Get_Child(&child_devinst, devinst, 0)) != CR_SUCCESS) {
1271
+ if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) {
959
1272
  usbi_warn(ctx, "could not get child devinst for '%s'", dev_id);
960
1273
  return LIBUSB_SUCCESS;
961
1274
  }
@@ -964,26 +1277,19 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
964
1277
  dev = usbi_get_device_by_session_id(ctx, session_id);
965
1278
  if (dev == NULL) {
966
1279
  usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id);
967
- return LIBUSB_ERROR_NO_DEVICE;
1280
+ return LIBUSB_SUCCESS;
968
1281
  }
969
1282
 
970
1283
  if (dev->bus_number == 0) {
971
1284
  // Only do this once
972
- usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number);
973
- priv = _device_priv(dev);
1285
+ usbi_dbg(ctx, "assigning HCD '%s' bus number %u", dev_id, bus_number);
974
1286
  dev->bus_number = bus_number;
975
- dev->num_configurations = 1;
976
- priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE;
977
- priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
978
- priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB;
979
- priv->dev_descriptor.bNumConfigurations = 1;
980
- priv->active_config = 1;
981
- priv->root_hub = true;
982
- if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) {
1287
+
1288
+ if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &dev->device_descriptor.idVendor, &dev->device_descriptor.idProduct) != 2)
983
1289
  usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id);
984
- priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
985
- priv->dev_descriptor.idProduct = 1;
986
- }
1290
+
1291
+ priv = usbi_get_device_priv(dev);
1292
+ priv->root_hub = true;
987
1293
  }
988
1294
 
989
1295
  libusb_unref_device(dev);
@@ -991,8 +1297,8 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
991
1297
  }
992
1298
 
993
1299
  // Returns the api type, or 0 if not found/unsupported
994
- static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
995
- SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
1300
+ static void get_api_type(HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data,
1301
+ int *api, int *sub_api)
996
1302
  {
997
1303
  // Precedence for filter drivers vs driver is in the order of this array
998
1304
  struct driver_lookup lookup[3] = {
@@ -1015,15 +1321,15 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
1015
1321
 
1016
1322
  // MULTI_SZ is a pain to work with. Turn it into something much more manageable
1017
1323
  // NB: none of the driver names we check against contain LIST_SEPARATOR,
1018
- // (currently ';'), so even if an unsuported one does, it's not an issue
1324
+ // (currently ';'), so even if an unsupported one does, it's not an issue
1019
1325
  for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) {
1020
1326
  if (lookup[k].list[l] == 0)
1021
1327
  lookup[k].list[l] = LIST_SEPARATOR;
1022
1328
  }
1023
- usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
1329
+ usbi_dbg(NULL, "%s(s): %s", lookup[k].designation, lookup[k].list);
1024
1330
  } else {
1025
1331
  if (GetLastError() != ERROR_INVALID_DATA)
1026
- usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
1332
+ usbi_dbg(NULL, "could not access %s: %s", lookup[k].designation, windows_error_str(0));
1027
1333
  lookup[k].list[0] = 0;
1028
1334
  }
1029
1335
  }
@@ -1032,7 +1338,7 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
1032
1338
  for (k = 0; k < 3; k++) {
1033
1339
  j = get_sub_api(lookup[k].list, i);
1034
1340
  if (j >= 0) {
1035
- usbi_dbg("matched %s name against %s", lookup[k].designation,
1341
+ usbi_dbg(NULL, "matched %s name against %s", lookup[k].designation,
1036
1342
  (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]);
1037
1343
  *api = i;
1038
1344
  *sub_api = j;
@@ -1045,7 +1351,7 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
1045
1351
  static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev,
1046
1352
  char *dev_interface_path, char *device_id, int api, int sub_api)
1047
1353
  {
1048
- struct winusb_device_priv *priv = _device_priv(dev);
1354
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
1049
1355
  int interface_number;
1050
1356
  const char *mi_str;
1051
1357
 
@@ -1053,7 +1359,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
1053
1359
  // devices will have only MI_00 & MI_03 for instance), we retrieve the actual
1054
1360
  // interface number from the path's MI value
1055
1361
  mi_str = strstr(device_id, "MI_");
1056
- if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) {
1362
+ if ((mi_str != NULL) && isdigit((unsigned char)mi_str[3]) && isdigit((unsigned char)mi_str[4])) {
1057
1363
  interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0');
1058
1364
  } else {
1059
1365
  usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id);
@@ -1068,7 +1374,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
1068
1374
  if (priv->usb_interface[interface_number].path != NULL) {
1069
1375
  if (api == USB_API_HID) {
1070
1376
  // HID devices can have multiple collections (COL##) for each MI_## interface
1071
- usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
1377
+ usbi_dbg(ctx, "interface[%d] already set - ignoring HID collection: %s",
1072
1378
  interface_number, device_id);
1073
1379
  return LIBUSB_ERROR_ACCESS;
1074
1380
  }
@@ -1076,7 +1382,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
1076
1382
  safe_free(priv->usb_interface[interface_number].path);
1077
1383
  }
1078
1384
 
1079
- usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
1385
+ usbi_dbg(ctx, "interface[%d] = %s", interface_number, dev_interface_path);
1080
1386
  priv->usb_interface[interface_number].path = dev_interface_path;
1081
1387
  priv->usb_interface[interface_number].apib = &usb_api_backend[api];
1082
1388
  priv->usb_interface[interface_number].sub_api = sub_api;
@@ -1092,27 +1398,27 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
1092
1398
  static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
1093
1399
  char *dev_interface_path)
1094
1400
  {
1095
- int i;
1096
- struct winusb_device_priv *priv = _device_priv(dev);
1401
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
1402
+ uint8_t i;
1097
1403
 
1098
1404
  if (priv->hid == NULL) {
1099
- usbi_err(ctx, "program assertion failed: parent is not HID");
1405
+ usbi_err(ctx, "program assertion failed - parent is not HID");
1100
1406
  return LIBUSB_ERROR_NO_DEVICE;
1101
1407
  } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
1102
- usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
1408
+ usbi_err(ctx, "program assertion failed - max USB interfaces reached for HID device");
1103
1409
  return LIBUSB_ERROR_NO_DEVICE;
1104
1410
  }
1105
1411
 
1106
1412
  for (i = 0; i < priv->hid->nb_interfaces; i++) {
1107
1413
  if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
1108
- usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
1414
+ usbi_dbg(ctx, "interface[%u] already set to %s", i, dev_interface_path);
1109
1415
  return LIBUSB_ERROR_ACCESS;
1110
1416
  }
1111
1417
  }
1112
1418
 
1113
1419
  priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
1114
1420
  priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
1115
- usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
1421
+ usbi_dbg(ctx, "interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
1116
1422
  priv->hid->nb_interfaces++;
1117
1423
  return LIBUSB_SUCCESS;
1118
1424
  }
@@ -1138,7 +1444,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1138
1444
  unsigned long session_id;
1139
1445
  DWORD size, port_nr, reg_type, install_state;
1140
1446
  HKEY key;
1141
- WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
1447
+ char guid_string[MAX_GUID_STRING_LENGTH];
1142
1448
  GUID *if_guid;
1143
1449
  LONG s;
1144
1450
  #define HUB_PASS 0
@@ -1153,7 +1459,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1153
1459
  unsigned int guid_size = GUID_SIZE_STEP;
1154
1460
  unsigned int nb_guids;
1155
1461
  // Keep a list of PnP enumerator strings that are found
1156
- char *usb_enumerator[8] = { "USB" };
1462
+ const char *usb_enumerator[8] = { "USB" };
1157
1463
  unsigned int nb_usb_enumerators = 1;
1158
1464
  unsigned int usb_enum_index = 0;
1159
1465
  // Keep a list of newly allocated devs to unref
@@ -1181,7 +1487,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1181
1487
  guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
1182
1488
  guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
1183
1489
  guid_list[GEN_PASS] = NULL;
1184
- if (api_hid_available) {
1490
+ if (HidD_GetHidGuid != NULL) {
1185
1491
  HidD_GetHidGuid(&hid_guid);
1186
1492
  guid_list[HID_PASS] = &hid_guid;
1187
1493
  } else {
@@ -1208,7 +1514,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1208
1514
  //#define ENUM_DEBUG
1209
1515
  #if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
1210
1516
  const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"};
1211
- usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass]));
1517
+ usbi_dbg(ctx, "#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass], guid_string));
1212
1518
  #endif
1213
1519
  if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL))
1214
1520
  continue;
@@ -1227,7 +1533,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1227
1533
  break;
1228
1534
 
1229
1535
  if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
1230
- usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX);
1536
+ usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest", UINT8_MAX);
1231
1537
  break;
1232
1538
  }
1233
1539
 
@@ -1255,12 +1561,12 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1255
1561
  // Read the Device ID path
1256
1562
  if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) {
1257
1563
  usbi_warn(ctx, "could not read the device instance ID for devInst %lX, skipping",
1258
- dev_info_data.DevInst);
1564
+ ULONG_CAST(dev_info_data.DevInst));
1259
1565
  continue;
1260
1566
  }
1261
1567
 
1262
1568
  #ifdef ENUM_DEBUG
1263
- usbi_dbg("PRO: %s", dev_id);
1569
+ usbi_dbg(ctx, "PRO: %s", dev_id);
1264
1570
  #endif
1265
1571
 
1266
1572
  // Set API to use or get additional data from generic pass
@@ -1283,7 +1589,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1283
1589
  break;
1284
1590
  }
1285
1591
  if (j == nb_usb_enumerators) {
1286
- usbi_dbg("found new PnP enumerator string '%s'", enumerator);
1592
+ usbi_dbg(ctx, "found new PnP enumerator string '%s'", enumerator);
1287
1593
  if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) {
1288
1594
  usb_enumerator[nb_usb_enumerators] = _strdup(enumerator);
1289
1595
  if (usb_enumerator[nb_usb_enumerators] != NULL) {
@@ -1309,16 +1615,25 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1309
1615
  if (key == INVALID_HANDLE_VALUE)
1310
1616
  break;
1311
1617
  // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order
1312
- size = sizeof(guid_string_w);
1313
- s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, &reg_type,
1314
- (LPBYTE)guid_string_w, &size);
1618
+ // If multiple GUIDs just process the first and ignore the others
1619
+ size = sizeof(guid_string);
1620
+ s = pRegQueryValueExA(key, "DeviceInterfaceGUIDs", NULL, &reg_type,
1621
+ (LPBYTE)guid_string, &size);
1315
1622
  if (s == ERROR_FILE_NOT_FOUND)
1316
- s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, &reg_type,
1317
- (LPBYTE)guid_string_w, &size);
1623
+ s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, &reg_type,
1624
+ (LPBYTE)guid_string, &size);
1318
1625
  pRegCloseKey(key);
1319
- if ((s == ERROR_SUCCESS) &&
1320
- (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) ||
1321
- ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) {
1626
+ if (s == ERROR_FILE_NOT_FOUND) {
1627
+ break; /* no DeviceInterfaceGUID registered */
1628
+ } else if (s != ERROR_SUCCESS && s != ERROR_MORE_DATA) {
1629
+ usbi_warn(ctx, "unexpected error from pRegQueryValueExA for '%s'", dev_id);
1630
+ break;
1631
+ }
1632
+ // https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa#remarks
1633
+ // - "string may not have been stored with the proper terminating null characters"
1634
+ // - "Note that REG_MULTI_SZ strings could have two terminating null characters"
1635
+ if ((reg_type == REG_SZ && size >= sizeof(guid_string) - sizeof(char))
1636
+ || (reg_type == REG_MULTI_SZ && size >= sizeof(guid_string) - 2 * sizeof(char))) {
1322
1637
  if (nb_guids == guid_size) {
1323
1638
  new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *));
1324
1639
  if (new_guid_list == NULL) {
@@ -1333,8 +1648,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1333
1648
  usbi_err(ctx, "failed to alloc if_guid");
1334
1649
  LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1335
1650
  }
1336
- if (pIIDFromString(guid_string_w, if_guid) != 0) {
1337
- usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id);
1651
+ if (!string_to_guid(guid_string, if_guid)) {
1652
+ usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string '%s', skipping", dev_id, guid_string);
1338
1653
  free(if_guid);
1339
1654
  } else {
1340
1655
  // Check if we've already seen this GUID
@@ -1343,14 +1658,14 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1343
1658
  break;
1344
1659
  }
1345
1660
  if (j == nb_guids) {
1346
- usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
1661
+ usbi_dbg(ctx, "extra GUID: %s", guid_string);
1347
1662
  guid_list[nb_guids++] = if_guid;
1348
1663
  } else {
1349
1664
  // Duplicate, ignore
1350
1665
  free(if_guid);
1351
1666
  }
1352
1667
  }
1353
- } else if (s == ERROR_SUCCESS) {
1668
+ } else {
1354
1669
  usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id);
1355
1670
  }
1356
1671
  break;
@@ -1364,11 +1679,11 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1364
1679
  usbi_warn(ctx, "could not detect installation state of driver for '%s': %s",
1365
1680
  dev_id, windows_error_str(0));
1366
1681
  } else if (install_state != 0) {
1367
- usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping",
1368
- dev_id, (unsigned int)install_state);
1682
+ usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %lu) - skipping",
1683
+ dev_id, ULONG_CAST(install_state));
1369
1684
  continue;
1370
1685
  }
1371
- get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api);
1686
+ get_api_type(dev_info, &dev_info_data, &api, &sub_api);
1372
1687
  break;
1373
1688
  }
1374
1689
 
@@ -1379,17 +1694,17 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1379
1694
  // Root hubs will not have a parent
1380
1695
  dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst);
1381
1696
  if (dev != NULL) {
1382
- priv = _device_priv(dev);
1697
+ priv = usbi_get_device_priv(dev);
1383
1698
  if (priv->root_hub)
1384
1699
  goto track_unref;
1385
1700
  libusb_unref_device(dev);
1386
1701
  }
1387
1702
 
1388
- usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
1703
+ usbi_dbg(ctx, "unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
1389
1704
  continue;
1390
1705
  }
1391
1706
 
1392
- parent_priv = _device_priv(parent_dev);
1707
+ parent_priv = usbi_get_device_priv(parent_dev);
1393
1708
  // virtual USB devices are also listed during GEN - don't process these yet
1394
1709
  if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) {
1395
1710
  libusb_unref_device(parent_dev);
@@ -1404,23 +1719,30 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1404
1719
  dev = usbi_get_device_by_session_id(ctx, session_id);
1405
1720
  if (dev == NULL) {
1406
1721
  alloc_device:
1407
- usbi_dbg("allocating new device for session [%lX]", session_id);
1722
+ usbi_dbg(ctx, "allocating new device for session [%lX]", session_id);
1408
1723
  dev = usbi_alloc_device(ctx, session_id);
1409
1724
  if (dev == NULL)
1410
1725
  LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1411
1726
 
1412
1727
  priv = winusb_device_priv_init(dev);
1413
1728
  priv->dev_id = _strdup(dev_id);
1729
+ priv->class_guid = dev_info_data.ClassGuid;
1414
1730
  if (priv->dev_id == NULL) {
1415
1731
  libusb_unref_device(dev);
1416
1732
  LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1417
1733
  }
1418
1734
  } else {
1419
- usbi_dbg("found existing device for session [%lX]", session_id);
1735
+ usbi_dbg(ctx, "found existing device for session [%lX]", session_id);
1420
1736
 
1421
- priv = _device_priv(dev);
1737
+ priv = usbi_get_device_priv(dev);
1422
1738
  if (strcmp(priv->dev_id, dev_id) != 0) {
1423
- usbi_dbg("device instance ID for session [%lX] changed", session_id);
1739
+ usbi_dbg(ctx, "device instance ID for session [%lX] changed", session_id);
1740
+ usbi_disconnect_device(dev);
1741
+ libusb_unref_device(dev);
1742
+ goto alloc_device;
1743
+ }
1744
+ if (!IsEqualGUID(&priv->class_guid, &dev_info_data.ClassGuid)) {
1745
+ usbi_dbg(ctx, "device class GUID for session [%lX] changed", session_id);
1424
1746
  usbi_disconnect_device(dev);
1425
1747
  libusb_unref_device(dev);
1426
1748
  goto alloc_device;
@@ -1478,10 +1800,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1478
1800
  r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst);
1479
1801
  break;
1480
1802
  case GEN_PASS:
1481
- // The SPDRP_ADDRESS for USB devices is the device port number on the hub
1482
1803
  port_nr = 0;
1483
- if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS,
1484
- NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr)))
1804
+ if (!get_dev_port_number(*dev_info, &dev_info_data, &port_nr))
1485
1805
  usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0));
1486
1806
  r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst);
1487
1807
  if (r == LIBUSB_SUCCESS) {
@@ -1491,19 +1811,20 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1491
1811
  LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1492
1812
 
1493
1813
  *_discdevs = discdevs;
1494
- } else if (r == LIBUSB_ERROR_NO_DEVICE) {
1495
- // This can occur if the device was disconnected but Windows hasn't
1496
- // refreshed its enumeration yet - in that case, we ignore the device
1814
+ } else {
1815
+ // Failed to initialize a single device doesn't stop us from enumerating all other devices,
1816
+ // but we skip it (don't add to list of discovered devices)
1817
+ usbi_warn(ctx, "failed to initialize device '%s'", priv->dev_id);
1497
1818
  r = LIBUSB_SUCCESS;
1498
1819
  }
1499
1820
  break;
1500
1821
  default: // HID_PASS and later
1501
1822
  if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) {
1502
1823
  if (parent_priv->apib->id == USB_API_HID) {
1503
- usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
1824
+ usbi_dbg(ctx, "setting HID interface for [%lX]:", parent_dev->session_data);
1504
1825
  r = set_hid_interface(ctx, parent_dev, dev_interface_path);
1505
1826
  } else {
1506
- usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
1827
+ usbi_dbg(ctx, "setting composite interface for [%lX]:", parent_dev->session_data);
1507
1828
  r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api);
1508
1829
  }
1509
1830
  switch (r) {
@@ -1534,7 +1855,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1534
1855
 
1535
1856
  // Free any PnP enumerator strings
1536
1857
  for (i = 1; i < nb_usb_enumerators; i++)
1537
- free(usb_enumerator[i]);
1858
+ free((void *)usb_enumerator[i]);
1538
1859
 
1539
1860
  // Unref newly allocated devs
1540
1861
  for (i = 0; i < unref_cur; i++)
@@ -1544,50 +1865,37 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
1544
1865
  return r;
1545
1866
  }
1546
1867
 
1547
- static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
1868
+ static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, void *buffer, size_t len)
1548
1869
  {
1549
- struct winusb_device_priv *priv = _device_priv(dev);
1550
-
1551
- memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH);
1552
- return LIBUSB_SUCCESS;
1553
- }
1554
-
1555
- static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len)
1556
- {
1557
- struct winusb_device_priv *priv = _device_priv(dev);
1870
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
1558
1871
  PUSB_CONFIGURATION_DESCRIPTOR config_header;
1559
- size_t size;
1560
-
1561
- // config index is zero based
1562
- if (config_index >= dev->num_configurations)
1563
- return LIBUSB_ERROR_INVALID_PARAM;
1564
1872
 
1565
1873
  if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
1566
1874
  return LIBUSB_ERROR_NOT_FOUND;
1567
1875
 
1568
1876
  config_header = priv->config_descriptor[config_index];
1569
1877
 
1570
- size = MIN(config_header->wTotalLength, len);
1571
- memcpy(buffer, priv->config_descriptor[config_index], size);
1572
- return (int)size;
1878
+ len = MIN(len, config_header->wTotalLength);
1879
+ memcpy(buffer, config_header, len);
1880
+ return (int)len;
1573
1881
  }
1574
1882
 
1575
1883
  static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
1576
- unsigned char **buffer)
1884
+ void **buffer)
1577
1885
  {
1578
- struct winusb_device_priv *priv = _device_priv(dev);
1886
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
1579
1887
  PUSB_CONFIGURATION_DESCRIPTOR config_header;
1580
1888
  uint8_t index;
1581
1889
 
1582
1890
  if (priv->config_descriptor == NULL)
1583
1891
  return LIBUSB_ERROR_NOT_FOUND;
1584
1892
 
1585
- for (index = 0; index < dev->num_configurations; index++) {
1893
+ for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
1586
1894
  config_header = priv->config_descriptor[index];
1587
1895
  if (config_header == NULL)
1588
1896
  continue;
1589
1897
  if (config_header->bConfigurationValue == bConfigurationValue) {
1590
- *buffer = (unsigned char *)priv->config_descriptor[index];
1898
+ *buffer = config_header;
1591
1899
  return (int)config_header->wTotalLength;
1592
1900
  }
1593
1901
  }
@@ -1598,10 +1906,10 @@ static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint
1598
1906
  /*
1599
1907
  * return the cached copy of the active config descriptor
1600
1908
  */
1601
- static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len)
1909
+ static int winusb_get_active_config_descriptor(struct libusb_device *dev, void *buffer, size_t len)
1602
1910
  {
1603
- struct winusb_device_priv *priv = _device_priv(dev);
1604
- unsigned char *config_desc;
1911
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
1912
+ void *config_desc;
1605
1913
  int r;
1606
1914
 
1607
1915
  if (priv->active_config == 0)
@@ -1611,14 +1919,14 @@ static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsign
1611
1919
  if (r < 0)
1612
1920
  return r;
1613
1921
 
1614
- len = MIN((size_t)r, len);
1922
+ len = MIN(len, (size_t)r);
1615
1923
  memcpy(buffer, config_desc, len);
1616
1924
  return (int)len;
1617
1925
  }
1618
1926
 
1619
1927
  static int winusb_open(struct libusb_device_handle *dev_handle)
1620
1928
  {
1621
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1929
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1622
1930
 
1623
1931
  CHECK_SUPPORTED_API(priv->apib, open);
1624
1932
 
@@ -1627,20 +1935,15 @@ static int winusb_open(struct libusb_device_handle *dev_handle)
1627
1935
 
1628
1936
  static void winusb_close(struct libusb_device_handle *dev_handle)
1629
1937
  {
1630
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1938
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1631
1939
 
1632
1940
  if (priv->apib->close)
1633
1941
  priv->apib->close(SUB_API_NOTSET, dev_handle);
1634
1942
  }
1635
1943
 
1636
- static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config)
1944
+ static int winusb_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
1637
1945
  {
1638
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1639
-
1640
- if (priv->active_config == 0) {
1641
- *config = 0;
1642
- return LIBUSB_ERROR_NOT_FOUND;
1643
- }
1946
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1644
1947
 
1645
1948
  *config = priv->active_config;
1646
1949
  return LIBUSB_SUCCESS;
@@ -1651,28 +1954,25 @@ static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int
1651
1954
  * does not currently expose a service that allows higher-level drivers to set
1652
1955
  * the configuration."
1653
1956
  */
1654
- static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config)
1957
+ static int winusb_set_configuration(struct libusb_device_handle *dev_handle, uint8_t config)
1655
1958
  {
1656
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1959
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1657
1960
  int r = LIBUSB_SUCCESS;
1658
1961
 
1659
- if (config >= USB_MAXCONFIG)
1660
- return LIBUSB_ERROR_INVALID_PARAM;
1661
-
1662
1962
  r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
1663
1963
  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
1664
- LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
1964
+ LIBUSB_REQUEST_SET_CONFIGURATION, config,
1665
1965
  0, NULL, 0, 1000);
1666
1966
 
1667
1967
  if (r == LIBUSB_SUCCESS)
1668
- priv->active_config = (uint8_t)config;
1968
+ priv->active_config = config;
1669
1969
 
1670
1970
  return r;
1671
1971
  }
1672
1972
 
1673
- static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface)
1973
+ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
1674
1974
  {
1675
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1975
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1676
1976
  int r;
1677
1977
 
1678
1978
  CHECK_SUPPORTED_API(priv->apib, claim_interface);
@@ -1688,9 +1988,9 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i
1688
1988
  return r;
1689
1989
  }
1690
1990
 
1691
- static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
1991
+ static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
1692
1992
  {
1693
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1993
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1694
1994
  int r;
1695
1995
 
1696
1996
  CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting);
@@ -1706,9 +2006,9 @@ static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_hand
1706
2006
  return r;
1707
2007
  }
1708
2008
 
1709
- static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface)
2009
+ static int winusb_release_interface(struct libusb_device_handle *dev_handle, uint8_t iface)
1710
2010
  {
1711
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2011
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1712
2012
 
1713
2013
  CHECK_SUPPORTED_API(priv->apib, release_interface);
1714
2014
 
@@ -1717,7 +2017,7 @@ static int winusb_release_interface(struct libusb_device_handle *dev_handle, int
1717
2017
 
1718
2018
  static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
1719
2019
  {
1720
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2020
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1721
2021
 
1722
2022
  CHECK_SUPPORTED_API(priv->apib, clear_halt);
1723
2023
 
@@ -1726,7 +2026,7 @@ static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1726
2026
 
1727
2027
  static int winusb_reset_device(struct libusb_device_handle *dev_handle)
1728
2028
  {
1729
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2029
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
1730
2030
 
1731
2031
  CHECK_SUPPORTED_API(priv->apib, reset_device);
1732
2032
 
@@ -1740,14 +2040,11 @@ static void winusb_destroy_device(struct libusb_device *dev)
1740
2040
 
1741
2041
  static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
1742
2042
  {
1743
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2043
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
1744
2044
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1745
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2045
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
1746
2046
  int sub_api = priv->sub_api;
1747
2047
 
1748
- usbi_close(transfer_priv->pollable_fd.fd);
1749
- transfer_priv->pollable_fd = INVALID_WINFD;
1750
- transfer_priv->handle = NULL;
1751
2048
  safe_free(transfer_priv->hid_buffer);
1752
2049
 
1753
2050
  if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && sub_api == SUB_API_WINUSB) {
@@ -1755,7 +2052,7 @@ static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
1755
2052
  if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
1756
2053
  transfer_priv->isoch_buffer_handle = NULL;
1757
2054
  } else {
1758
- usbi_dbg("Couldn't unregister isoch buffer!");
2055
+ usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
1759
2056
  }
1760
2057
  }
1761
2058
  }
@@ -1766,64 +2063,26 @@ static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
1766
2063
  auto_release(itransfer);
1767
2064
  }
1768
2065
 
1769
- static int do_submit_transfer(struct usbi_transfer *itransfer, short events,
1770
- int (*transfer_fn)(int, struct usbi_transfer *))
1771
- {
1772
- struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
1773
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1774
- struct winfd wfd;
1775
- int r;
1776
-
1777
- wfd = usbi_create_fd();
1778
- if (wfd.fd < 0)
1779
- return LIBUSB_ERROR_NO_MEM;
1780
-
1781
- r = usbi_add_pollfd(ctx, wfd.fd, events);
1782
- if (r) {
1783
- usbi_close(wfd.fd);
1784
- return r;
1785
- }
1786
-
1787
- // Use transfer_priv to store data needed for async polling
1788
- transfer_priv->pollable_fd = wfd;
1789
-
1790
- r = transfer_fn(SUB_API_NOTSET, itransfer);
1791
-
1792
- if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) {
1793
- usbi_remove_pollfd(ctx, wfd.fd);
1794
- usbi_close(wfd.fd);
1795
- transfer_priv->pollable_fd = INVALID_WINFD;
1796
- }
1797
-
1798
- return r;
1799
- }
1800
-
1801
2066
  static int winusb_submit_transfer(struct usbi_transfer *itransfer)
1802
2067
  {
1803
2068
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1804
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2069
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
1805
2070
  int (*transfer_fn)(int, struct usbi_transfer *);
1806
- short events;
1807
2071
 
1808
2072
  switch (transfer->type) {
1809
2073
  case LIBUSB_TRANSFER_TYPE_CONTROL:
1810
- events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
1811
2074
  transfer_fn = priv->apib->submit_control_transfer;
1812
2075
  break;
1813
2076
  case LIBUSB_TRANSFER_TYPE_BULK:
1814
2077
  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1815
- if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
1816
- return LIBUSB_ERROR_NOT_SUPPORTED;
1817
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
1818
2078
  transfer_fn = priv->apib->submit_bulk_transfer;
1819
2079
  break;
1820
2080
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
1821
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
1822
2081
  transfer_fn = priv->apib->submit_iso_transfer;
1823
2082
  break;
1824
- case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
1825
- return LIBUSB_ERROR_NOT_SUPPORTED;
1826
2083
  default:
2084
+ // Should not get here since windows_submit_transfer() validates
2085
+ // the transfer->type field
1827
2086
  usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
1828
2087
  return LIBUSB_ERROR_INVALID_PARAM;
1829
2088
  }
@@ -1835,76 +2094,30 @@ static int winusb_submit_transfer(struct usbi_transfer *itransfer)
1835
2094
  return LIBUSB_ERROR_NOT_SUPPORTED;
1836
2095
  }
1837
2096
 
1838
- return do_submit_transfer(itransfer, events, transfer_fn);
2097
+ return transfer_fn(SUB_API_NOTSET, itransfer);
1839
2098
  }
1840
2099
 
1841
- static int windows_abort_control(struct usbi_transfer *itransfer)
1842
- {
1843
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1844
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1845
-
1846
- CHECK_SUPPORTED_API(priv->apib, abort_control);
1847
-
1848
- return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
1849
- }
1850
-
1851
- static int windows_abort_transfers(struct usbi_transfer *itransfer)
2100
+ static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
1852
2101
  {
1853
2102
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1854
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2103
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
1855
2104
 
1856
- CHECK_SUPPORTED_API(priv->apib, abort_transfers);
2105
+ CHECK_SUPPORTED_API(priv->apib, cancel_transfer);
1857
2106
 
1858
- return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
2107
+ return priv->apib->cancel_transfer(SUB_API_NOTSET, itransfer);
1859
2108
  }
1860
2109
 
1861
- static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
2110
+ static enum libusb_transfer_status winusb_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
1862
2111
  {
1863
2112
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2113
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
1864
2114
 
1865
- switch (transfer->type) {
1866
- case LIBUSB_TRANSFER_TYPE_CONTROL:
1867
- return windows_abort_control(itransfer);
1868
- case LIBUSB_TRANSFER_TYPE_BULK:
1869
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1870
- case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
1871
- return windows_abort_transfers(itransfer);
1872
- case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
1873
- return LIBUSB_ERROR_NOT_SUPPORTED;
1874
- default:
1875
- usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
1876
- return LIBUSB_ERROR_INVALID_PARAM;
2115
+ if (priv->apib->copy_transfer_data == NULL) {
2116
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
2117
+ return LIBUSB_TRANSFER_ERROR;
1877
2118
  }
1878
- }
1879
-
1880
- static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
1881
- {
1882
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1883
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1884
- return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
1885
- }
1886
-
1887
- static int winusb_get_transfer_fd(struct usbi_transfer *itransfer)
1888
- {
1889
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1890
- return transfer_priv->pollable_fd.fd;
1891
- }
1892
2119
 
1893
- static void winusb_get_overlapped_result(struct usbi_transfer *itransfer,
1894
- DWORD *io_result, DWORD *io_size)
1895
- {
1896
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1897
- struct winfd *pollable_fd = &transfer_priv->pollable_fd;
1898
-
1899
- if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
1900
- *io_result = NO_ERROR;
1901
- *io_size = (DWORD)pollable_fd->overlapped->InternalHigh;
1902
- } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) {
1903
- // Regular async overlapped
1904
- *io_result = NO_ERROR;
1905
- } else {
1906
- *io_result = GetLastError();
1907
- }
2120
+ return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, length);
1908
2121
  }
1909
2122
 
1910
2123
  // NB: MSVC6 does not support named initializers.
@@ -1914,7 +2127,6 @@ const struct windows_backend winusb_backend = {
1914
2127
  winusb_get_device_list,
1915
2128
  winusb_open,
1916
2129
  winusb_close,
1917
- winusb_get_device_descriptor,
1918
2130
  winusb_get_active_config_descriptor,
1919
2131
  winusb_get_config_descriptor,
1920
2132
  winusb_get_config_descriptor_by_value,
@@ -1930,8 +2142,6 @@ const struct windows_backend winusb_backend = {
1930
2142
  winusb_cancel_transfer,
1931
2143
  winusb_clear_transfer_priv,
1932
2144
  winusb_copy_transfer_data,
1933
- winusb_get_transfer_fd,
1934
- winusb_get_overlapped_result,
1935
2145
  };
1936
2146
 
1937
2147
  /*
@@ -1945,12 +2155,44 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
1945
2155
  {
1946
2156
  USB_API_UNSUPPORTED,
1947
2157
  "Unsupported API",
1948
- // No supported operations
2158
+ NULL, /* driver_name_list */
2159
+ 0, /* nb_driver_names */
2160
+ NULL, /* init */
2161
+ NULL, /* exit */
2162
+ NULL, /* open */
2163
+ NULL, /* close */
2164
+ NULL, /* configure_endpoints */
2165
+ NULL, /* claim_interface */
2166
+ NULL, /* set_interface_altsetting */
2167
+ NULL, /* release_interface */
2168
+ NULL, /* clear_halt */
2169
+ NULL, /* reset_device */
2170
+ NULL, /* submit_bulk_transfer */
2171
+ NULL, /* submit_iso_transfer */
2172
+ NULL, /* submit_control_transfer */
2173
+ NULL, /* cancel_transfer */
2174
+ NULL, /* copy_transfer_data */
1949
2175
  },
1950
2176
  {
1951
2177
  USB_API_HUB,
1952
2178
  "HUB API",
1953
- // No supported operations
2179
+ NULL, /* driver_name_list */
2180
+ 0, /* nb_driver_names */
2181
+ NULL, /* init */
2182
+ NULL, /* exit */
2183
+ NULL, /* open */
2184
+ NULL, /* close */
2185
+ NULL, /* configure_endpoints */
2186
+ NULL, /* claim_interface */
2187
+ NULL, /* set_interface_altsetting */
2188
+ NULL, /* release_interface */
2189
+ NULL, /* clear_halt */
2190
+ NULL, /* reset_device */
2191
+ NULL, /* submit_bulk_transfer */
2192
+ NULL, /* submit_iso_transfer */
2193
+ NULL, /* submit_control_transfer */
2194
+ NULL, /* cancel_transfer */
2195
+ NULL, /* copy_transfer_data */
1954
2196
  },
1955
2197
  {
1956
2198
  USB_API_COMPOSITE,
@@ -1970,8 +2212,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
1970
2212
  composite_submit_bulk_transfer,
1971
2213
  composite_submit_iso_transfer,
1972
2214
  composite_submit_control_transfer,
1973
- composite_abort_control,
1974
- composite_abort_transfers,
2215
+ composite_cancel_transfer,
1975
2216
  composite_copy_transfer_data,
1976
2217
  },
1977
2218
  {
@@ -1992,8 +2233,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
1992
2233
  winusbx_submit_bulk_transfer,
1993
2234
  winusbx_submit_iso_transfer,
1994
2235
  winusbx_submit_control_transfer,
1995
- winusbx_abort_control,
1996
- winusbx_abort_transfers,
2236
+ winusbx_cancel_transfer,
1997
2237
  winusbx_copy_transfer_data,
1998
2238
  },
1999
2239
  {
@@ -2014,8 +2254,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
2014
2254
  hid_submit_bulk_transfer,
2015
2255
  NULL, /* submit_iso_transfer */
2016
2256
  hid_submit_control_transfer,
2017
- hid_abort_transfers,
2018
- hid_abort_transfers,
2257
+ NULL, /* cancel_transfer */
2019
2258
  hid_copy_transfer_data,
2020
2259
  },
2021
2260
  };
@@ -2024,105 +2263,159 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
2024
2263
  /*
2025
2264
  * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
2026
2265
  */
2027
- #define WinUSBX_Set(fn) \
2266
+ #define WinUSB_Set(h, fn, required) \
2028
2267
  do { \
2029
- if (native_winusb) \
2030
- WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
2031
- else \
2032
- pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \
2268
+ WinUSBX[SUB_API_WINUSB].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
2269
+ if (required && (WinUSBX[SUB_API_WINUSB].fn == NULL)) { \
2270
+ usbi_err(ctx, "GetProcAddress() failed for WinUsb_%s", #fn); \
2271
+ goto cleanup_winusb; \
2272
+ } \
2033
2273
  } while (0)
2034
2274
 
2035
- #define NativeWinUSBOnly_Set(fn) \
2275
+ #define libusbK_Set(sub_api, fn, required) \
2036
2276
  do { \
2037
- if (native_winusb) \
2038
- WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
2039
- else \
2040
- WinUSBX[i].fn = NULL; \
2277
+ pLibK_GetProcAddress((PVOID *)&WinUSBX[sub_api].fn, sub_api, KUSB_FNID_##fn); \
2278
+ if (required && (WinUSBX[sub_api].fn == NULL)) { \
2279
+ usbi_err(ctx, "LibK_GetProcAddress() failed for LibK_%s", #fn); \
2280
+ goto cleanup_libusbk; \
2281
+ } \
2041
2282
  } while (0)
2042
2283
 
2043
- static int winusbx_init(struct libusb_context *ctx)
2284
+ static bool winusbx_init(struct libusb_context *ctx)
2044
2285
  {
2045
- HMODULE h;
2046
- bool native_winusb;
2047
- int i;
2048
- KLIB_VERSION LibK_Version;
2049
- LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
2050
- LibK_GetVersion_t pLibK_GetVersion;
2286
+ HMODULE hWinUSB, hlibusbK;
2287
+
2288
+ hWinUSB = load_system_library(ctx, "WinUSB");
2289
+ if (hWinUSB != NULL) {
2290
+ WinUSB_Set(hWinUSB, AbortPipe, true);
2291
+ WinUSB_Set(hWinUSB, ControlTransfer, true);
2292
+ WinUSB_Set(hWinUSB, FlushPipe, true);
2293
+ WinUSB_Set(hWinUSB, Free, true);
2294
+ WinUSB_Set(hWinUSB, GetAssociatedInterface, true);
2295
+ WinUSB_Set(hWinUSB, Initialize, true);
2296
+ WinUSB_Set(hWinUSB, ReadPipe, true);
2297
+ WinUSB_Set(hWinUSB, ResetPipe, true);
2298
+ WinUSB_Set(hWinUSB, SetCurrentAlternateSetting, true);
2299
+ WinUSB_Set(hWinUSB, SetPipePolicy, true);
2300
+ WinUSB_Set(hWinUSB, WritePipe, true);
2301
+
2302
+ // Check for isochronous transfers support (available starting with Windows 8.1)
2303
+ WinUSB_Set(hWinUSB, ReadIsochPipeAsap, false);
2304
+ if (WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) {
2305
+ WinUSB_Set(hWinUSB, QueryPipeEx, true);
2306
+ WinUSB_Set(hWinUSB, RegisterIsochBuffer, true);
2307
+ WinUSB_Set(hWinUSB, UnregisterIsochBuffer, true);
2308
+ WinUSB_Set(hWinUSB, WriteIsochPipeAsap, true);
2309
+ }
2051
2310
 
2052
- h = LoadLibraryA("libusbK");
2311
+ WinUSBX[SUB_API_WINUSB].hDll = hWinUSB;
2053
2312
 
2054
- if (h == NULL) {
2055
- usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
2056
- h = LoadLibraryA("WinUSB");
2313
+ usbi_info(ctx, "WinUSB DLL available (%s isoch support)",
2314
+ (WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) ? "with" : "without");
2057
2315
 
2058
- if (h == NULL) {
2059
- usbi_warn(ctx, "WinUSB DLL is not available either, "
2060
- "you will not be able to access devices outside of enumeration");
2061
- return LIBUSB_ERROR_NOT_FOUND;
2316
+ cleanup_winusb:
2317
+ if (WinUSBX[SUB_API_WINUSB].hDll == NULL) {
2318
+ usbi_err(ctx, "failed to initialize WinUSB");
2319
+ memset(&WinUSBX[SUB_API_WINUSB], 0, sizeof(WinUSBX[SUB_API_WINUSB]));
2320
+ FreeLibrary(hWinUSB);
2321
+ hWinUSB = NULL;
2062
2322
  }
2063
2323
  } else {
2064
- usbi_dbg("using libusbK DLL for universal access");
2065
- pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
2324
+ usbi_info(ctx, "WinUSB DLL is not available");
2325
+ }
2326
+
2327
+ hlibusbK = load_system_library(ctx, "libusbK");
2328
+ if (hlibusbK != NULL) {
2329
+ LibK_GetVersion_t pLibK_GetVersion;
2330
+ LibK_GetProcAddress_t pLibK_GetProcAddress;
2331
+ int sub_api = 0;
2332
+
2333
+ pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(hlibusbK, "LibK_GetVersion");
2066
2334
  if (pLibK_GetVersion != NULL) {
2335
+ KLIB_VERSION LibK_Version;
2336
+
2067
2337
  pLibK_GetVersion(&LibK_Version);
2068
- usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
2338
+ usbi_dbg(ctx, "libusbK DLL found, version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
2069
2339
  LibK_Version.Micro, LibK_Version.Nano);
2340
+ } else {
2341
+ usbi_dbg(ctx, "libusbK DLL found, version unknown");
2070
2342
  }
2071
- pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
2343
+
2344
+ pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(hlibusbK, "LibK_GetProcAddress");
2072
2345
  if (pLibK_GetProcAddress == NULL) {
2073
2346
  usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
2074
- FreeLibrary(h);
2075
- return LIBUSB_ERROR_NOT_FOUND;
2347
+ goto cleanup_libusbk;
2076
2348
  }
2077
- }
2078
2349
 
2079
- native_winusb = (pLibK_GetProcAddress == NULL);
2080
- for (i = 0; i < SUB_API_MAX; i++) {
2081
- WinUSBX_Set(AbortPipe);
2082
- WinUSBX_Set(ControlTransfer);
2083
- WinUSBX_Set(FlushPipe);
2084
- WinUSBX_Set(Free);
2085
- WinUSBX_Set(GetAssociatedInterface);
2086
- WinUSBX_Set(Initialize);
2087
- WinUSBX_Set(ReadPipe);
2088
- if (!native_winusb)
2089
- WinUSBX_Set(ResetDevice);
2090
- WinUSBX_Set(ResetPipe);
2091
- WinUSBX_Set(SetCurrentAlternateSetting);
2092
- WinUSBX_Set(SetPipePolicy);
2093
- WinUSBX_Set(WritePipe);
2094
- WinUSBX_Set(IsoReadPipe);
2095
- WinUSBX_Set(IsoWritePipe);
2096
- NativeWinUSBOnly_Set(RegisterIsochBuffer);
2097
- NativeWinUSBOnly_Set(UnregisterIsochBuffer);
2098
- NativeWinUSBOnly_Set(WriteIsochPipeAsap);
2099
- NativeWinUSBOnly_Set(ReadIsochPipeAsap);
2100
- NativeWinUSBOnly_Set(QueryPipeEx);
2101
-
2102
- if (WinUSBX[i].Initialize != NULL) {
2103
- WinUSBX[i].initialized = true;
2104
- // Assume driver supports CancelIoEx() if it is available
2105
- WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL);
2106
- usbi_dbg("initalized sub API %s", winusbx_driver_names[i]);
2107
- } else {
2108
- usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]);
2109
- WinUSBX[i].initialized = false;
2350
+ // NB: The below for loop works because the sub_api value for WinUSB
2351
+ // is a higher value than that of libusbK and libusb0
2352
+ for (; sub_api < SUB_API_WINUSB; sub_api++) {
2353
+ libusbK_Set(sub_api, AbortPipe, true);
2354
+ libusbK_Set(sub_api, ControlTransfer, true);
2355
+ libusbK_Set(sub_api, FlushPipe, true);
2356
+ libusbK_Set(sub_api, Free, true);
2357
+ libusbK_Set(sub_api, GetAssociatedInterface, true);
2358
+ libusbK_Set(sub_api, Initialize, true);
2359
+ libusbK_Set(sub_api, ReadPipe, true);
2360
+ libusbK_Set(sub_api, ResetPipe, true);
2361
+ libusbK_Set(sub_api, SetCurrentAlternateSetting, true);
2362
+ libusbK_Set(sub_api, SetPipePolicy, true);
2363
+ libusbK_Set(sub_api, WritePipe, true);
2364
+
2365
+ // Optional isochronous support
2366
+ libusbK_Set(sub_api, IsoReadPipe, false);
2367
+ if (WinUSBX[sub_api].IsoReadPipe != NULL)
2368
+ libusbK_Set(sub_api, IsoWritePipe, true);
2369
+
2370
+ // Optional device reset support
2371
+ libusbK_Set(sub_api, ResetDevice, false);
2372
+
2373
+ WinUSBX[sub_api].hDll = hlibusbK;
2374
+ }
2375
+
2376
+ cleanup_libusbk:
2377
+ if (sub_api < SUB_API_WINUSB) {
2378
+ usbi_err(ctx, "failed to initialize libusbK");
2379
+ while (sub_api >= 0) {
2380
+ memset(&WinUSBX[sub_api], 0, sizeof(WinUSBX[sub_api]));
2381
+ sub_api--;
2382
+ }
2383
+ FreeLibrary(hlibusbK);
2384
+ hlibusbK = NULL;
2110
2385
  }
2386
+ } else {
2387
+ usbi_info(ctx, "libusbK DLL is not available");
2111
2388
  }
2112
2389
 
2113
- WinUSBX_handle = h;
2114
- return LIBUSB_SUCCESS;
2390
+ if ((hWinUSB == NULL) && (hlibusbK == NULL)) {
2391
+ usbi_warn(ctx, "neither WinUSB nor libusbK DLLs were found, "
2392
+ "you will not be able to access devices outside of enumeration");
2393
+ return false;
2394
+ }
2395
+
2396
+ return true;
2115
2397
  }
2116
2398
 
2117
2399
  static void winusbx_exit(void)
2118
2400
  {
2119
- if (WinUSBX_handle != NULL) {
2120
- FreeLibrary(WinUSBX_handle);
2121
- WinUSBX_handle = NULL;
2401
+ bool loaded = false;
2402
+ HMODULE hDll;
2122
2403
 
2123
- /* Reset the WinUSBX API structures */
2124
- memset(&WinUSBX, 0, sizeof(WinUSBX));
2404
+ hDll = WinUSBX[SUB_API_LIBUSBK].hDll;
2405
+ if (hDll != NULL) {
2406
+ FreeLibrary(hDll);
2407
+ loaded = true;
2408
+ }
2409
+
2410
+ hDll = WinUSBX[SUB_API_WINUSB].hDll;
2411
+ if (hDll != NULL) {
2412
+ FreeLibrary(hDll);
2413
+ loaded = true;
2125
2414
  }
2415
+
2416
+ // Reset the WinUSBX API structures if something was loaded
2417
+ if (loaded)
2418
+ memset(&WinUSBX, 0, sizeof(WinUSBX));
2126
2419
  }
2127
2420
 
2128
2421
  // NB: open and close must ensure that they only handle interface of
@@ -2130,9 +2423,8 @@ static void winusbx_exit(void)
2130
2423
  // composite_open(), with interfaces belonging to different APIs
2131
2424
  static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
2132
2425
  {
2133
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2134
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2135
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2426
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2427
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2136
2428
  HANDLE file_handle;
2137
2429
  int i;
2138
2430
 
@@ -2142,10 +2434,9 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
2142
2434
  for (i = 0; i < USB_MAXINTERFACES; i++) {
2143
2435
  if ((priv->usb_interface[i].path != NULL)
2144
2436
  && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
2145
- file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
2146
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2437
+ file_handle = windows_open(dev_handle, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
2147
2438
  if (file_handle == INVALID_HANDLE_VALUE) {
2148
- usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
2439
+ usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
2149
2440
  switch (GetLastError()) {
2150
2441
  case ERROR_FILE_NOT_FOUND: // The device was disconnected
2151
2442
  return LIBUSB_ERROR_NO_DEVICE;
@@ -2155,6 +2446,7 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
2155
2446
  return LIBUSB_ERROR_IO;
2156
2447
  }
2157
2448
  }
2449
+
2158
2450
  handle_priv->interface_handle[i].dev_handle = file_handle;
2159
2451
  }
2160
2452
  }
@@ -2164,15 +2456,15 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
2164
2456
 
2165
2457
  static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
2166
2458
  {
2167
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2168
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2459
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2460
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2169
2461
  HANDLE handle;
2170
2462
  int i;
2171
2463
 
2172
2464
  if (sub_api == SUB_API_NOTSET)
2173
2465
  sub_api = priv->sub_api;
2174
2466
 
2175
- if (!WinUSBX[sub_api].initialized)
2467
+ if (WinUSBX[sub_api].hDll == NULL)
2176
2468
  return;
2177
2469
 
2178
2470
  if (priv->apib->id == USB_API_COMPOSITE) {
@@ -2207,10 +2499,10 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
2207
2499
  }
2208
2500
  }
2209
2501
 
2210
- static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2502
+ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
2211
2503
  {
2212
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2213
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2504
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2505
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2214
2506
  HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
2215
2507
  UCHAR policy;
2216
2508
  ULONG timeout = 0;
@@ -2219,62 +2511,62 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
2219
2511
 
2220
2512
  CHECK_WINUSBX_AVAILABLE(sub_api);
2221
2513
 
2222
- // With handle and enpoints set (in parent), we can setup the default pipe properties
2514
+ // With handle and endpoints set (in parent), we can setup the default pipe properties
2223
2515
  // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
2224
2516
  for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) {
2225
2517
  endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
2226
2518
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2227
2519
  PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout))
2228
- usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
2520
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
2229
2521
 
2230
2522
  if ((i == -1) || (sub_api == SUB_API_LIBUSB0))
2231
2523
  continue; // Other policies don't apply to control endpoint or libusb0
2232
2524
 
2233
2525
  policy = false;
2526
+ handle_priv->interface_handle[iface].zlp[endpoint_address] = WINUSB_ZLP_UNSET;
2234
2527
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2235
2528
  SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
2236
- usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
2529
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
2237
2530
 
2238
2531
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2239
2532
  IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy))
2240
- usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
2533
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
2241
2534
 
2242
2535
  policy = true;
2243
2536
  /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
2244
2537
  https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
2245
2538
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2246
2539
  ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy))
2247
- usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
2540
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
2248
2541
 
2249
2542
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2250
2543
  AUTO_CLEAR_STALL, sizeof(UCHAR), &policy))
2251
- usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
2544
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
2252
2545
 
2253
2546
  if (sub_api == SUB_API_LIBUSBK) {
2254
2547
  if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2255
2548
  ISO_ALWAYS_START_ASAP, sizeof(UCHAR), &policy))
2256
- usbi_dbg("failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
2549
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
2257
2550
  }
2258
2551
  }
2259
2552
 
2260
2553
  return LIBUSB_SUCCESS;
2261
2554
  }
2262
2555
 
2263
- static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2556
+ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
2264
2557
  {
2265
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2266
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2267
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2558
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
2559
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2560
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2268
2561
  bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
2269
- SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
2270
- HDEVINFO dev_info = INVALID_HANDLE_VALUE;
2271
- SP_DEVINFO_DATA dev_info_data;
2272
- char *dev_path_no_guid = NULL;
2562
+ HDEVINFO dev_info;
2563
+ char *dev_interface_path = NULL;
2564
+ char *dev_interface_path_guid_start;
2273
2565
  char filter_path[] = "\\\\.\\libusb0-0000";
2274
2566
  bool found_filter = false;
2275
2567
  HANDLE file_handle, winusb_handle;
2276
- DWORD err;
2277
- int i;
2568
+ DWORD err, _index;
2569
+ int r;
2278
2570
 
2279
2571
  CHECK_WINUSBX_AVAILABLE(sub_api);
2280
2572
 
@@ -2292,27 +2584,30 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
2292
2584
  switch (err) {
2293
2585
  case ERROR_BAD_COMMAND:
2294
2586
  // The device was disconnected
2295
- usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
2587
+ usbi_err(ctx, "could not access interface %u: %s", iface, windows_error_str(0));
2296
2588
  return LIBUSB_ERROR_NO_DEVICE;
2297
2589
  default:
2298
2590
  // it may be that we're using the libusb0 filter driver.
2299
2591
  // TODO: can we move this whole business into the K/0 DLL?
2300
- for (i = 0; ; i++) {
2301
- safe_free(dev_interface_details);
2302
- safe_free(dev_path_no_guid);
2592
+ r = LIBUSB_SUCCESS;
2593
+ for (_index = 0; ; _index++) {
2594
+ safe_free(dev_interface_path);
2303
2595
 
2304
- dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path);
2305
- if ((found_filter) || (dev_interface_details == NULL))
2596
+ if (found_filter)
2597
+ break;
2598
+
2599
+ r = get_interface_details_filter(ctx, &dev_info, _index, filter_path, &dev_interface_path);
2600
+ if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL))
2306
2601
  break;
2307
2602
 
2308
2603
  // ignore GUID part
2309
- dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{"));
2310
- if (dev_path_no_guid == NULL)
2604
+ dev_interface_path_guid_start = strchr(dev_interface_path, '{');
2605
+ if (dev_interface_path_guid_start == NULL)
2311
2606
  continue;
2607
+ *dev_interface_path_guid_start = '\0';
2312
2608
 
2313
- if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) {
2314
- file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
2315
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2609
+ if (strncmp(dev_interface_path, priv->usb_interface[iface].path, strlen(dev_interface_path)) == 0) {
2610
+ file_handle = windows_open(dev_handle, filter_path, GENERIC_READ | GENERIC_WRITE);
2316
2611
  if (file_handle != INVALID_HANDLE_VALUE) {
2317
2612
  if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2318
2613
  // Replace the existing file handle with the working one
@@ -2328,9 +2623,10 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
2328
2623
  }
2329
2624
  }
2330
2625
  }
2331
- free(dev_interface_details);
2626
+ if (r != LIBUSB_SUCCESS)
2627
+ return r;
2332
2628
  if (!found_filter) {
2333
- usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
2629
+ usbi_err(ctx, "could not access interface %u: %s", iface, windows_error_str(err));
2334
2630
  return LIBUSB_ERROR_ACCESS;
2335
2631
  }
2336
2632
  }
@@ -2345,9 +2641,9 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
2345
2641
  file_handle = handle_priv->interface_handle[0].dev_handle;
2346
2642
  if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2347
2643
  handle_priv->interface_handle[0].api_handle = winusb_handle;
2348
- usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
2644
+ usbi_warn(ctx, "auto-claimed interface 0 (required to claim %u with WinUSB)", iface);
2349
2645
  } else {
2350
- usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
2646
+ usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %u with WinUSB): %s", iface, windows_error_str(0));
2351
2647
  return LIBUSB_ERROR_ACCESS;
2352
2648
  }
2353
2649
  }
@@ -2362,22 +2658,22 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
2362
2658
  case ERROR_ALREADY_EXISTS: // already claimed
2363
2659
  return LIBUSB_ERROR_BUSY;
2364
2660
  default:
2365
- usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
2661
+ usbi_err(ctx, "could not claim interface %u: %s", iface, windows_error_str(0));
2366
2662
  return LIBUSB_ERROR_ACCESS;
2367
2663
  }
2368
2664
  }
2369
2665
  handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle;
2370
2666
  }
2371
- usbi_dbg("claimed interface %d", iface);
2667
+ usbi_dbg(ctx, "claimed interface %u", iface);
2372
2668
  handle_priv->active_interface = iface;
2373
2669
 
2374
2670
  return LIBUSB_SUCCESS;
2375
2671
  }
2376
2672
 
2377
- static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2673
+ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
2378
2674
  {
2379
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2380
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2675
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2676
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2381
2677
  HANDLE winusb_handle;
2382
2678
 
2383
2679
  CHECK_WINUSBX_AVAILABLE(sub_api);
@@ -2397,12 +2693,12 @@ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *d
2397
2693
  */
2398
2694
  static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
2399
2695
  {
2400
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2401
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2696
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2697
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2402
2698
  int i;
2403
2699
 
2404
2700
  if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
2405
- usbi_dbg("unsupported API ID");
2701
+ usbi_dbg(HANDLE_CTX(dev_handle), "unsupported API ID");
2406
2702
  return -1;
2407
2703
  }
2408
2704
 
@@ -2421,14 +2717,14 @@ static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_
2421
2717
  */
2422
2718
  static int check_valid_interface(struct libusb_device_handle *dev_handle, unsigned short interface, int api_id)
2423
2719
  {
2424
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2425
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2720
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2721
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2426
2722
 
2427
2723
  if (interface >= USB_MAXINTERFACES)
2428
2724
  return -1;
2429
2725
 
2430
2726
  if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
2431
- usbi_dbg("unsupported API ID");
2727
+ usbi_dbg(HANDLE_CTX(dev_handle), "unsupported API ID");
2432
2728
  return -1;
2433
2729
  }
2434
2730
 
@@ -2466,12 +2762,11 @@ static int interface_by_endpoint(struct winusb_device_priv *priv,
2466
2762
  static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
2467
2763
  {
2468
2764
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2469
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2470
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2471
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2472
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2765
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
2766
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
2767
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
2473
2768
  PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
2474
- ULONG size;
2769
+ ULONG size, transferred;
2475
2770
  HANDLE winusb_handle;
2476
2771
  OVERLAPPED *overlapped;
2477
2772
  int current_interface;
@@ -2481,7 +2776,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
2481
2776
  size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
2482
2777
 
2483
2778
  // Windows places upper limits on the control transfer size
2484
- // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx
2779
+ // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-bandwidth-allocation#maximum-transfer-size
2485
2780
  if (size > MAX_CTRL_BUFFER_LENGTH)
2486
2781
  return LIBUSB_ERROR_INVALID_PARAM;
2487
2782
 
@@ -2494,87 +2789,58 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
2494
2789
  return LIBUSB_ERROR_NOT_FOUND;
2495
2790
  }
2496
2791
 
2497
- usbi_dbg("will use interface %d", current_interface);
2792
+ usbi_dbg(ITRANSFER_CTX(itransfer), "will use interface %d", current_interface);
2498
2793
 
2499
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2500
- overlapped = transfer_priv->pollable_fd.overlapped;
2794
+ transfer_priv->interface_number = (uint8_t)current_interface;
2795
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2796
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
2797
+ overlapped = get_transfer_priv_overlapped(itransfer);
2501
2798
 
2502
2799
  // Sending of set configuration control requests from WinUSB creates issues, except when using libusb0.sys
2503
2800
  if (sub_api != SUB_API_LIBUSB0
2504
2801
  && (LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD)
2505
2802
  && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
2506
2803
  if (setup->Value != priv->active_config) {
2507
- usbi_warn(ctx, "cannot set configuration other than the default one");
2508
- return LIBUSB_ERROR_INVALID_PARAM;
2804
+ usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
2805
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2509
2806
  }
2510
- windows_force_sync_completion(overlapped, 0);
2807
+ windows_force_sync_completion(itransfer, 0);
2511
2808
  } else {
2512
- if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) {
2809
+ if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, &transferred, overlapped)) {
2513
2810
  if (GetLastError() != ERROR_IO_PENDING) {
2514
- usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
2811
+ usbi_warn(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
2515
2812
  return LIBUSB_ERROR_IO;
2516
2813
  }
2517
2814
  } else {
2518
- windows_force_sync_completion(overlapped, size);
2815
+ windows_force_sync_completion(itransfer, transferred);
2519
2816
  }
2520
2817
  }
2521
2818
 
2522
- transfer_priv->interface_number = (uint8_t)current_interface;
2523
-
2524
2819
  return LIBUSB_SUCCESS;
2525
2820
  }
2526
2821
 
2527
- static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
2822
+ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
2528
2823
  {
2529
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2530
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2531
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2824
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
2825
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2532
2826
  HANDLE winusb_handle;
2533
2827
 
2534
2828
  CHECK_WINUSBX_AVAILABLE(sub_api);
2535
2829
 
2536
- if (altsetting > 255)
2537
- return LIBUSB_ERROR_INVALID_PARAM;
2538
-
2539
2830
  winusb_handle = handle_priv->interface_handle[iface].api_handle;
2540
2831
  if (!HANDLE_VALID(winusb_handle)) {
2541
- usbi_err(ctx, "interface must be claimed first");
2832
+ usbi_err(HANDLE_CTX(dev_handle), "interface must be claimed first");
2542
2833
  return LIBUSB_ERROR_NOT_FOUND;
2543
2834
  }
2544
2835
 
2545
- if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
2546
- usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
2836
+ if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, altsetting)) {
2837
+ usbi_err(HANDLE_CTX(dev_handle), "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
2547
2838
  return LIBUSB_ERROR_IO;
2548
2839
  }
2549
2840
 
2550
2841
  return LIBUSB_SUCCESS;
2551
2842
  }
2552
2843
 
2553
- static enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
2554
- {
2555
- /* Based on https://msdn.microsoft.com/en-us/library/windows/hardware/ff539136(v=vs.85).aspx :
2556
- * USBD_STATUS have the most significant 4 bits indicating overall status and the rest gives the details. */
2557
- switch (status >> 28) {
2558
- case 0x00: /* USBD_STATUS_SUCCESS */
2559
- return LIBUSB_TRANSFER_COMPLETED;
2560
- case 0x01: /* USBD_STATUS_PENDING */
2561
- return LIBUSB_TRANSFER_COMPLETED;
2562
- default: /* USBD_STATUS_ERROR */
2563
- switch (status & 0x0fffffff) {
2564
- case 0xC0006000: /* USBD_STATUS_TIMEOUT */
2565
- return LIBUSB_TRANSFER_TIMED_OUT;
2566
- case 0xC0010000: /* USBD_STATUS_CANCELED */
2567
- return LIBUSB_TRANSFER_CANCELLED;
2568
- case 0xC0000030: /* USBD_STATUS_ENDPOINT_HALTED */
2569
- return LIBUSB_TRANSFER_STALL;
2570
- case 0xC0007000: /* USBD_STATUS_DEVICE_GONE */
2571
- return LIBUSB_TRANSFER_NO_DEVICE;
2572
- default:
2573
- usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", status);
2574
- return LIBUSB_TRANSFER_ERROR;
2575
- }
2576
- }
2577
- }
2578
2844
 
2579
2845
  static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct libusb_transfer *transfer)
2580
2846
  {
@@ -2583,27 +2849,24 @@ static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct l
2583
2849
  // The role of this callback is to fallback to ContinueStream = FALSE if the transfer
2584
2850
  // did not succeed.
2585
2851
 
2586
- struct winusb_transfer_priv *transfer_priv = (struct winusb_transfer_priv *)
2587
- usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
2588
- BOOL fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
2852
+ struct winusb_transfer_priv *transfer_priv =
2853
+ get_winusb_transfer_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
2854
+ bool fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
2589
2855
  int idx;
2590
2856
 
2591
2857
  // Restore the user callback
2592
2858
  transfer->callback = transfer_priv->iso_user_callback;
2593
2859
 
2594
- for (idx = 0; idx < transfer->num_iso_packets && !fallback; ++idx) {
2595
- if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED) {
2596
- fallback = TRUE;
2597
- }
2860
+ for (idx = 0; idx < transfer->num_iso_packets && !fallback; idx++) {
2861
+ if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED)
2862
+ fallback = true;
2598
2863
  }
2599
2864
 
2600
2865
  if (!fallback) {
2601
2866
  // If the transfer was successful, we restore the user callback and call it.
2602
- if (transfer->callback) {
2867
+ if (transfer->callback)
2603
2868
  transfer->callback(transfer);
2604
- }
2605
- }
2606
- else {
2869
+ } else {
2607
2870
  // If the transfer wasn't successful we reschedule the transfer while forcing it
2608
2871
  // not to continue the stream. This might results in a 5-ms delay.
2609
2872
  transfer_priv->iso_break_stream = TRUE;
@@ -2613,27 +2876,28 @@ static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct l
2613
2876
  static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
2614
2877
  {
2615
2878
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2616
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2617
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2618
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2619
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2879
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
2880
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
2881
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
2620
2882
  HANDLE winusb_handle;
2621
2883
  OVERLAPPED *overlapped;
2622
- bool ret;
2884
+ BOOL ret;
2623
2885
  int current_interface;
2624
2886
 
2625
2887
  CHECK_WINUSBX_AVAILABLE(sub_api);
2626
2888
 
2627
2889
  current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
2628
2890
  if (current_interface < 0) {
2629
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
2891
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
2630
2892
  return LIBUSB_ERROR_NOT_FOUND;
2631
- } else {
2632
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
2633
2893
  }
2634
2894
 
2635
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2636
- overlapped = transfer_priv->pollable_fd.overlapped;
2895
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
2896
+
2897
+ transfer_priv->interface_number = (uint8_t)current_interface;
2898
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2899
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
2900
+ overlapped = get_transfer_priv_overlapped(itransfer);
2637
2901
 
2638
2902
  if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
2639
2903
  int i;
@@ -2641,6 +2905,11 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2641
2905
  size_t iso_ctx_size;
2642
2906
  PKISO_CONTEXT iso_context;
2643
2907
 
2908
+ if (WinUSBX[sub_api].IsoReadPipe == NULL) {
2909
+ usbi_warn(TRANSFER_CTX(transfer), "libusbK DLL does not support isoch transfers");
2910
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2911
+ }
2912
+
2644
2913
  iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET));
2645
2914
  transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size);
2646
2915
  if (transfer_priv->iso_context == NULL)
@@ -2658,49 +2927,34 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2658
2927
  }
2659
2928
 
2660
2929
  if (IS_XFERIN(transfer)) {
2661
- usbi_dbg("reading %d iso packets", transfer->num_iso_packets);
2930
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d iso packets", transfer->num_iso_packets);
2662
2931
  ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
2663
2932
  } else {
2664
- usbi_dbg("writing %d iso packets", transfer->num_iso_packets);
2933
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d iso packets", transfer->num_iso_packets);
2665
2934
  ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
2666
2935
  }
2667
2936
 
2668
- if (!ret) {
2669
- if (GetLastError() != ERROR_IO_PENDING) {
2670
- usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
2671
- return LIBUSB_ERROR_IO;
2672
- }
2673
- } else {
2674
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
2937
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
2938
+ usbi_err(TRANSFER_CTX(transfer), "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
2939
+ return LIBUSB_ERROR_IO;
2675
2940
  }
2676
2941
 
2677
- transfer_priv->interface_number = (uint8_t)current_interface;
2678
-
2679
2942
  return LIBUSB_SUCCESS;
2680
- }
2681
- else if (sub_api == SUB_API_WINUSB) {
2943
+ } else if (sub_api == SUB_API_WINUSB) {
2682
2944
  WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 };
2683
2945
  WINUSB_ISOCH_BUFFER_HANDLE buffer_handle;
2684
2946
  ULONG iso_transfer_size_multiple;
2685
2947
  int out_transfer_length = 0;
2686
2948
  int idx;
2687
2949
 
2688
- # define WINUSBX_CHECK_API_SUPPORTED(API) \
2689
- if (WinUSBX[sub_api].API == NULL) \
2690
- { \
2691
- usbi_dbg(#API " isn't available"); \
2692
- return LIBUSB_ERROR_NOT_SUPPORTED; \
2693
- }
2694
-
2695
2950
  // Depending on the version of Microsoft WinUSB, isochronous transfers may not be supported.
2696
- WINUSBX_CHECK_API_SUPPORTED(RegisterIsochBuffer);
2697
- WINUSBX_CHECK_API_SUPPORTED(ReadIsochPipeAsap);
2698
- WINUSBX_CHECK_API_SUPPORTED(WriteIsochPipeAsap);
2699
- WINUSBX_CHECK_API_SUPPORTED(UnregisterIsochBuffer);
2700
- WINUSBX_CHECK_API_SUPPORTED(QueryPipeEx);
2951
+ if (WinUSBX[sub_api].ReadIsochPipeAsap == NULL) {
2952
+ usbi_warn(TRANSFER_CTX(transfer), "WinUSB DLL does not support isoch transfers");
2953
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2954
+ }
2701
2955
 
2702
2956
  if (sizeof(struct libusb_iso_packet_descriptor) != sizeof(USBD_ISO_PACKET_DESCRIPTOR)) {
2703
- usbi_dbg("The size of Microsoft WinUsb and libusb isochronous packet descriptor doesn't match.");
2957
+ usbi_err(TRANSFER_CTX(transfer), "size of WinUsb and libusb isoch packet descriptors don't match");
2704
2958
  return LIBUSB_ERROR_NOT_SUPPORTED;
2705
2959
  }
2706
2960
 
@@ -2708,18 +2962,17 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2708
2962
  for (idx = 0; idx < priv->usb_interface[current_interface].nb_endpoints; ++idx) {
2709
2963
  ret = WinUSBX[sub_api].QueryPipeEx(winusb_handle, (UINT8)priv->usb_interface[current_interface].current_altsetting, (UCHAR)idx, &pipe_info_ex);
2710
2964
  if (!ret) {
2711
- usbi_dbg("Couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
2965
+ usbi_err(TRANSFER_CTX(transfer), "couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
2712
2966
  return LIBUSB_ERROR_NOT_FOUND;
2713
2967
  }
2714
2968
 
2715
- if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous) {
2969
+ if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous)
2716
2970
  break;
2717
- }
2718
2971
  }
2719
2972
 
2720
2973
  // Make sure we found the index.
2721
- if (idx >= priv->usb_interface[current_interface].nb_endpoints) {
2722
- usbi_dbg("Couldn't find the isochronous endpoint %02x.", transfer->endpoint);
2974
+ if (idx == priv->usb_interface[current_interface].nb_endpoints) {
2975
+ usbi_err(TRANSFER_CTX(transfer), "couldn't find isoch endpoint 0x%02x", transfer->endpoint);
2723
2976
  return LIBUSB_ERROR_NOT_FOUND;
2724
2977
  }
2725
2978
 
@@ -2727,27 +2980,25 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2727
2980
  int interval = pipe_info_ex.Interval;
2728
2981
 
2729
2982
  // For high-speed and SuperSpeed device, the interval is 2**(bInterval-1).
2730
- if (libusb_get_device_speed(libusb_get_device(transfer->dev_handle)) >= LIBUSB_SPEED_HIGH) {
2983
+ if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH)
2731
2984
  interval = (1 << (pipe_info_ex.Interval - 1));
2732
- }
2733
2985
 
2734
- // WinUSB only supports isochronous transfers spanning a full USB frames. Later, we might be smarter about this
2986
+ // WinUSB only supports isoch transfers spanning a full USB frames. Later, we might be smarter about this
2735
2987
  // and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped
2736
2988
  // IO...
2737
2989
  iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
2738
2990
  if (transfer->length % iso_transfer_size_multiple != 0) {
2739
- usbi_dbg("The length of isochronous buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
2991
+ usbi_err(TRANSFER_CTX(transfer), "length of isoch buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
2740
2992
  return LIBUSB_ERROR_INVALID_PARAM;
2741
2993
  }
2742
- }
2743
- else {
2744
- // If this is an OUT transfer, we make sure the isochronous packets are contiguous as this isn't supported otherwise.
2745
- BOOL size_should_be_zero = FALSE;
2746
- out_transfer_length = 0;
2994
+ } else {
2995
+ // If this is an OUT transfer, we make sure the isoch packets are contiguous as this isn't supported otherwise.
2996
+ bool size_should_be_zero = false;
2997
+
2747
2998
  for (idx = 0; idx < transfer->num_iso_packets; ++idx) {
2748
2999
  if ((size_should_be_zero && transfer->iso_packet_desc[idx].length != 0) ||
2749
3000
  (transfer->iso_packet_desc[idx].length != pipe_info_ex.MaximumBytesPerInterval && idx + 1 < transfer->num_iso_packets && transfer->iso_packet_desc[idx + 1].length > 0)) {
2750
- usbi_dbg("Isochronous packets for OUT transfer with Microsoft WinUSB must be contiguous in memory.");
3001
+ usbi_err(TRANSFER_CTX(transfer), "isoch packets for OUT transfer with WinUSB must be contiguous in memory");
2751
3002
  return LIBUSB_ERROR_INVALID_PARAM;
2752
3003
  }
2753
3004
 
@@ -2760,20 +3011,20 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2760
3011
  if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
2761
3012
  transfer_priv->isoch_buffer_handle = NULL;
2762
3013
  } else {
2763
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
3014
+ usbi_err(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
2764
3015
  return LIBUSB_ERROR_OTHER;
2765
3016
  }
2766
3017
  }
2767
3018
 
2768
- // Register the isochronous buffer to the operating system.
3019
+ // Register the isoch buffer to the operating system.
2769
3020
  ret = WinUSBX[sub_api].RegisterIsochBuffer(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, &buffer_handle);
2770
3021
  if (!ret) {
2771
- usbi_dbg("Microsoft WinUSB refused to allocate an isochronous buffer.");
3022
+ usbi_err(TRANSFER_CTX(transfer), "failed to register WinUSB isoch buffer: %s", windows_error_str(0));
2772
3023
  return LIBUSB_ERROR_NO_MEM;
2773
3024
  }
2774
3025
 
2775
3026
  // Important note: the WinUSB_Read/WriteIsochPipeAsap API requires a ContinueStream parameter that tells whether the isochronous
2776
- // stream must be continued or if the WinUSB driver can schedule the transfer at its conveniance. Profiling subsequent transfers
3027
+ // stream must be continued or if the WinUSB driver can schedule the transfer at its convenience. Profiling subsequent transfers
2777
3028
  // with ContinueStream = FALSE showed that 5 frames, i.e. about 5 milliseconds, were left empty between each transfer. This
2778
3029
  // is critical as this greatly diminish the achievable isochronous bandwidth. We solved the problem using the following strategy:
2779
3030
  // - Transfers are first scheduled with ContinueStream = TRUE and with winusbx_iso_transfer_continue_stream_callback as user callback.
@@ -2785,38 +3036,22 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2785
3036
  }
2786
3037
 
2787
3038
  // Initiate the transfers.
2788
- if (IS_XFERIN(transfer)) {
3039
+ if (IS_XFERIN(transfer))
2789
3040
  ret = WinUSBX[sub_api].ReadIsochPipeAsap(buffer_handle, 0, transfer->length, !transfer_priv->iso_break_stream, transfer->num_iso_packets, (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc, overlapped);
2790
- }
2791
- else {
3041
+ else
2792
3042
  ret = WinUSBX[sub_api].WriteIsochPipeAsap(buffer_handle, 0, out_transfer_length, !transfer_priv->iso_break_stream, overlapped);
3043
+
3044
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
3045
+ usbi_err(TRANSFER_CTX(transfer), "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
3046
+ if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle))
3047
+ usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
3048
+ return LIBUSB_ERROR_IO;
2793
3049
  }
2794
3050
 
2795
3051
  // Restore the ContinueStream parameter to TRUE.
2796
3052
  transfer_priv->iso_break_stream = FALSE;
2797
3053
 
2798
- if (!ret) {
2799
- if (GetLastError() == ERROR_IO_PENDING) {
2800
- transfer_priv->isoch_buffer_handle = buffer_handle;
2801
- } else {
2802
- usbi_err(ctx, "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
2803
- if (WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
2804
- transfer_priv->isoch_buffer_handle = NULL;
2805
- return LIBUSB_ERROR_IO;
2806
- } else {
2807
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
2808
- return LIBUSB_ERROR_OTHER;
2809
- }
2810
- }
2811
- } else {
2812
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
2813
- if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
2814
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
2815
- return LIBUSB_ERROR_OTHER;
2816
- }
2817
- }
2818
-
2819
- transfer_priv->interface_number = (uint8_t)current_interface;
3054
+ transfer_priv->isoch_buffer_handle = buffer_handle;
2820
3055
 
2821
3056
  return LIBUSB_SUCCESS;
2822
3057
  } else {
@@ -2828,55 +3063,66 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
2828
3063
  static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
2829
3064
  {
2830
3065
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2831
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2832
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2833
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2834
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3066
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
3067
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
3068
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
2835
3069
  HANDLE winusb_handle;
2836
3070
  OVERLAPPED *overlapped;
2837
- bool ret;
3071
+ BOOL ret;
2838
3072
  int current_interface;
2839
3073
 
2840
3074
  CHECK_WINUSBX_AVAILABLE(sub_api);
2841
3075
 
2842
3076
  current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
2843
3077
  if (current_interface < 0) {
2844
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
3078
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
2845
3079
  return LIBUSB_ERROR_NOT_FOUND;
2846
3080
  }
2847
3081
 
2848
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
3082
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
2849
3083
 
2850
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2851
- overlapped = transfer_priv->pollable_fd.overlapped;
3084
+ transfer_priv->interface_number = (uint8_t)current_interface;
3085
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
3086
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
3087
+ overlapped = get_transfer_priv_overlapped(itransfer);
2852
3088
 
2853
3089
  if (IS_XFERIN(transfer)) {
2854
- usbi_dbg("reading %d bytes", transfer->length);
3090
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d bytes", transfer->length);
2855
3091
  ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
2856
3092
  } else {
2857
- usbi_dbg("writing %d bytes", transfer->length);
3093
+ // Set SHORT_PACKET_TERMINATE if ZLP requested.
3094
+ // Changing this can be a problem with packets in flight, so only allow on the first transfer.
3095
+ UCHAR policy = (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) != 0;
3096
+ uint8_t* current_zlp = &handle_priv->interface_handle[current_interface].zlp[transfer->endpoint];
3097
+ if (*current_zlp == WINUSB_ZLP_UNSET) {
3098
+ if (policy &&
3099
+ !WinUSBX[sub_api].SetPipePolicy(winusb_handle, transfer->endpoint,
3100
+ SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
3101
+ usbi_err(TRANSFER_CTX(transfer), "failed to set SHORT_PACKET_TERMINATE for endpoint %02X", transfer->endpoint);
3102
+ return LIBUSB_ERROR_NOT_SUPPORTED;
3103
+ }
3104
+ *current_zlp = policy ? WINUSB_ZLP_ON : WINUSB_ZLP_OFF;
3105
+ } else if (policy != (*current_zlp == WINUSB_ZLP_ON)) {
3106
+ usbi_err(TRANSFER_CTX(transfer), "cannot change ZERO_PACKET for endpoint %02X on Windows", transfer->endpoint);
3107
+ return LIBUSB_ERROR_NOT_SUPPORTED;
3108
+ }
3109
+
3110
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d bytes", transfer->length);
2858
3111
  ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
2859
3112
  }
2860
3113
 
2861
- if (!ret) {
2862
- if (GetLastError() != ERROR_IO_PENDING) {
2863
- usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
2864
- return LIBUSB_ERROR_IO;
2865
- }
2866
- } else {
2867
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
3114
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
3115
+ usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
3116
+ return LIBUSB_ERROR_IO;
2868
3117
  }
2869
3118
 
2870
- transfer_priv->interface_number = (uint8_t)current_interface;
2871
-
2872
3119
  return LIBUSB_SUCCESS;
2873
3120
  }
2874
3121
 
2875
3122
  static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
2876
3123
  {
2877
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2878
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2879
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3124
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3125
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2880
3126
  HANDLE winusb_handle;
2881
3127
  int current_interface;
2882
3128
 
@@ -2884,68 +3130,37 @@ static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_hand
2884
3130
 
2885
3131
  current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
2886
3132
  if (current_interface < 0) {
2887
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
3133
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
2888
3134
  return LIBUSB_ERROR_NOT_FOUND;
2889
3135
  }
2890
3136
 
2891
- usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
3137
+ usbi_dbg(HANDLE_CTX(dev_handle), "matched endpoint %02X with interface %d", endpoint, current_interface);
2892
3138
  winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2893
3139
 
2894
3140
  if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
2895
- usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
3141
+ usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
2896
3142
  return LIBUSB_ERROR_NO_DEVICE;
2897
3143
  }
2898
3144
 
2899
3145
  return LIBUSB_SUCCESS;
2900
3146
  }
2901
3147
 
2902
- /*
2903
- * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
2904
- * through testing as well):
2905
- * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
2906
- * the control transfer using CancelIo"
2907
- */
2908
- static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
2909
- {
2910
- // Cancelling of the I/O is done in the parent
2911
- return LIBUSB_SUCCESS;
2912
- }
2913
-
2914
- static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
3148
+ static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
2915
3149
  {
2916
3150
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2917
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2918
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2919
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2920
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3151
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
3152
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
3153
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
3154
+ int current_interface = transfer_priv->interface_number;
2921
3155
  HANDLE handle;
2922
- int current_interface;
2923
3156
 
2924
3157
  CHECK_WINUSBX_AVAILABLE(sub_api);
2925
3158
 
2926
- current_interface = transfer_priv->interface_number;
2927
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
2928
- usbi_err(ctx, "program assertion failed: invalid interface_number");
2929
- return LIBUSB_ERROR_NOT_FOUND;
2930
- }
2931
- usbi_dbg("will use interface %d", current_interface);
2932
-
2933
- if (WinUSBX[sub_api].CancelIoEx_supported) {
2934
- // Try to use CancelIoEx if available to cancel just a single transfer
2935
- handle = handle_priv->interface_handle[current_interface].dev_handle;
2936
- if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped))
2937
- return LIBUSB_SUCCESS;
2938
- else if (GetLastError() == ERROR_NOT_FOUND)
2939
- return LIBUSB_ERROR_NOT_FOUND;
2940
-
2941
- // Not every driver implements the necessary functionality for CancelIoEx
2942
- usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]);
2943
- WinUSBX[sub_api].CancelIoEx_supported = false;
2944
- }
3159
+ usbi_dbg(TRANSFER_CTX(transfer), "will use interface %d", current_interface);
2945
3160
 
2946
3161
  handle = handle_priv->interface_handle[current_interface].api_handle;
2947
3162
  if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) {
2948
- usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
3163
+ usbi_err(TRANSFER_CTX(transfer), "AbortPipe failed: %s", windows_error_str(0));
2949
3164
  return LIBUSB_ERROR_NO_DEVICE;
2950
3165
  }
2951
3166
 
@@ -2963,9 +3178,8 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
2963
3178
  // TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
2964
3179
  static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
2965
3180
  {
2966
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2967
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2968
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3181
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3182
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
2969
3183
  HANDLE winusb_handle;
2970
3184
  int i, j;
2971
3185
 
@@ -2976,26 +3190,26 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
2976
3190
  winusb_handle = handle_priv->interface_handle[i].api_handle;
2977
3191
  if (HANDLE_VALID(winusb_handle)) {
2978
3192
  for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
2979
- usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
3193
+ usbi_dbg(HANDLE_CTX(dev_handle), "resetting ep %02X", priv->usb_interface[i].endpoint[j]);
2980
3194
  if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
2981
- usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
3195
+ usbi_err(HANDLE_CTX(dev_handle), "AbortPipe (pipe address %02X) failed: %s",
2982
3196
  priv->usb_interface[i].endpoint[j], windows_error_str(0));
2983
3197
 
2984
3198
  // FlushPipe seems to fail on OUT pipes
2985
3199
  if (IS_EPIN(priv->usb_interface[i].endpoint[j])
2986
3200
  && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])))
2987
- usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
3201
+ usbi_err(HANDLE_CTX(dev_handle), "FlushPipe (pipe address %02X) failed: %s",
2988
3202
  priv->usb_interface[i].endpoint[j], windows_error_str(0));
2989
3203
 
2990
3204
  if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
2991
- usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
3205
+ usbi_err(HANDLE_CTX(dev_handle), "ResetPipe (pipe address %02X) failed: %s",
2992
3206
  priv->usb_interface[i].endpoint[j], windows_error_str(0));
2993
3207
  }
2994
3208
  }
2995
3209
  }
2996
3210
 
2997
3211
  // libusbK & libusb0 have the ability to issue an actual device reset
2998
- if (WinUSBX[sub_api].ResetDevice != NULL) {
3212
+ if ((sub_api != SUB_API_WINUSB) && (WinUSBX[sub_api].ResetDevice != NULL)) {
2999
3213
  winusb_handle = handle_priv->interface_handle[0].api_handle;
3000
3214
  if (HANDLE_VALID(winusb_handle))
3001
3215
  WinUSBX[sub_api].ResetDevice(winusb_handle);
@@ -3004,21 +3218,17 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
3004
3218
  return LIBUSB_SUCCESS;
3005
3219
  }
3006
3220
 
3007
- static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
3221
+ static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
3008
3222
  {
3009
3223
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3010
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3011
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3012
- PKISO_CONTEXT iso_context;
3224
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
3013
3225
  int i;
3014
3226
 
3015
3227
  if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
3016
- CHECK_WINUSBX_AVAILABLE(sub_api);
3017
-
3018
3228
  // for isochronous, need to copy the individual iso packet actual_lengths and statuses
3019
3229
  if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
3020
3230
  // iso only supported on libusbk-based backends for now
3021
- iso_context = transfer_priv->iso_context;
3231
+ PKISO_CONTEXT iso_context = transfer_priv->iso_context;
3022
3232
  for (i = 0; i < transfer->num_iso_packets; i++) {
3023
3233
  transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length;
3024
3234
  // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status
@@ -3029,31 +3239,28 @@ static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransf
3029
3239
  /* Convert isochronous packet descriptor between Windows and libusb representation.
3030
3240
  * Both representation are guaranteed to have the same length in bytes.*/
3031
3241
  PUSBD_ISO_PACKET_DESCRIPTOR usbd_iso_packet_desc = (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc;
3032
- for (i = 0; i < transfer->num_iso_packets; ++i)
3033
- {
3034
- int length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length;
3035
- int actual_length = usbd_iso_packet_desc[i].Length;
3242
+ for (i = 0; i < transfer->num_iso_packets; i++) {
3243
+ unsigned int packet_length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length;
3244
+ unsigned int actual_length = usbd_iso_packet_desc[i].Length;
3036
3245
  USBD_STATUS status = usbd_iso_packet_desc[i].Status;
3037
3246
 
3038
- transfer->iso_packet_desc[i].length = length;
3247
+ transfer->iso_packet_desc[i].length = packet_length;
3039
3248
  transfer->iso_packet_desc[i].actual_length = actual_length;
3040
3249
  transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(status);
3041
3250
  }
3042
- }
3043
- else {
3044
- for (i = 0; i < transfer->num_iso_packets; ++i)
3045
- {
3251
+ } else {
3252
+ for (i = 0; i < transfer->num_iso_packets; i++) {
3046
3253
  transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED;
3047
3254
  }
3048
3255
  }
3049
3256
  } else {
3050
3257
  // This should only occur if backend is not set correctly or other backend isoc is partially implemented
3051
3258
  PRINT_UNSUPPORTED_API(copy_transfer_data);
3052
- return LIBUSB_ERROR_NOT_SUPPORTED;
3259
+ return LIBUSB_TRANSFER_ERROR;
3053
3260
  }
3054
3261
  }
3055
3262
 
3056
- itransfer->transferred += io_size;
3263
+ itransfer->transferred += (int)length;
3057
3264
  return LIBUSB_TRANSFER_COMPLETED;
3058
3265
  }
3059
3266
 
@@ -3075,7 +3282,7 @@ static int _hid_wcslen(WCHAR *str)
3075
3282
  return i;
3076
3283
  }
3077
3284
 
3078
- static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3285
+ static int _hid_get_device_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
3079
3286
  {
3080
3287
  struct libusb_device_descriptor d;
3081
3288
 
@@ -3086,12 +3293,12 @@ static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, s
3086
3293
  d.bDeviceSubClass = 0;
3087
3294
  d.bDeviceProtocol = 0;
3088
3295
  d.bMaxPacketSize0 = 64; /* fix this! */
3089
- d.idVendor = (uint16_t)dev->vid;
3090
- d.idProduct = (uint16_t)dev->pid;
3296
+ d.idVendor = (uint16_t)hid_priv->vid;
3297
+ d.idProduct = (uint16_t)hid_priv->pid;
3091
3298
  d.bcdDevice = 0x0100;
3092
- d.iManufacturer = dev->string_index[0];
3093
- d.iProduct = dev->string_index[1];
3094
- d.iSerialNumber = dev->string_index[2];
3299
+ d.iManufacturer = hid_priv->string_index[0];
3300
+ d.iProduct = hid_priv->string_index[1];
3301
+ d.iSerialNumber = hid_priv->string_index[2];
3095
3302
  d.bNumConfigurations = 1;
3096
3303
 
3097
3304
  if (*size > LIBUSB_DT_DEVICE_SIZE)
@@ -3101,7 +3308,7 @@ static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, s
3101
3308
  return LIBUSB_COMPLETED;
3102
3309
  }
3103
3310
 
3104
- static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3311
+ static int _hid_get_config_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
3105
3312
  {
3106
3313
  char num_endpoints = 0;
3107
3314
  size_t config_total_len = 0;
@@ -3112,9 +3319,9 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
3112
3319
  struct libusb_endpoint_descriptor *ed;
3113
3320
  size_t tmp_size;
3114
3321
 
3115
- if (dev->input_report_size)
3322
+ if (hid_priv->input_report_size)
3116
3323
  num_endpoints++;
3117
- if (dev->output_report_size)
3324
+ if (hid_priv->output_report_size)
3118
3325
  num_endpoints++;
3119
3326
 
3120
3327
  config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
@@ -3148,24 +3355,24 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
3148
3355
  id->iInterface = 0;
3149
3356
 
3150
3357
  tmp_size = LIBUSB_DT_HID_SIZE;
3151
- _hid_get_hid_descriptor(dev, hd, &tmp_size);
3358
+ _hid_get_hid_descriptor(hid_priv, hd, &tmp_size);
3152
3359
 
3153
- if (dev->input_report_size) {
3360
+ if (hid_priv->input_report_size) {
3154
3361
  ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
3155
3362
  ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
3156
3363
  ed->bEndpointAddress = HID_IN_EP;
3157
3364
  ed->bmAttributes = 3;
3158
- ed->wMaxPacketSize = dev->input_report_size - 1;
3365
+ ed->wMaxPacketSize = hid_priv->input_report_size - 1;
3159
3366
  ed->bInterval = 10;
3160
3367
  ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE);
3161
3368
  }
3162
3369
 
3163
- if (dev->output_report_size) {
3370
+ if (hid_priv->output_report_size) {
3164
3371
  ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
3165
3372
  ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
3166
3373
  ed->bEndpointAddress = HID_OUT_EP;
3167
3374
  ed->bmAttributes = 3;
3168
- ed->wMaxPacketSize = dev->output_report_size - 1;
3375
+ ed->wMaxPacketSize = hid_priv->output_report_size - 1;
3169
3376
  ed->bInterval = 10;
3170
3377
  }
3171
3378
 
@@ -3176,7 +3383,7 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
3176
3383
  return LIBUSB_COMPLETED;
3177
3384
  }
3178
3385
 
3179
- static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
3386
+ static int _hid_get_string_descriptor(struct hid_device_priv *hid_priv, int _index,
3180
3387
  void *data, size_t *size, HANDLE hid_handle)
3181
3388
  {
3182
3389
  void *tmp = NULL;
@@ -3187,17 +3394,14 @@ static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
3187
3394
  /* language ID, EN-US */
3188
3395
  char string_langid[] = {0x09, 0x04};
3189
3396
 
3190
- if ((*size < 2) || (*size > 255))
3191
- return LIBUSB_ERROR_OVERFLOW;
3192
-
3193
3397
  if (_index == 0) {
3194
3398
  tmp = string_langid;
3195
3399
  tmp_size = sizeof(string_langid) + 2;
3196
3400
  } else {
3197
3401
  for (i = 0; i < 3; i++) {
3198
- if (_index == (dev->string_index[i])) {
3199
- tmp = dev->string[i];
3200
- tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
3402
+ if (_index == (hid_priv->string_index[i])) {
3403
+ tmp = hid_priv->string[i];
3404
+ tmp_size = (_hid_wcslen(hid_priv->string[i]) + 1) * sizeof(WCHAR);
3201
3405
  break;
3202
3406
  }
3203
3407
  }
@@ -3224,13 +3428,13 @@ static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
3224
3428
  return LIBUSB_COMPLETED;
3225
3429
  }
3226
3430
 
3227
- static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3431
+ static int _hid_get_hid_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
3228
3432
  {
3229
3433
  struct libusb_hid_descriptor d;
3230
3434
  uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
3231
3435
  size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
3232
3436
 
3233
- _hid_get_report_descriptor(dev, tmp, &report_len);
3437
+ _hid_get_report_descriptor(hid_priv, tmp, &report_len);
3234
3438
 
3235
3439
  d.bLength = LIBUSB_DT_HID_SIZE;
3236
3440
  d.bDescriptorType = LIBUSB_DT_HID;
@@ -3247,19 +3451,19 @@ static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size
3247
3451
  return LIBUSB_COMPLETED;
3248
3452
  }
3249
3453
 
3250
- static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3454
+ static int _hid_get_report_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
3251
3455
  {
3252
3456
  uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
3253
3457
  size_t i = 0;
3254
3458
 
3255
3459
  /* usage page */
3256
- d[i++] = 0x06; d[i++] = dev->usagePage & 0xFF; d[i++] = dev->usagePage >> 8;
3460
+ d[i++] = 0x06; d[i++] = hid_priv->usagePage & 0xFF; d[i++] = hid_priv->usagePage >> 8;
3257
3461
  /* usage */
3258
- d[i++] = 0x09; d[i++] = (uint8_t)dev->usage;
3462
+ d[i++] = 0x09; d[i++] = (uint8_t)hid_priv->usage;
3259
3463
  /* start collection (application) */
3260
3464
  d[i++] = 0xA1; d[i++] = 0x01;
3261
3465
  /* input report */
3262
- if (dev->input_report_size) {
3466
+ if (hid_priv->input_report_size) {
3263
3467
  /* usage (vendor defined) */
3264
3468
  d[i++] = 0x09; d[i++] = 0x01;
3265
3469
  /* logical minimum (0) */
@@ -3269,12 +3473,12 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
3269
3473
  /* report size (8 bits) */
3270
3474
  d[i++] = 0x75; d[i++] = 0x08;
3271
3475
  /* report count */
3272
- d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
3476
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->input_report_size - 1;
3273
3477
  /* input (data, variable, absolute) */
3274
3478
  d[i++] = 0x81; d[i++] = 0x00;
3275
3479
  }
3276
3480
  /* output report */
3277
- if (dev->output_report_size) {
3481
+ if (hid_priv->output_report_size) {
3278
3482
  /* usage (vendor defined) */
3279
3483
  d[i++] = 0x09; d[i++] = 0x02;
3280
3484
  /* logical minimum (0) */
@@ -3284,12 +3488,12 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
3284
3488
  /* report size (8 bits) */
3285
3489
  d[i++] = 0x75; d[i++] = 0x08;
3286
3490
  /* report count */
3287
- d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
3491
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->output_report_size - 1;
3288
3492
  /* output (data, variable, absolute) */
3289
3493
  d[i++] = 0x91; d[i++] = 0x00;
3290
3494
  }
3291
3495
  /* feature report */
3292
- if (dev->feature_report_size) {
3496
+ if (hid_priv->feature_report_size) {
3293
3497
  /* usage (vendor defined) */
3294
3498
  d[i++] = 0x09; d[i++] = 0x03;
3295
3499
  /* logical minimum (0) */
@@ -3299,7 +3503,7 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
3299
3503
  /* report size (8 bits) */
3300
3504
  d[i++] = 0x75; d[i++] = 0x08;
3301
3505
  /* report count */
3302
- d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
3506
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->feature_report_size - 1;
3303
3507
  /* feature (data, variable, absolute) */
3304
3508
  d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
3305
3509
  }
@@ -3314,54 +3518,56 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
3314
3518
  return LIBUSB_COMPLETED;
3315
3519
  }
3316
3520
 
3317
- static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
3521
+ static int _hid_get_descriptor(struct libusb_device *dev, HANDLE hid_handle, int recipient,
3318
3522
  int type, int _index, void *data, size_t *size)
3319
3523
  {
3524
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
3525
+ UNUSED(recipient);
3526
+
3320
3527
  switch (type) {
3321
3528
  case LIBUSB_DT_DEVICE:
3322
- usbi_dbg("LIBUSB_DT_DEVICE");
3323
- return _hid_get_device_descriptor(dev, data, size);
3529
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_DEVICE");
3530
+ return _hid_get_device_descriptor(priv->hid, data, size);
3324
3531
  case LIBUSB_DT_CONFIG:
3325
- usbi_dbg("LIBUSB_DT_CONFIG");
3532
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_CONFIG");
3326
3533
  if (!_index)
3327
- return _hid_get_config_descriptor(dev, data, size);
3534
+ return _hid_get_config_descriptor(priv->hid, data, size);
3328
3535
  return LIBUSB_ERROR_INVALID_PARAM;
3329
3536
  case LIBUSB_DT_STRING:
3330
- usbi_dbg("LIBUSB_DT_STRING");
3331
- return _hid_get_string_descriptor(dev, _index, data, size, hid_handle);
3537
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_STRING");
3538
+ return _hid_get_string_descriptor(priv->hid, _index, data, size, hid_handle);
3332
3539
  case LIBUSB_DT_HID:
3333
- usbi_dbg("LIBUSB_DT_HID");
3540
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_HID");
3334
3541
  if (!_index)
3335
- return _hid_get_hid_descriptor(dev, data, size);
3542
+ return _hid_get_hid_descriptor(priv->hid, data, size);
3336
3543
  return LIBUSB_ERROR_INVALID_PARAM;
3337
3544
  case LIBUSB_DT_REPORT:
3338
- usbi_dbg("LIBUSB_DT_REPORT");
3545
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_REPORT");
3339
3546
  if (!_index)
3340
- return _hid_get_report_descriptor(dev, data, size);
3547
+ return _hid_get_report_descriptor(priv->hid, data, size);
3341
3548
  return LIBUSB_ERROR_INVALID_PARAM;
3342
3549
  case LIBUSB_DT_PHYSICAL:
3343
- usbi_dbg("LIBUSB_DT_PHYSICAL");
3550
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_PHYSICAL");
3344
3551
  if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
3345
3552
  return LIBUSB_COMPLETED;
3346
3553
  return LIBUSB_ERROR_OTHER;
3347
3554
  }
3348
3555
 
3349
- usbi_dbg("unsupported");
3556
+ usbi_warn(DEVICE_CTX(dev), "unsupported");
3350
3557
  return LIBUSB_ERROR_NOT_SUPPORTED;
3351
3558
  }
3352
3559
 
3353
- static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
3354
- struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
3560
+ static int _hid_get_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
3561
+ struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
3355
3562
  {
3563
+ DWORD ioctl_code, expected_size = (DWORD)size;
3356
3564
  uint8_t *buf;
3357
- DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
3358
- int r = LIBUSB_SUCCESS;
3359
3565
 
3360
3566
  if (tp->hid_buffer != NULL)
3361
- usbi_dbg("program assertion failed: hid_buffer is not NULL");
3567
+ usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
3362
3568
 
3363
- if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
3364
- usbi_dbg("invalid size (%zu)", *size);
3569
+ if ((size == 0) || (size > MAX_HID_REPORT_SIZE)) {
3570
+ usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
3365
3571
  return LIBUSB_ERROR_INVALID_PARAM;
3366
3572
  }
3367
3573
 
@@ -3373,7 +3579,7 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
3373
3579
  ioctl_code = IOCTL_HID_GET_FEATURE;
3374
3580
  break;
3375
3581
  default:
3376
- usbi_dbg("unknown HID report type %d", report_type);
3582
+ usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
3377
3583
  return LIBUSB_ERROR_INVALID_PARAM;
3378
3584
  }
3379
3585
 
@@ -3383,64 +3589,39 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
3383
3589
  return LIBUSB_ERROR_NO_MEM;
3384
3590
 
3385
3591
  buf[0] = (uint8_t)id; // Must be set always
3386
- usbi_dbg("report ID: 0x%02X", buf[0]);
3387
-
3388
- tp->hid_expected_size = expected_size;
3389
- read_size = expected_size;
3592
+ usbi_dbg(DEVICE_CTX(dev), "report ID: 0x%02X", buf[0]);
3390
3593
 
3391
3594
  // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3392
3595
  if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
3393
- buf, expected_size + 1, &read_size, overlapped)) {
3596
+ buf, expected_size + 1, NULL, overlapped)) {
3394
3597
  if (GetLastError() != ERROR_IO_PENDING) {
3395
- usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
3598
+ usbi_err(DEVICE_CTX(dev), "failed to read HID Report: %s", windows_error_str(0));
3396
3599
  free(buf);
3397
3600
  return LIBUSB_ERROR_IO;
3398
3601
  }
3399
- // Asynchronous wait
3400
- tp->hid_buffer = buf;
3401
- tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
3402
- return LIBUSB_SUCCESS;
3403
3602
  }
3404
3603
 
3405
- // Transfer completed synchronously => copy and discard extra buffer
3406
- if (read_size == 0) {
3407
- usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
3408
- *size = 0;
3409
- } else {
3410
- if (buf[0] != id)
3411
- usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
3412
-
3413
- if ((size_t)read_size > expected_size) {
3414
- r = LIBUSB_ERROR_OVERFLOW;
3415
- usbi_dbg("OVERFLOW!");
3416
- } else {
3417
- r = LIBUSB_COMPLETED;
3418
- }
3419
-
3420
- *size = MIN((size_t)read_size, *size);
3421
- if (id == 0)
3422
- memcpy(data, buf + 1, *size); // Discard report ID
3423
- else
3424
- memcpy(data, buf, *size);
3425
- }
3604
+ // Asynchronous wait
3605
+ tp->hid_buffer = buf;
3606
+ tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
3607
+ tp->hid_expected_size = expected_size;
3426
3608
 
3427
- free(buf);
3428
- return r;
3609
+ return LIBUSB_SUCCESS;
3429
3610
  }
3430
3611
 
3431
- static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
3432
- struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
3612
+ static int _hid_set_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
3613
+ struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
3433
3614
  {
3434
- uint8_t *buf = NULL;
3435
- DWORD ioctl_code, write_size = (DWORD)*size;
3615
+ DWORD ioctl_code, write_size = (DWORD)size;
3436
3616
  // If an id is reported, we must allow MAX_HID_REPORT_SIZE + 1
3437
3617
  size_t max_report_size = MAX_HID_REPORT_SIZE + (id ? 1 : 0);
3618
+ uint8_t *buf;
3438
3619
 
3439
3620
  if (tp->hid_buffer != NULL)
3440
- usbi_dbg("program assertion failed: hid_buffer is not NULL");
3621
+ usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
3441
3622
 
3442
- if ((*size == 0) || (*size > max_report_size)) {
3443
- usbi_dbg("invalid size (%zu)", *size);
3623
+ if ((size == 0) || (size > max_report_size)) {
3624
+ usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
3444
3625
  return LIBUSB_ERROR_INVALID_PARAM;
3445
3626
  }
3446
3627
 
@@ -3452,11 +3633,11 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
3452
3633
  ioctl_code = IOCTL_HID_SET_FEATURE;
3453
3634
  break;
3454
3635
  default:
3455
- usbi_dbg("unknown HID report type %d", report_type);
3636
+ usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
3456
3637
  return LIBUSB_ERROR_INVALID_PARAM;
3457
3638
  }
3458
3639
 
3459
- usbi_dbg("report ID: 0x%02X", id);
3640
+ usbi_dbg(DEVICE_CTX(dev), "report ID: 0x%02X", id);
3460
3641
  // When report IDs are not used (i.e. when id == 0), we must add
3461
3642
  // a null report ID. Otherwise, we just use original data buffer
3462
3643
  if (id == 0)
@@ -3468,44 +3649,39 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
3468
3649
 
3469
3650
  if (id == 0) {
3470
3651
  buf[0] = 0;
3471
- memcpy(buf + 1, data, *size);
3652
+ memcpy(buf + 1, data, size);
3472
3653
  } else {
3473
3654
  // This seems like a waste, but if we don't duplicate the
3474
3655
  // data, we'll get issues when freeing hid_buffer
3475
- memcpy(buf, data, *size);
3656
+ memcpy(buf, data, size);
3476
3657
  if (buf[0] != id)
3477
- usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
3658
+ usbi_warn(DEVICE_CTX(dev), "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
3478
3659
  }
3479
3660
 
3480
3661
  // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3481
3662
  if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
3482
- buf, write_size, &write_size, overlapped)) {
3663
+ buf, write_size, NULL, overlapped)) {
3483
3664
  if (GetLastError() != ERROR_IO_PENDING) {
3484
- usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
3665
+ usbi_err(DEVICE_CTX(dev), "failed to write HID Output Report: %s", windows_error_str(0));
3485
3666
  free(buf);
3486
3667
  return LIBUSB_ERROR_IO;
3487
3668
  }
3488
- tp->hid_buffer = buf;
3489
- tp->hid_dest = NULL;
3490
- return LIBUSB_SUCCESS;
3491
3669
  }
3492
3670
 
3493
- // Transfer completed synchronously
3494
- *size = write_size;
3495
- if (write_size == 0)
3496
- usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
3497
-
3498
- free(buf);
3499
- return LIBUSB_COMPLETED;
3671
+ tp->hid_buffer = buf;
3672
+ tp->hid_dest = NULL;
3673
+ return LIBUSB_SUCCESS;
3500
3674
  }
3501
3675
 
3502
- static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
3676
+ static int _hid_class_request(struct libusb_device *dev, HANDLE hid_handle, int request_type,
3503
3677
  int request, int value, int _index, void *data, struct winusb_transfer_priv *tp,
3504
- size_t *size, OVERLAPPED *overlapped)
3678
+ size_t size, OVERLAPPED *overlapped)
3505
3679
  {
3506
3680
  int report_type = (value >> 8) & 0xFF;
3507
3681
  int report_id = value & 0xFF;
3508
3682
 
3683
+ UNUSED(_index);
3684
+
3509
3685
  if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
3510
3686
  && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE))
3511
3687
  return LIBUSB_ERROR_INVALID_PARAM;
@@ -3519,30 +3695,28 @@ static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, in
3519
3695
  return LIBUSB_ERROR_INVALID_PARAM;
3520
3696
  }
3521
3697
 
3522
-
3523
3698
  /*
3524
3699
  * HID API functions
3525
3700
  */
3526
- static int hid_init(struct libusb_context *ctx)
3701
+ static bool hid_init(struct libusb_context *ctx)
3527
3702
  {
3528
- DLL_GET_HANDLE(hid);
3529
-
3530
- DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE);
3531
- DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE);
3532
- DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE);
3533
- DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE);
3534
- DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE);
3535
- DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE);
3536
- DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE);
3537
- DLL_LOAD_FUNC(hid, HidD_GetIndexedString, TRUE);
3538
- DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE);
3539
- DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE);
3540
- DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE);
3541
- DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE);
3542
- DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE);
3543
-
3544
- api_hid_available = true;
3545
- return LIBUSB_SUCCESS;
3703
+ DLL_GET_HANDLE(ctx, hid);
3704
+
3705
+ DLL_LOAD_FUNC(hid, HidD_GetAttributes, true);
3706
+ DLL_LOAD_FUNC(hid, HidD_GetHidGuid, true);
3707
+ DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, true);
3708
+ DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, true);
3709
+ DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, true);
3710
+ DLL_LOAD_FUNC(hid, HidD_GetProductString, true);
3711
+ DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, true);
3712
+ DLL_LOAD_FUNC(hid, HidD_GetIndexedString, true);
3713
+ DLL_LOAD_FUNC(hid, HidP_GetCaps, true);
3714
+ DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, true);
3715
+ DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, true);
3716
+ DLL_LOAD_FUNC(hid, HidD_FlushQueue, true);
3717
+ DLL_LOAD_FUNC(hid, HidP_GetValueCaps, true);
3718
+
3719
+ return true;
3546
3720
  }
3547
3721
 
3548
3722
  static void hid_exit(void)
@@ -3555,9 +3729,9 @@ static void hid_exit(void)
3555
3729
  // composite_open(), with interfaces belonging to different APIs
3556
3730
  static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3557
3731
  {
3558
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
3559
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3560
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3732
+ struct libusb_device *dev = dev_handle->dev;
3733
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev);
3734
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3561
3735
  HIDD_ATTRIBUTES hid_attributes;
3562
3736
  PHIDP_PREPARSED_DATA preparsed_data = NULL;
3563
3737
  HIDP_CAPS capabilities;
@@ -3571,18 +3745,18 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3571
3745
  const char * const type[3] = {"input", "output", "feature"};
3572
3746
  #endif
3573
3747
 
3748
+ UNUSED(sub_api);
3574
3749
  CHECK_HID_AVAILABLE;
3575
3750
 
3576
3751
  if (priv->hid == NULL) {
3577
- usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
3752
+ usbi_err(HANDLE_CTX(dev_handle), "program assertion failed - private HID structure is uninitialized");
3578
3753
  return LIBUSB_ERROR_NOT_FOUND;
3579
3754
  }
3580
3755
 
3581
3756
  for (i = 0; i < USB_MAXINTERFACES; i++) {
3582
3757
  if ((priv->usb_interface[i].path != NULL)
3583
3758
  && (priv->usb_interface[i].apib->id == USB_API_HID)) {
3584
- hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
3585
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
3759
+ hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
3586
3760
  /*
3587
3761
  * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
3588
3762
  * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
@@ -3591,11 +3765,10 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3591
3765
  * HidD_GetFeature (if the device supports Feature reports)."
3592
3766
  */
3593
3767
  if (hid_handle == INVALID_HANDLE_VALUE) {
3594
- usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
3595
- hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
3596
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
3768
+ usbi_warn(HANDLE_CTX(dev_handle), "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
3769
+ hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, 0);
3597
3770
  if (hid_handle == INVALID_HANDLE_VALUE) {
3598
- usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
3771
+ usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
3599
3772
  switch (GetLastError()) {
3600
3773
  case ERROR_FILE_NOT_FOUND: // The device was disconnected
3601
3774
  return LIBUSB_ERROR_NO_DEVICE;
@@ -3614,7 +3787,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3614
3787
  hid_attributes.Size = sizeof(hid_attributes);
3615
3788
  do {
3616
3789
  if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
3617
- usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
3790
+ usbi_err(HANDLE_CTX(dev_handle), "could not gain access to HID top collection (HidD_GetAttributes)");
3618
3791
  break;
3619
3792
  }
3620
3793
 
@@ -3623,15 +3796,15 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3623
3796
 
3624
3797
  // Set the maximum available input buffer size
3625
3798
  for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2);
3626
- usbi_dbg("set maximum input buffer size to %d", i / 2);
3799
+ usbi_dbg(HANDLE_CTX(dev_handle), "set maximum input buffer size to %d", i / 2);
3627
3800
 
3628
3801
  // Get the maximum input and output report size
3629
3802
  if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
3630
- usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
3803
+ usbi_err(HANDLE_CTX(dev_handle), "could not read HID preparsed data (HidD_GetPreparsedData)");
3631
3804
  break;
3632
3805
  }
3633
3806
  if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
3634
- usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
3807
+ usbi_err(HANDLE_CTX(dev_handle), "could not parse HID capabilities (HidP_GetCaps)");
3635
3808
  break;
3636
3809
  }
3637
3810
 
@@ -3640,7 +3813,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3640
3813
  size[1] = capabilities.NumberOutputValueCaps;
3641
3814
  size[2] = capabilities.NumberFeatureValueCaps;
3642
3815
  for (j = HidP_Input; j <= HidP_Feature; j++) {
3643
- usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]);
3816
+ usbi_dbg(HANDLE_CTX(dev_handle), "%lu HID %s report value(s) found", ULONG_CAST(size[j]), type[j]);
3644
3817
  priv->hid->uses_report_ids[j] = false;
3645
3818
  if (size[j] > 0) {
3646
3819
  value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS));
@@ -3650,7 +3823,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3650
3823
  nb_ids[0] = 0;
3651
3824
  nb_ids[1] = 0;
3652
3825
  for (i = 0; i < (int)size[j]; i++) {
3653
- usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID);
3826
+ usbi_dbg(HANDLE_CTX(dev_handle), " Report ID: 0x%02X", value_caps[i].ReportID);
3654
3827
  if (value_caps[i].ReportID != 0)
3655
3828
  nb_ids[1]++;
3656
3829
  else
@@ -3658,12 +3831,12 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3658
3831
  }
3659
3832
  if (nb_ids[1] != 0) {
3660
3833
  if (nb_ids[0] != 0)
3661
- usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
3834
+ usbi_warn(HANDLE_CTX(dev_handle), "program assertion failed - zero and nonzero report IDs used for %s",
3662
3835
  type[j]);
3663
3836
  priv->hid->uses_report_ids[j] = true;
3664
3837
  }
3665
3838
  } else {
3666
- usbi_warn(ctx, " could not process %s report IDs", type[j]);
3839
+ usbi_warn(HANDLE_CTX(dev_handle), " could not process %s report IDs", type[j]);
3667
3840
  }
3668
3841
  free(value_caps);
3669
3842
  }
@@ -3679,19 +3852,19 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3679
3852
  priv->hid->usagePage = capabilities.UsagePage;
3680
3853
 
3681
3854
  // Fetch string descriptors
3682
- priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer;
3855
+ priv->hid->string_index[0] = dev->device_descriptor.iManufacturer;
3683
3856
  if (priv->hid->string_index[0] != 0)
3684
3857
  HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0]));
3685
3858
  else
3686
3859
  priv->hid->string[0][0] = 0;
3687
3860
 
3688
- priv->hid->string_index[1] = priv->dev_descriptor.iProduct;
3861
+ priv->hid->string_index[1] = dev->device_descriptor.iProduct;
3689
3862
  if (priv->hid->string_index[1] != 0)
3690
3863
  HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1]));
3691
3864
  else
3692
3865
  priv->hid->string[1][0] = 0;
3693
3866
 
3694
- priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber;
3867
+ priv->hid->string_index[2] = dev->device_descriptor.iSerialNumber;
3695
3868
  if (priv->hid->string_index[2] != 0)
3696
3869
  HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2]));
3697
3870
  else
@@ -3706,12 +3879,14 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3706
3879
 
3707
3880
  static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
3708
3881
  {
3709
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3710
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3882
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
3883
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3711
3884
  HANDLE file_handle;
3712
3885
  int i;
3713
3886
 
3714
- if (!api_hid_available)
3887
+ UNUSED(sub_api);
3888
+
3889
+ if (DLL_HANDLE_NAME(hid) == NULL)
3715
3890
  return;
3716
3891
 
3717
3892
  for (i = 0; i < USB_MAXINTERFACES; i++) {
@@ -3723,11 +3898,12 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
3723
3898
  }
3724
3899
  }
3725
3900
 
3726
- static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
3901
+ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
3727
3902
  {
3728
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3729
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3903
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3904
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
3730
3905
 
3906
+ UNUSED(sub_api);
3731
3907
  CHECK_HID_AVAILABLE;
3732
3908
 
3733
3909
  // NB: Disconnection detection is not possible in this function
@@ -3740,17 +3916,18 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han
3740
3916
 
3741
3917
  handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
3742
3918
 
3743
- usbi_dbg("claimed interface %d", iface);
3919
+ usbi_dbg(HANDLE_CTX(dev_handle), "claimed interface %u", iface);
3744
3920
  handle_priv->active_interface = iface;
3745
3921
 
3746
3922
  return LIBUSB_SUCCESS;
3747
3923
  }
3748
3924
 
3749
- static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
3925
+ static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
3750
3926
  {
3751
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3752
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3927
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3928
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
3753
3929
 
3930
+ UNUSED(sub_api);
3754
3931
  CHECK_HID_AVAILABLE;
3755
3932
 
3756
3933
  if (priv->usb_interface[iface].path == NULL)
@@ -3764,17 +3941,15 @@ static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_h
3764
3941
  return LIBUSB_SUCCESS;
3765
3942
  }
3766
3943
 
3767
- static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
3944
+ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
3768
3945
  {
3769
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
3946
+ UNUSED(sub_api);
3947
+ UNUSED(iface);
3770
3948
 
3771
3949
  CHECK_HID_AVAILABLE;
3772
3950
 
3773
- if (altsetting > 255)
3774
- return LIBUSB_ERROR_INVALID_PARAM;
3775
-
3776
3951
  if (altsetting != 0) {
3777
- usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
3952
+ usbi_err(HANDLE_CTX(dev_handle), "set interface altsetting not supported for altsetting >0");
3778
3953
  return LIBUSB_ERROR_NOT_SUPPORTED;
3779
3954
  }
3780
3955
 
@@ -3784,17 +3959,19 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle
3784
3959
  static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
3785
3960
  {
3786
3961
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3787
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3788
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3789
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3790
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
3962
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
3963
+ struct libusb_device_handle *dev_handle = transfer->dev_handle;
3964
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
3965
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
3791
3966
  WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
3792
3967
  HANDLE hid_handle;
3793
3968
  OVERLAPPED *overlapped;
3794
- int current_interface, config;
3969
+ int current_interface;
3970
+ uint8_t config;
3795
3971
  size_t size;
3796
- int r = LIBUSB_ERROR_INVALID_PARAM;
3972
+ int r;
3797
3973
 
3974
+ UNUSED(sub_api);
3798
3975
  CHECK_HID_AVAILABLE;
3799
3976
 
3800
3977
  safe_free(transfer_priv->hid_buffer);
@@ -3804,29 +3981,31 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
3804
3981
  if (size > MAX_CTRL_BUFFER_LENGTH)
3805
3982
  return LIBUSB_ERROR_INVALID_PARAM;
3806
3983
 
3807
- current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
3984
+ current_interface = get_valid_interface(dev_handle, USB_API_HID);
3808
3985
  if (current_interface < 0) {
3809
3986
  if (auto_claim(transfer, &current_interface, USB_API_HID) != LIBUSB_SUCCESS)
3810
3987
  return LIBUSB_ERROR_NOT_FOUND;
3811
3988
  }
3812
3989
 
3813
- usbi_dbg("will use interface %d", current_interface);
3990
+ usbi_dbg(ITRANSFER_CTX(itransfer), "will use interface %d", current_interface);
3814
3991
 
3992
+ transfer_priv->interface_number = (uint8_t)current_interface;
3815
3993
  hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3816
- overlapped = transfer_priv->pollable_fd.overlapped;
3994
+ set_transfer_priv_handle(itransfer, hid_handle);
3995
+ overlapped = get_transfer_priv_overlapped(itransfer);
3817
3996
 
3818
3997
  switch (LIBUSB_REQ_TYPE(setup->RequestType)) {
3819
3998
  case LIBUSB_REQUEST_TYPE_STANDARD:
3820
3999
  switch (setup->Request) {
3821
4000
  case LIBUSB_REQUEST_GET_DESCRIPTOR:
3822
- r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
4001
+ r = _hid_get_descriptor(dev_handle->dev, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
3823
4002
  (setup->Value >> 8) & 0xFF, setup->Value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
3824
4003
  break;
3825
4004
  case LIBUSB_REQUEST_GET_CONFIGURATION:
3826
- r = winusb_get_configuration(transfer->dev_handle, &config);
4005
+ r = winusb_get_configuration(dev_handle, &config);
3827
4006
  if (r == LIBUSB_SUCCESS) {
3828
4007
  size = 1;
3829
- ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
4008
+ ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = config;
3830
4009
  r = LIBUSB_COMPLETED;
3831
4010
  }
3832
4011
  break;
@@ -3834,7 +4013,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
3834
4013
  if (setup->Value == priv->active_config) {
3835
4014
  r = LIBUSB_COMPLETED;
3836
4015
  } else {
3837
- usbi_warn(ctx, "cannot set configuration other than the default one");
4016
+ usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
3838
4017
  r = LIBUSB_ERROR_NOT_SUPPORTED;
3839
4018
  }
3840
4019
  break;
@@ -3844,22 +4023,22 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
3844
4023
  r = LIBUSB_COMPLETED;
3845
4024
  break;
3846
4025
  case LIBUSB_REQUEST_SET_INTERFACE:
3847
- r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->Index, setup->Value);
4026
+ r = hid_set_interface_altsetting(0, dev_handle, (uint8_t)setup->Index, (uint8_t)setup->Value);
3848
4027
  if (r == LIBUSB_SUCCESS)
3849
4028
  r = LIBUSB_COMPLETED;
3850
4029
  break;
3851
4030
  default:
3852
- usbi_warn(ctx, "unsupported HID control request");
4031
+ usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
3853
4032
  return LIBUSB_ERROR_NOT_SUPPORTED;
3854
4033
  }
3855
4034
  break;
3856
4035
  case LIBUSB_REQUEST_TYPE_CLASS:
3857
- r = _hid_class_request(priv->hid, hid_handle, setup->RequestType, setup->Request, setup->Value,
4036
+ r = _hid_class_request(dev_handle->dev, hid_handle, setup->RequestType, setup->Request, setup->Value,
3858
4037
  setup->Index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
3859
- &size, overlapped);
4038
+ size, overlapped);
3860
4039
  break;
3861
4040
  default:
3862
- usbi_warn(ctx, "unsupported HID control request");
4041
+ usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
3863
4042
  return LIBUSB_ERROR_NOT_SUPPORTED;
3864
4043
  }
3865
4044
 
@@ -3868,44 +4047,46 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
3868
4047
 
3869
4048
  if (r == LIBUSB_COMPLETED) {
3870
4049
  // Force request to be completed synchronously. Transferred size has been set by previous call
3871
- windows_force_sync_completion(overlapped, (ULONG)size);
4050
+ windows_force_sync_completion(itransfer, (ULONG)size);
3872
4051
  r = LIBUSB_SUCCESS;
3873
4052
  }
3874
4053
 
3875
- transfer_priv->interface_number = (uint8_t)current_interface;
3876
-
3877
4054
  return LIBUSB_SUCCESS;
3878
4055
  }
3879
4056
 
3880
4057
  static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
3881
4058
  {
3882
4059
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3883
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3884
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
3885
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3886
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4060
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
4061
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
4062
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
3887
4063
  HANDLE hid_handle;
3888
4064
  OVERLAPPED *overlapped;
3889
- bool direction_in, ret;
4065
+ bool direction_in;
4066
+ BOOL ret;
3890
4067
  int current_interface, length;
3891
- DWORD size;
3892
- int r = LIBUSB_SUCCESS;
3893
4068
 
4069
+ UNUSED(sub_api);
3894
4070
  CHECK_HID_AVAILABLE;
3895
4071
 
4072
+ if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
4073
+ return LIBUSB_ERROR_NOT_SUPPORTED;
4074
+
3896
4075
  transfer_priv->hid_dest = NULL;
3897
4076
  safe_free(transfer_priv->hid_buffer);
3898
4077
 
3899
4078
  current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
3900
4079
  if (current_interface < 0) {
3901
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
4080
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
3902
4081
  return LIBUSB_ERROR_NOT_FOUND;
3903
4082
  }
3904
4083
 
3905
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
4084
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
3906
4085
 
3907
- transfer_priv->handle = hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3908
- overlapped = transfer_priv->pollable_fd.overlapped;
4086
+ transfer_priv->interface_number = (uint8_t)current_interface;
4087
+ hid_handle = handle_priv->interface_handle[current_interface].api_handle;
4088
+ set_transfer_priv_handle(itransfer, hid_handle);
4089
+ overlapped = get_transfer_priv_overlapped(itransfer);
3909
4090
  direction_in = IS_XFERIN(transfer);
3910
4091
 
3911
4092
  // If report IDs are not in use, an extra prefix byte must be added
@@ -3924,8 +4105,8 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
3924
4105
 
3925
4106
  if (direction_in) {
3926
4107
  transfer_priv->hid_dest = transfer->buffer;
3927
- usbi_dbg("reading %d bytes (report ID: 0x00)", length);
3928
- ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, &size, overlapped);
4108
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d bytes (report ID: 0x00)", length);
4109
+ ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, NULL, overlapped);
3929
4110
  } else {
3930
4111
  if (!priv->hid->uses_report_ids[1])
3931
4112
  memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length);
@@ -3933,77 +4114,26 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
3933
4114
  // We could actually do without the calloc and memcpy in this case
3934
4115
  memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
3935
4116
 
3936
- usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
3937
- ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, &size, overlapped);
4117
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
4118
+ ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, NULL, overlapped);
3938
4119
  }
3939
4120
 
3940
- if (!ret) {
3941
- if (GetLastError() != ERROR_IO_PENDING) {
3942
- usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
3943
- safe_free(transfer_priv->hid_buffer);
3944
- return LIBUSB_ERROR_IO;
3945
- }
3946
- } else {
3947
- // Only write operations that completed synchronously need to free up
3948
- // hid_buffer. For reads, copy_transfer_data() handles that process.
3949
- if (!direction_in)
3950
- safe_free(transfer_priv->hid_buffer);
3951
-
3952
- if (size == 0) {
3953
- usbi_err(ctx, "program assertion failed - no data was transferred");
3954
- size = 1;
3955
- }
3956
- if (size > (size_t)length) {
3957
- usbi_err(ctx, "OVERFLOW!");
3958
- r = LIBUSB_ERROR_OVERFLOW;
3959
- }
3960
- windows_force_sync_completion(overlapped, (ULONG)size);
3961
- }
3962
-
3963
- transfer_priv->interface_number = (uint8_t)current_interface;
3964
-
3965
- return r;
3966
- }
3967
-
3968
- static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
3969
- {
3970
- struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
3971
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3972
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3973
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3974
- HANDLE hid_handle;
3975
- int current_interface;
3976
-
3977
- CHECK_HID_AVAILABLE;
3978
-
3979
- current_interface = transfer_priv->interface_number;
3980
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
3981
- usbi_err(ctx, "program assertion failed: invalid interface_number");
3982
- return LIBUSB_ERROR_NOT_FOUND;
3983
- }
3984
- usbi_dbg("will use interface %d", current_interface);
3985
-
3986
- hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3987
-
3988
- if (pCancelIoEx != NULL) {
3989
- // Use CancelIoEx if available to cancel just a single transfer
3990
- if (pCancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped))
3991
- return LIBUSB_SUCCESS;
3992
- } else {
3993
- if (CancelIo(hid_handle))
3994
- return LIBUSB_SUCCESS;
4121
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
4122
+ usbi_err(TRANSFER_CTX(transfer), "HID transfer failed: %s", windows_error_str(0));
4123
+ safe_free(transfer_priv->hid_buffer);
4124
+ return LIBUSB_ERROR_IO;
3995
4125
  }
3996
4126
 
3997
- usbi_warn(ctx, "cancel failed: %s", windows_error_str(0));
3998
- return LIBUSB_ERROR_NOT_FOUND;
4127
+ return LIBUSB_SUCCESS;
3999
4128
  }
4000
4129
 
4001
4130
  static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
4002
4131
  {
4003
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
4132
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
4004
4133
  HANDLE hid_handle;
4005
4134
  int current_interface;
4006
4135
 
4136
+ UNUSED(sub_api);
4007
4137
  CHECK_HID_AVAILABLE;
4008
4138
 
4009
4139
  // Flushing the queues on all interfaces is the best we can achieve
@@ -4018,27 +4148,27 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle
4018
4148
 
4019
4149
  static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
4020
4150
  {
4021
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
4022
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
4023
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4151
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
4152
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4024
4153
  HANDLE hid_handle;
4025
4154
  int current_interface;
4026
4155
 
4156
+ UNUSED(sub_api);
4027
4157
  CHECK_HID_AVAILABLE;
4028
4158
 
4029
4159
  current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
4030
4160
  if (current_interface < 0) {
4031
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
4161
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
4032
4162
  return LIBUSB_ERROR_NOT_FOUND;
4033
4163
  }
4034
4164
 
4035
- usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
4165
+ usbi_dbg(HANDLE_CTX(dev_handle), "matched endpoint %02X with interface %d", endpoint, current_interface);
4036
4166
  hid_handle = handle_priv->interface_handle[current_interface].api_handle;
4037
4167
 
4038
4168
  // No endpoint selection with Microsoft's implementation, so we try to flush the
4039
4169
  // whole interface. Should be OK for most case scenarios
4040
4170
  if (!HidD_FlushQueue(hid_handle)) {
4041
- usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
4171
+ usbi_err(HANDLE_CTX(dev_handle), "Flushing of HID queue failed: %s", windows_error_str(0));
4042
4172
  // Device was probably disconnected
4043
4173
  return LIBUSB_ERROR_NO_DEVICE;
4044
4174
  }
@@ -4047,31 +4177,29 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle,
4047
4177
  }
4048
4178
 
4049
4179
  // This extra function is only needed for HID
4050
- static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
4180
+ static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
4051
4181
  {
4052
4182
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4053
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4054
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4055
- int r = LIBUSB_TRANSFER_COMPLETED;
4056
- uint32_t corrected_size = io_size;
4183
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
4184
+ enum libusb_transfer_status r = LIBUSB_TRANSFER_COMPLETED;
4185
+
4186
+ UNUSED(sub_api);
4057
4187
 
4058
4188
  if (transfer_priv->hid_buffer != NULL) {
4059
4189
  // If we have a valid hid_buffer, it means the transfer was async
4060
4190
  if (transfer_priv->hid_dest != NULL) { // Data readout
4061
- if (corrected_size > 0) {
4191
+ if (length > 0) {
4062
4192
  // First, check for overflow
4063
- if (corrected_size > transfer_priv->hid_expected_size) {
4064
- usbi_err(ctx, "OVERFLOW!");
4065
- corrected_size = (uint32_t)transfer_priv->hid_expected_size;
4193
+ if ((size_t)length > transfer_priv->hid_expected_size) {
4194
+ usbi_err(TRANSFER_CTX(transfer), "OVERFLOW!");
4195
+ length = (DWORD)transfer_priv->hid_expected_size;
4066
4196
  r = LIBUSB_TRANSFER_OVERFLOW;
4067
4197
  }
4068
4198
 
4069
4199
  if (transfer_priv->hid_buffer[0] == 0) {
4070
- // Discard the 1 byte report ID prefix
4071
- corrected_size--;
4072
- memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
4200
+ memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length);
4073
4201
  } else {
4074
- memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
4202
+ memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length);
4075
4203
  }
4076
4204
  }
4077
4205
  transfer_priv->hid_dest = NULL;
@@ -4080,7 +4208,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer,
4080
4208
  safe_free(transfer_priv->hid_buffer);
4081
4209
  }
4082
4210
 
4083
- itransfer->transferred += corrected_size;
4211
+ itransfer->transferred += (int)length;
4084
4212
  return r;
4085
4213
  }
4086
4214
 
@@ -4090,11 +4218,15 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer,
4090
4218
  */
4091
4219
  static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
4092
4220
  {
4093
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4094
- int r = LIBUSB_ERROR_NOT_FOUND;
4095
- uint8_t i;
4221
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4222
+ int i, r = LIBUSB_ERROR_NOT_FOUND;
4096
4223
  // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
4097
- bool available[SUB_API_MAX + 1] = { 0 };
4224
+ bool available[SUB_API_MAX + 1];
4225
+
4226
+ UNUSED(sub_api);
4227
+
4228
+ for (i = 0; i < SUB_API_MAX + 1; i++)
4229
+ available[i] = false;
4098
4230
 
4099
4231
  for (i = 0; i < USB_MAXINTERFACES; i++) {
4100
4232
  switch (priv->usb_interface[i].apib->id) {
@@ -4125,7 +4257,7 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
4125
4257
  // open HID devices with a U2F usage unless running as administrator. We ignore this
4126
4258
  // failure and proceed without the HID device opened.
4127
4259
  if (r == LIBUSB_ERROR_ACCESS) {
4128
- usbi_dbg("ignoring access denied error while opening HID interface of composite device");
4260
+ usbi_dbg(HANDLE_CTX(dev_handle), "ignoring access denied error while opening HID interface of composite device");
4129
4261
  r = LIBUSB_SUCCESS;
4130
4262
  }
4131
4263
  }
@@ -4135,10 +4267,15 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
4135
4267
 
4136
4268
  static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
4137
4269
  {
4138
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4139
- uint8_t i;
4270
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4271
+ int i;
4140
4272
  // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
4141
- bool available[SUB_API_MAX + 1] = { 0 };
4273
+ bool available[SUB_API_MAX + 1];
4274
+
4275
+ UNUSED(sub_api);
4276
+
4277
+ for (i = 0; i < SUB_API_MAX + 1; i++)
4278
+ available[i] = false;
4142
4279
 
4143
4280
  for (i = 0; i < USB_MAXINTERFACES; i++) {
4144
4281
  switch (priv->usb_interface[i].apib->id) {
@@ -4163,30 +4300,33 @@ static void composite_close(int sub_api, struct libusb_device_handle *dev_handle
4163
4300
  hid_close(SUB_API_NOTSET, dev_handle);
4164
4301
  }
4165
4302
 
4166
- static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
4303
+ static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
4167
4304
  {
4168
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4305
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4169
4306
 
4307
+ UNUSED(sub_api);
4170
4308
  CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface);
4171
4309
 
4172
4310
  return priv->usb_interface[iface].apib->
4173
4311
  claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
4174
4312
  }
4175
4313
 
4176
- static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
4314
+ static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
4177
4315
  {
4178
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4316
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4179
4317
 
4318
+ UNUSED(sub_api);
4180
4319
  CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting);
4181
4320
 
4182
4321
  return priv->usb_interface[iface].apib->
4183
4322
  set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
4184
4323
  }
4185
4324
 
4186
- static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
4325
+ static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
4187
4326
  {
4188
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4327
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4189
4328
 
4329
+ UNUSED(sub_api);
4190
4330
  CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface);
4191
4331
 
4192
4332
  return priv->usb_interface[iface].apib->
@@ -4196,12 +4336,13 @@ static int composite_release_interface(int sub_api, struct libusb_device_handle
4196
4336
  static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
4197
4337
  {
4198
4338
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4199
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4200
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4339
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
4201
4340
  struct libusb_config_descriptor *conf_desc;
4202
4341
  WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
4203
4342
  int iface, pass, r;
4204
4343
 
4344
+ UNUSED(sub_api);
4345
+
4205
4346
  // Interface shouldn't matter for control, but it does in practice, with Windows'
4206
4347
  // restrictions with regards to accessing HID keyboards and mice. Try to target
4207
4348
  // a specific interface first, if possible.
@@ -4216,7 +4357,8 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
4216
4357
  libusb_free_config_descriptor(conf_desc);
4217
4358
  break;
4218
4359
  }
4219
- // Fall through if not able to determine interface
4360
+ // No break if not able to determine interface
4361
+ // Fall through
4220
4362
  default:
4221
4363
  iface = -1;
4222
4364
  break;
@@ -4224,7 +4366,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
4224
4366
 
4225
4367
  // Try and target a specific interface if the control setup indicates such
4226
4368
  if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
4227
- usbi_dbg("attempting control transfer targeted to interface %d", iface);
4369
+ usbi_dbg(TRANSFER_CTX(transfer), "attempting control transfer targeted to interface %d", iface);
4228
4370
  if ((priv->usb_interface[iface].path != NULL)
4229
4371
  && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
4230
4372
  r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
@@ -4240,10 +4382,10 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
4240
4382
  if ((priv->usb_interface[iface].path != NULL)
4241
4383
  && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
4242
4384
  if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
4243
- usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
4385
+ usbi_dbg(TRANSFER_CTX(transfer), "trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
4244
4386
  continue;
4245
4387
  }
4246
- usbi_dbg("using interface %d", iface);
4388
+ usbi_dbg(TRANSFER_CTX(transfer), "using interface %d", iface);
4247
4389
  r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
4248
4390
  // If not supported on this API, it may be supported on another, so don't give up yet!!
4249
4391
  if (r == LIBUSB_ERROR_NOT_SUPPORTED)
@@ -4253,20 +4395,22 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
4253
4395
  }
4254
4396
  }
4255
4397
 
4256
- usbi_err(ctx, "no libusb supported interfaces to complete request");
4398
+ usbi_err(TRANSFER_CTX(transfer), "no libusb supported interfaces to complete request");
4257
4399
  return LIBUSB_ERROR_NOT_FOUND;
4258
4400
  }
4259
4401
 
4260
- static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
4402
+ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
4403
+ {
4261
4404
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4262
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4263
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
4264
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4405
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
4406
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
4265
4407
  int current_interface;
4266
4408
 
4409
+ UNUSED(sub_api);
4410
+
4267
4411
  current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
4268
4412
  if (current_interface < 0) {
4269
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
4413
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
4270
4414
  return LIBUSB_ERROR_NOT_FOUND;
4271
4415
  }
4272
4416
 
@@ -4276,16 +4420,18 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr
4276
4420
  submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
4277
4421
  }
4278
4422
 
4279
- static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
4423
+ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
4424
+ {
4280
4425
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4281
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4282
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
4283
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4426
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
4427
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
4284
4428
  int current_interface;
4285
4429
 
4430
+ UNUSED(sub_api);
4431
+
4286
4432
  current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
4287
4433
  if (current_interface < 0) {
4288
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
4434
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
4289
4435
  return LIBUSB_ERROR_NOT_FOUND;
4290
4436
  }
4291
4437
 
@@ -4297,14 +4443,15 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra
4297
4443
 
4298
4444
  static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
4299
4445
  {
4300
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
4301
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
4302
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4446
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
4447
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4303
4448
  int current_interface;
4304
4449
 
4450
+ UNUSED(sub_api);
4451
+
4305
4452
  current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
4306
4453
  if (current_interface < 0) {
4307
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
4454
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
4308
4455
  return LIBUSB_ERROR_NOT_FOUND;
4309
4456
  }
4310
4457
 
@@ -4314,49 +4461,34 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha
4314
4461
  clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
4315
4462
  }
4316
4463
 
4317
- static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
4464
+ static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
4318
4465
  {
4319
4466
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4320
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4321
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4467
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
4468
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
4322
4469
  int current_interface = transfer_priv->interface_number;
4323
4470
 
4324
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
4325
- usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
4326
- return LIBUSB_ERROR_NOT_FOUND;
4327
- }
4328
-
4329
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control);
4330
-
4331
- return priv->usb_interface[current_interface].apib->
4332
- abort_control(priv->usb_interface[current_interface].sub_api, itransfer);
4333
- }
4334
-
4335
- static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
4336
- {
4337
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4338
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4339
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4340
- int current_interface = transfer_priv->interface_number;
4471
+ UNUSED(sub_api);
4341
4472
 
4342
4473
  if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
4343
- usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
4474
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - invalid interface_number");
4344
4475
  return LIBUSB_ERROR_NOT_FOUND;
4345
4476
  }
4346
4477
 
4347
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers);
4478
+ CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, cancel_transfer);
4348
4479
 
4349
4480
  return priv->usb_interface[current_interface].apib->
4350
- abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer);
4481
+ cancel_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
4351
4482
  }
4352
4483
 
4353
4484
  static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
4354
4485
  {
4355
- struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4356
- int r;
4357
- uint8_t i;
4486
+ struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
4487
+ int i, r;
4358
4488
  bool available[SUB_API_MAX];
4359
4489
 
4490
+ UNUSED(sub_api);
4491
+
4360
4492
  for (i = 0; i < SUB_API_MAX; i++)
4361
4493
  available[i] = false;
4362
4494
 
@@ -4377,15 +4509,19 @@ static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_
4377
4509
  return LIBUSB_SUCCESS;
4378
4510
  }
4379
4511
 
4380
- static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
4512
+ static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
4381
4513
  {
4382
4514
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4383
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4384
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4515
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
4516
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
4385
4517
  int current_interface = transfer_priv->interface_number;
4386
4518
 
4387
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data);
4519
+ UNUSED(sub_api);
4520
+ if (priv->usb_interface[current_interface].apib->copy_transfer_data == NULL) {
4521
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
4522
+ return LIBUSB_TRANSFER_ERROR;
4523
+ }
4388
4524
 
4389
4525
  return priv->usb_interface[current_interface].apib->
4390
- copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size);
4526
+ copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, length);
4391
4527
  }