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