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