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