libusb 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -2
- data/Gemfile +2 -0
- data/History.md +12 -0
- data/README.md +25 -14
- data/Rakefile +64 -109
- data/appveyor.yml +23 -0
- data/ext/extconf.rb +10 -12
- data/ext/libusb_recipe.rb +29 -0
- data/lib/libusb/call.rb +14 -11
- data/lib/libusb/compat.rb +9 -9
- data/lib/libusb/context.rb +16 -1
- data/lib/libusb/dependencies.rb +7 -0
- data/lib/libusb/dev_handle.rb +13 -3
- data/lib/libusb/eventmachine.rb +4 -4
- data/lib/libusb/transfer.rb +71 -10
- data/lib/libusb/version_gem.rb +1 -1
- data/libusb.gemspec +7 -5
- data/ports/archives/libusb-1.0.21.tar.bz2 +0 -0
- data/test/test_libusb_bulk_stream_transfer.rb +1 -1
- data/test/test_libusb_descriptors.rb +4 -4
- data/test/test_libusb_event_machine.rb +7 -7
- data/test/test_libusb_hotplug.rb +15 -3
- data/test/test_libusb_iso_transfer.rb +1 -1
- data/test/test_libusb_mass_storage.rb +19 -19
- data/test/test_libusb_mass_storage2.rb +1 -1
- data/test/test_libusb_structs.rb +13 -0
- data/test/test_libusb_threads.rb +2 -2
- data/wireshark-usb-sniffer.png +0 -0
- metadata +32 -156
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ext/libusb-1.0.20/AUTHORS +0 -89
- data/ext/libusb-1.0.20/COPYING +0 -504
- data/ext/libusb-1.0.20/ChangeLog +0 -227
- data/ext/libusb-1.0.20/INSTALL +0 -234
- data/ext/libusb-1.0.20/Makefile.am +0 -28
- data/ext/libusb-1.0.20/Makefile.in +0 -897
- data/ext/libusb-1.0.20/NEWS +0 -2
- data/ext/libusb-1.0.20/PORTING +0 -94
- data/ext/libusb-1.0.20/README +0 -29
- data/ext/libusb-1.0.20/TODO +0 -2
- data/ext/libusb-1.0.20/Xcode/common.xcconfig +0 -49
- data/ext/libusb-1.0.20/Xcode/config.h +0 -28
- data/ext/libusb-1.0.20/Xcode/debug.xcconfig +0 -29
- data/ext/libusb-1.0.20/Xcode/libusb.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +0 -865
- data/ext/libusb-1.0.20/Xcode/libusb_debug.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/libusb_release.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/release.xcconfig +0 -30
- data/ext/libusb-1.0.20/aclocal.m4 +0 -1193
- data/ext/libusb-1.0.20/android/README +0 -114
- data/ext/libusb-1.0.20/android/config.h +0 -81
- data/ext/libusb-1.0.20/android/jni/Android.mk +0 -23
- data/ext/libusb-1.0.20/android/jni/Application.mk +0 -24
- data/ext/libusb-1.0.20/android/jni/examples.mk +0 -134
- data/ext/libusb-1.0.20/android/jni/libusb.mk +0 -54
- data/ext/libusb-1.0.20/android/jni/tests.mk +0 -56
- data/ext/libusb-1.0.20/compile +0 -347
- data/ext/libusb-1.0.20/config.guess +0 -1421
- data/ext/libusb-1.0.20/config.h.in +0 -155
- data/ext/libusb-1.0.20/config.sub +0 -1807
- data/ext/libusb-1.0.20/configure +0 -15466
- data/ext/libusb-1.0.20/configure.ac +0 -326
- data/ext/libusb-1.0.20/depcomp +0 -791
- data/ext/libusb-1.0.20/doc/Makefile.am +0 -9
- data/ext/libusb-1.0.20/doc/Makefile.in +0 -456
- data/ext/libusb-1.0.20/doc/doxygen.cfg.in +0 -2334
- data/ext/libusb-1.0.20/examples/Makefile.am +0 -19
- data/ext/libusb-1.0.20/examples/Makefile.in +0 -713
- data/ext/libusb-1.0.20/examples/dpfp.c +0 -506
- data/ext/libusb-1.0.20/examples/dpfp_threaded.c +0 -549
- data/ext/libusb-1.0.20/examples/ezusb.c +0 -831
- data/ext/libusb-1.0.20/examples/ezusb.h +0 -120
- data/ext/libusb-1.0.20/examples/fxload.c +0 -308
- data/ext/libusb-1.0.20/examples/getopt/getopt.c +0 -1060
- data/ext/libusb-1.0.20/examples/getopt/getopt.h +0 -180
- data/ext/libusb-1.0.20/examples/getopt/getopt1.c +0 -188
- data/ext/libusb-1.0.20/examples/hotplugtest.c +0 -122
- data/ext/libusb-1.0.20/examples/listdevs.c +0 -71
- data/ext/libusb-1.0.20/examples/sam3u_benchmark.c +0 -193
- data/ext/libusb-1.0.20/examples/xusb.c +0 -1130
- data/ext/libusb-1.0.20/install-sh +0 -501
- data/ext/libusb-1.0.20/libusb-1.0.pc.in +0 -11
- data/ext/libusb-1.0.20/libusb/Makefile.am +0 -90
- data/ext/libusb-1.0.20/libusb/Makefile.in +0 -1053
- data/ext/libusb-1.0.20/libusb/core.c +0 -2452
- data/ext/libusb-1.0.20/libusb/descriptor.c +0 -1201
- data/ext/libusb-1.0.20/libusb/hotplug.c +0 -344
- data/ext/libusb-1.0.20/libusb/hotplug.h +0 -90
- data/ext/libusb-1.0.20/libusb/io.c +0 -2760
- data/ext/libusb-1.0.20/libusb/libusb-1.0.def +0 -168
- data/ext/libusb-1.0.20/libusb/libusb-1.0.rc +0 -61
- data/ext/libusb-1.0.20/libusb/libusb.h +0 -1999
- data/ext/libusb-1.0.20/libusb/libusbi.h +0 -1102
- data/ext/libusb-1.0.20/libusb/os/darwin_usb.c +0 -1969
- data/ext/libusb-1.0.20/libusb/os/darwin_usb.h +0 -158
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +0 -5
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +0 -810
- data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +0 -1193
- data/ext/libusb-1.0.20/libusb/os/haiku/compile +0 -347
- data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +0 -1421
- data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +0 -1807
- data/ext/libusb-1.0.20/libusb/os/haiku/configure +0 -17579
- data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +0 -8
- data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +0 -791
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +0 -378
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +0 -112
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +0 -550
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +0 -255
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +0 -180
- data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +0 -501
- data/ext/libusb-1.0.20/libusb/os/haiku/ltmain.sh +0 -9655
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/libtool.m4 +0 -7992
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltoptions.m4 +0 -384
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltsugar.m4 +0 -123
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltversion.m4 +0 -23
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/lt~obsolete.m4 +0 -98
- data/ext/libusb-1.0.20/libusb/os/haiku/missing +0 -215
- data/ext/libusb-1.0.20/libusb/os/linux_netlink.c +0 -369
- data/ext/libusb-1.0.20/libusb/os/linux_udev.c +0 -306
- data/ext/libusb-1.0.20/libusb/os/linux_usbfs.c +0 -2692
- data/ext/libusb-1.0.20/libusb/os/linux_usbfs.h +0 -192
- data/ext/libusb-1.0.20/libusb/os/netbsd_usb.c +0 -674
- data/ext/libusb-1.0.20/libusb/os/openbsd_usb.c +0 -768
- data/ext/libusb-1.0.20/libusb/os/poll_posix.c +0 -53
- data/ext/libusb-1.0.20/libusb/os/poll_posix.h +0 -11
- data/ext/libusb-1.0.20/libusb/os/poll_windows.c +0 -728
- data/ext/libusb-1.0.20/libusb/os/poll_windows.h +0 -131
- data/ext/libusb-1.0.20/libusb/os/threads_posix.c +0 -82
- data/ext/libusb-1.0.20/libusb/os/threads_posix.h +0 -50
- data/ext/libusb-1.0.20/libusb/os/threads_windows.c +0 -214
- data/ext/libusb-1.0.20/libusb/os/threads_windows.h +0 -87
- data/ext/libusb-1.0.20/libusb/os/wince_usb.c +0 -869
- data/ext/libusb-1.0.20/libusb/os/wince_usb.h +0 -131
- data/ext/libusb-1.0.20/libusb/os/windows_common.h +0 -108
- data/ext/libusb-1.0.20/libusb/os/windows_usb.c +0 -4643
- data/ext/libusb-1.0.20/libusb/os/windows_usb.h +0 -973
- data/ext/libusb-1.0.20/libusb/strerror.c +0 -202
- data/ext/libusb-1.0.20/libusb/sync.c +0 -308
- data/ext/libusb-1.0.20/libusb/version.h +0 -18
- data/ext/libusb-1.0.20/libusb/version_nano.h +0 -1
- data/ext/libusb-1.0.20/ltmain.sh +0 -9655
- data/ext/libusb-1.0.20/m4/libtool.m4 +0 -7992
- data/ext/libusb-1.0.20/m4/ltoptions.m4 +0 -384
- data/ext/libusb-1.0.20/m4/ltsugar.m4 +0 -123
- data/ext/libusb-1.0.20/m4/ltversion.m4 +0 -23
- data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +0 -98
- data/ext/libusb-1.0.20/missing +0 -215
- data/ext/libusb-1.0.20/tests/Makefile.am +0 -6
- data/ext/libusb-1.0.20/tests/Makefile.in +0 -596
- data/ext/libusb-1.0.20/tests/libusb_testlib.h +0 -107
- data/ext/libusb-1.0.20/tests/stress.c +0 -160
- data/ext/libusb-1.0.20/tests/testlib.c +0 -277
- metadata.gz.sig +0 -0
@@ -1,131 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Windows CE backend for libusb 1.0
|
3
|
-
* Copyright © 2011-2013 RealVNC Ltd.
|
4
|
-
* Portions taken from Windows backend, which is
|
5
|
-
* Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
|
6
|
-
* With contributions from Michael Plante, Orin Eman et al.
|
7
|
-
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
|
8
|
-
* Major code testing contribution by Xiaofan Chen
|
9
|
-
*
|
10
|
-
* This library is free software; you can redistribute it and/or
|
11
|
-
* modify it under the terms of the GNU Lesser General Public
|
12
|
-
* License as published by the Free Software Foundation; either
|
13
|
-
* version 2.1 of the License, or (at your option) any later version.
|
14
|
-
*
|
15
|
-
* This library is distributed in the hope that it will be useful,
|
16
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
18
|
-
* Lesser General Public License for more details.
|
19
|
-
*
|
20
|
-
* You should have received a copy of the GNU Lesser General Public
|
21
|
-
* License along with this library; if not, write to the Free Software
|
22
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
23
|
-
*/
|
24
|
-
#pragma once
|
25
|
-
|
26
|
-
#include "windows_common.h"
|
27
|
-
|
28
|
-
#include <windows.h>
|
29
|
-
#include "poll_windows.h"
|
30
|
-
|
31
|
-
#define MAX_DEVICE_COUNT 256
|
32
|
-
|
33
|
-
// This is a modified dump of the types in the ceusbkwrapper.h library header
|
34
|
-
// with functions transformed into extern pointers.
|
35
|
-
//
|
36
|
-
// This backend dynamically loads ceusbkwrapper.dll and doesn't include
|
37
|
-
// ceusbkwrapper.h directly to simplify the build process. The kernel
|
38
|
-
// side wrapper driver is built using the platform image build tools,
|
39
|
-
// which makes it difficult to reference directly from the libusb build
|
40
|
-
// system.
|
41
|
-
struct UKW_DEVICE_PRIV;
|
42
|
-
typedef struct UKW_DEVICE_PRIV *UKW_DEVICE;
|
43
|
-
typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE;
|
44
|
-
|
45
|
-
typedef struct {
|
46
|
-
UINT8 bLength;
|
47
|
-
UINT8 bDescriptorType;
|
48
|
-
UINT16 bcdUSB;
|
49
|
-
UINT8 bDeviceClass;
|
50
|
-
UINT8 bDeviceSubClass;
|
51
|
-
UINT8 bDeviceProtocol;
|
52
|
-
UINT8 bMaxPacketSize0;
|
53
|
-
UINT16 idVendor;
|
54
|
-
UINT16 idProduct;
|
55
|
-
UINT16 bcdDevice;
|
56
|
-
UINT8 iManufacturer;
|
57
|
-
UINT8 iProduct;
|
58
|
-
UINT8 iSerialNumber;
|
59
|
-
UINT8 bNumConfigurations;
|
60
|
-
} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR;
|
61
|
-
|
62
|
-
typedef struct {
|
63
|
-
UINT8 bmRequestType;
|
64
|
-
UINT8 bRequest;
|
65
|
-
UINT16 wValue;
|
66
|
-
UINT16 wIndex;
|
67
|
-
UINT16 wLength;
|
68
|
-
} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER;
|
69
|
-
|
70
|
-
// Collection of flags which can be used when issuing transfer requests
|
71
|
-
/* Indicates that the transfer direction is 'in' */
|
72
|
-
#define UKW_TF_IN_TRANSFER 0x00000001
|
73
|
-
/* Indicates that the transfer direction is 'out' */
|
74
|
-
#define UKW_TF_OUT_TRANSFER 0x00000000
|
75
|
-
/* Specifies that the transfer should complete as soon as possible,
|
76
|
-
* even if no OVERLAPPED structure has been provided. */
|
77
|
-
#define UKW_TF_NO_WAIT 0x00000100
|
78
|
-
/* Indicates that transfers shorter than the buffer are ok */
|
79
|
-
#define UKW_TF_SHORT_TRANSFER_OK 0x00000200
|
80
|
-
#define UKW_TF_SEND_TO_DEVICE 0x00010000
|
81
|
-
#define UKW_TF_SEND_TO_INTERFACE 0x00020000
|
82
|
-
#define UKW_TF_SEND_TO_ENDPOINT 0x00040000
|
83
|
-
/* Don't block when waiting for memory allocations */
|
84
|
-
#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000
|
85
|
-
|
86
|
-
/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor,
|
87
|
-
* to specify the currently active configuration for the device. */
|
88
|
-
#define UKW_ACTIVE_CONFIGURATION -1
|
89
|
-
|
90
|
-
DLL_DECLARE(WINAPI, HANDLE, UkwOpenDriver, ());
|
91
|
-
DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD));
|
92
|
-
DLL_DECLARE(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD));
|
93
|
-
DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*));
|
94
|
-
DLL_DECLARE(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR));
|
95
|
-
DLL_DECLARE(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD));
|
96
|
-
DLL_DECLARE(WINAPI, void, UkwCloseDriver, (HANDLE));
|
97
|
-
DLL_DECLARE(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD));
|
98
|
-
DLL_DECLARE(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
|
99
|
-
DLL_DECLARE(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD));
|
100
|
-
DLL_DECLARE(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD));
|
101
|
-
DLL_DECLARE(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD));
|
102
|
-
DLL_DECLARE(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR));
|
103
|
-
DLL_DECLARE(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR));
|
104
|
-
DLL_DECLARE(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR));
|
105
|
-
DLL_DECLARE(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR));
|
106
|
-
DLL_DECLARE(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE));
|
107
|
-
DLL_DECLARE(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL));
|
108
|
-
DLL_DECLARE(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD));
|
109
|
-
DLL_DECLARE(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD));
|
110
|
-
DLL_DECLARE(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED));
|
111
|
-
DLL_DECLARE(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL));
|
112
|
-
|
113
|
-
// Used to determine if an endpoint status really is halted on a failed transfer.
|
114
|
-
#define STATUS_HALT_FLAG 0x1
|
115
|
-
|
116
|
-
struct wince_device_priv {
|
117
|
-
UKW_DEVICE dev;
|
118
|
-
UKW_DEVICE_DESCRIPTOR desc;
|
119
|
-
};
|
120
|
-
|
121
|
-
struct wince_device_handle_priv {
|
122
|
-
// This member isn't used, but only exists to avoid an empty structure
|
123
|
-
// for private data for the device handle.
|
124
|
-
int reserved;
|
125
|
-
};
|
126
|
-
|
127
|
-
struct wince_transfer_priv {
|
128
|
-
struct winfd pollable_fd;
|
129
|
-
uint8_t interface_number;
|
130
|
-
};
|
131
|
-
|
@@ -1,108 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Windows backend common header for libusb 1.0
|
3
|
-
*
|
4
|
-
* This file brings together header code common between
|
5
|
-
* the desktop Windows and Windows CE backends.
|
6
|
-
* Copyright © 2012-2013 RealVNC Ltd.
|
7
|
-
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
|
8
|
-
* With contributions from Michael Plante, Orin Eman et al.
|
9
|
-
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
|
10
|
-
* Major code testing contribution by Xiaofan Chen
|
11
|
-
*
|
12
|
-
* This library is free software; you can redistribute it and/or
|
13
|
-
* modify it under the terms of the GNU Lesser General Public
|
14
|
-
* License as published by the Free Software Foundation; either
|
15
|
-
* version 2.1 of the License, or (at your option) any later version.
|
16
|
-
*
|
17
|
-
* This library is distributed in the hope that it will be useful,
|
18
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
20
|
-
* Lesser General Public License for more details.
|
21
|
-
*
|
22
|
-
* You should have received a copy of the GNU Lesser General Public
|
23
|
-
* License along with this library; if not, write to the Free Software
|
24
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
-
*/
|
26
|
-
|
27
|
-
#pragma once
|
28
|
-
|
29
|
-
// Windows API default is uppercase - ugh!
|
30
|
-
#if !defined(bool)
|
31
|
-
#define bool BOOL
|
32
|
-
#endif
|
33
|
-
#if !defined(true)
|
34
|
-
#define true TRUE
|
35
|
-
#endif
|
36
|
-
#if !defined(false)
|
37
|
-
#define false FALSE
|
38
|
-
#endif
|
39
|
-
|
40
|
-
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
|
41
|
-
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
|
42
|
-
#define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
|
43
|
-
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
|
44
|
-
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
|
45
|
-
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
|
46
|
-
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
|
47
|
-
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
|
48
|
-
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
|
49
|
-
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
|
50
|
-
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
|
51
|
-
#define safe_strlen(str) ((str==NULL)?0:strlen(str))
|
52
|
-
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
|
53
|
-
#define safe_stprintf _sntprintf
|
54
|
-
#define safe_tcslen(str) ((str==NULL)?0:_tcslen(str))
|
55
|
-
#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
|
56
|
-
#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
|
57
|
-
#ifndef ARRAYSIZE
|
58
|
-
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
59
|
-
#endif
|
60
|
-
|
61
|
-
#define ERR_BUFFER_SIZE 256
|
62
|
-
#define TIMER_REQUEST_RETRY_MS 100
|
63
|
-
#define MAX_TIMER_SEMAPHORES 128
|
64
|
-
|
65
|
-
|
66
|
-
/*
|
67
|
-
* API macros - from libusb-win32 1.x
|
68
|
-
*/
|
69
|
-
#define DLL_DECLARE_PREFIXNAME(api, ret, prefixname, name, args) \
|
70
|
-
typedef ret (api * __dll_##name##_t)args; \
|
71
|
-
static __dll_##name##_t prefixname = NULL
|
72
|
-
|
73
|
-
#ifndef _WIN32_WCE
|
74
|
-
#define DLL_STRINGIFY(dll) #dll
|
75
|
-
#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandleA(DLL_STRINGIFY(dll))
|
76
|
-
#define DLL_LOAD_LIBRARY(dll) LoadLibraryA(DLL_STRINGIFY(dll))
|
77
|
-
#else
|
78
|
-
#define DLL_STRINGIFY(dll) L#dll
|
79
|
-
#define DLL_GET_MODULE_HANDLE(dll) GetModuleHandle(DLL_STRINGIFY(dll))
|
80
|
-
#define DLL_LOAD_LIBRARY(dll) LoadLibrary(DLL_STRINGIFY(dll))
|
81
|
-
#endif
|
82
|
-
|
83
|
-
#define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
|
84
|
-
do { \
|
85
|
-
HMODULE h = DLL_GET_MODULE_HANDLE(dll); \
|
86
|
-
if (!h) \
|
87
|
-
h = DLL_LOAD_LIBRARY(dll); \
|
88
|
-
if (!h) { \
|
89
|
-
if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; } \
|
90
|
-
else { break; } \
|
91
|
-
} \
|
92
|
-
prefixname = (__dll_##name##_t)GetProcAddress(h, \
|
93
|
-
DLL_STRINGIFY(name)); \
|
94
|
-
if (prefixname) break; \
|
95
|
-
prefixname = (__dll_##name##_t)GetProcAddress(h, \
|
96
|
-
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
|
97
|
-
if (prefixname) break; \
|
98
|
-
prefixname = (__dll_##name##_t)GetProcAddress(h, \
|
99
|
-
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
|
100
|
-
if (prefixname) break; \
|
101
|
-
if(ret_on_failure) \
|
102
|
-
return LIBUSB_ERROR_NOT_FOUND; \
|
103
|
-
} while(0)
|
104
|
-
|
105
|
-
#define DLL_DECLARE(api, ret, name, args) DLL_DECLARE_PREFIXNAME(api, ret, name, name, args)
|
106
|
-
#define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure)
|
107
|
-
#define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args) DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args)
|
108
|
-
#define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure)
|
@@ -1,4643 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* windows backend for libusb 1.0
|
3
|
-
* Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
|
4
|
-
* With contributions from Michael Plante, Orin Eman et al.
|
5
|
-
* Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
|
6
|
-
* HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
|
7
|
-
* Hash table functions adapted from glibc, by Ulrich Drepper et al.
|
8
|
-
* Major code testing contribution by Xiaofan Chen
|
9
|
-
*
|
10
|
-
* This library is free software; you can redistribute it and/or
|
11
|
-
* modify it under the terms of the GNU Lesser General Public
|
12
|
-
* License as published by the Free Software Foundation; either
|
13
|
-
* version 2.1 of the License, or (at your option) any later version.
|
14
|
-
*
|
15
|
-
* This library is distributed in the hope that it will be useful,
|
16
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
18
|
-
* Lesser General Public License for more details.
|
19
|
-
*
|
20
|
-
* You should have received a copy of the GNU Lesser General Public
|
21
|
-
* License along with this library; if not, write to the Free Software
|
22
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
23
|
-
*/
|
24
|
-
|
25
|
-
#include <config.h>
|
26
|
-
|
27
|
-
#include <windows.h>
|
28
|
-
#include <setupapi.h>
|
29
|
-
#include <ctype.h>
|
30
|
-
#include <errno.h>
|
31
|
-
#include <fcntl.h>
|
32
|
-
#include <process.h>
|
33
|
-
#include <stdio.h>
|
34
|
-
#include <inttypes.h>
|
35
|
-
#include <objbase.h>
|
36
|
-
#include <winioctl.h>
|
37
|
-
|
38
|
-
#include "libusbi.h"
|
39
|
-
#include "poll_windows.h"
|
40
|
-
#include "windows_usb.h"
|
41
|
-
|
42
|
-
// The 2 macros below are used in conjunction with safe loops.
|
43
|
-
#define LOOP_CHECK(fcall) { r=fcall; if (r != LIBUSB_SUCCESS) continue; }
|
44
|
-
#define LOOP_BREAK(err) { r=err; continue; }
|
45
|
-
|
46
|
-
// Helper prototypes
|
47
|
-
static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian);
|
48
|
-
static int windows_clock_gettime(int clk_id, struct timespec *tp);
|
49
|
-
unsigned __stdcall windows_clock_gettime_threaded(void* param);
|
50
|
-
// Common calls
|
51
|
-
static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
52
|
-
|
53
|
-
// WinUSB-like API prototypes
|
54
|
-
static int winusbx_init(int sub_api, struct libusb_context *ctx);
|
55
|
-
static int winusbx_exit(int sub_api);
|
56
|
-
static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
|
57
|
-
static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
|
58
|
-
static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
59
|
-
static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
60
|
-
static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
61
|
-
static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
|
62
|
-
static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
|
63
|
-
static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
|
64
|
-
static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
|
65
|
-
static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
|
66
|
-
static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
|
67
|
-
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
|
68
|
-
static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
|
69
|
-
// HID API prototypes
|
70
|
-
static int hid_init(int sub_api, struct libusb_context *ctx);
|
71
|
-
static int hid_exit(int sub_api);
|
72
|
-
static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
|
73
|
-
static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
|
74
|
-
static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
75
|
-
static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
76
|
-
static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
|
77
|
-
static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
|
78
|
-
static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
|
79
|
-
static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
|
80
|
-
static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
|
81
|
-
static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
|
82
|
-
static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
|
83
|
-
// Composite API prototypes
|
84
|
-
static int composite_init(int sub_api, struct libusb_context *ctx);
|
85
|
-
static int composite_exit(int sub_api);
|
86
|
-
static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
|
87
|
-
static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
|
88
|
-
static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
89
|
-
static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
|
90
|
-
static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
|
91
|
-
static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
|
92
|
-
static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
|
93
|
-
static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
|
94
|
-
static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
|
95
|
-
static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
|
96
|
-
static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
|
97
|
-
static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
|
98
|
-
static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
|
99
|
-
|
100
|
-
|
101
|
-
// Global variables
|
102
|
-
uint64_t hires_frequency, hires_ticks_to_ps;
|
103
|
-
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
|
104
|
-
int windows_version = WINDOWS_UNDEFINED;
|
105
|
-
static char windows_version_str[128] = "Windows Undefined";
|
106
|
-
// Concurrency
|
107
|
-
static int concurrent_usage = -1;
|
108
|
-
usbi_mutex_t autoclaim_lock;
|
109
|
-
// Timer thread
|
110
|
-
HANDLE timer_thread = NULL;
|
111
|
-
DWORD timer_thread_id = 0;
|
112
|
-
// API globals
|
113
|
-
#define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \
|
114
|
-
if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0)
|
115
|
-
static struct winusb_interface WinUSBX[SUB_API_MAX];
|
116
|
-
const char* sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES;
|
117
|
-
bool api_hid_available = false;
|
118
|
-
#define CHECK_HID_AVAILABLE do { if (!api_hid_available) return LIBUSB_ERROR_ACCESS; } while (0)
|
119
|
-
|
120
|
-
static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) {
|
121
|
-
if ((guid1 != NULL) && (guid2 != NULL)) {
|
122
|
-
return (memcmp(guid1, guid2, sizeof(GUID)) == 0);
|
123
|
-
}
|
124
|
-
return false;
|
125
|
-
}
|
126
|
-
|
127
|
-
#if defined(ENABLE_LOGGING)
|
128
|
-
static char* guid_to_string(const GUID* guid)
|
129
|
-
{
|
130
|
-
static char guid_string[MAX_GUID_STRING_LENGTH];
|
131
|
-
|
132
|
-
if (guid == NULL) return NULL;
|
133
|
-
sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
134
|
-
(unsigned int)guid->Data1, guid->Data2, guid->Data3,
|
135
|
-
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
136
|
-
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
137
|
-
return guid_string;
|
138
|
-
}
|
139
|
-
#endif
|
140
|
-
|
141
|
-
/*
|
142
|
-
* Converts a windows error to human readable string
|
143
|
-
* uses retval as errorcode, or, if 0, use GetLastError()
|
144
|
-
*/
|
145
|
-
#if defined(ENABLE_LOGGING)
|
146
|
-
static char *windows_error_str(uint32_t retval)
|
147
|
-
{
|
148
|
-
static char err_string[ERR_BUFFER_SIZE];
|
149
|
-
|
150
|
-
DWORD size;
|
151
|
-
ssize_t i;
|
152
|
-
uint32_t error_code, format_error;
|
153
|
-
|
154
|
-
error_code = retval?retval:GetLastError();
|
155
|
-
|
156
|
-
safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code);
|
157
|
-
|
158
|
-
// Translate codes returned by SetupAPI. The ones we are dealing with are either
|
159
|
-
// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
|
160
|
-
// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
|
161
|
-
switch (error_code & 0xE0000000) {
|
162
|
-
case 0:
|
163
|
-
error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
|
164
|
-
break;
|
165
|
-
case 0xE0000000:
|
166
|
-
error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
|
167
|
-
break;
|
168
|
-
default:
|
169
|
-
break;
|
170
|
-
}
|
171
|
-
|
172
|
-
size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
|
173
|
-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)],
|
174
|
-
ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL);
|
175
|
-
if (size == 0) {
|
176
|
-
format_error = GetLastError();
|
177
|
-
if (format_error)
|
178
|
-
safe_sprintf(err_string, ERR_BUFFER_SIZE,
|
179
|
-
"Windows error code %u (FormatMessage error code %u)", error_code, format_error);
|
180
|
-
else
|
181
|
-
safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code);
|
182
|
-
} else {
|
183
|
-
// Remove CR/LF terminators
|
184
|
-
for (i=safe_strlen(err_string)-1; (i>=0) && ((err_string[i]==0x0A) || (err_string[i]==0x0D)); i--) {
|
185
|
-
err_string[i] = 0;
|
186
|
-
}
|
187
|
-
}
|
188
|
-
return err_string;
|
189
|
-
}
|
190
|
-
#endif
|
191
|
-
|
192
|
-
/*
|
193
|
-
* Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
|
194
|
-
* Return an allocated sanitized string or NULL on error.
|
195
|
-
*/
|
196
|
-
static char* sanitize_path(const char* path)
|
197
|
-
{
|
198
|
-
const char root_prefix[] = "\\\\.\\";
|
199
|
-
size_t j, size, root_size;
|
200
|
-
char* ret_path = NULL;
|
201
|
-
size_t add_root = 0;
|
202
|
-
|
203
|
-
if (path == NULL)
|
204
|
-
return NULL;
|
205
|
-
|
206
|
-
size = safe_strlen(path)+1;
|
207
|
-
root_size = sizeof(root_prefix)-1;
|
208
|
-
|
209
|
-
// Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
|
210
|
-
if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) ||
|
211
|
-
((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
|
212
|
-
add_root = root_size;
|
213
|
-
size += add_root;
|
214
|
-
}
|
215
|
-
|
216
|
-
if ((ret_path = (char*) calloc(size, 1)) == NULL)
|
217
|
-
return NULL;
|
218
|
-
|
219
|
-
safe_strcpy(&ret_path[add_root], size-add_root, path);
|
220
|
-
|
221
|
-
// Ensure consistency with root prefix
|
222
|
-
for (j=0; j<root_size; j++)
|
223
|
-
ret_path[j] = root_prefix[j];
|
224
|
-
|
225
|
-
// Same goes for '\' and '#' after the root prefix. Ensure '#' is used
|
226
|
-
for(j=root_size; j<size; j++) {
|
227
|
-
ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too
|
228
|
-
if (ret_path[j] == '\\')
|
229
|
-
ret_path[j] = '#';
|
230
|
-
}
|
231
|
-
|
232
|
-
return ret_path;
|
233
|
-
}
|
234
|
-
|
235
|
-
/*
|
236
|
-
* Cfgmgr32, OLE32 and SetupAPI DLL functions
|
237
|
-
*/
|
238
|
-
static int init_dlls(void)
|
239
|
-
{
|
240
|
-
DLL_LOAD(Cfgmgr32.dll, CM_Get_Parent, TRUE);
|
241
|
-
DLL_LOAD(Cfgmgr32.dll, CM_Get_Child, TRUE);
|
242
|
-
DLL_LOAD(Cfgmgr32.dll, CM_Get_Sibling, TRUE);
|
243
|
-
DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_IDA, TRUE);
|
244
|
-
// Prefixed to avoid conflict with header files
|
245
|
-
DLL_LOAD_PREFIXED(OLE32.dll, p, CLSIDFromString, TRUE);
|
246
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetClassDevsA, TRUE);
|
247
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInfo, TRUE);
|
248
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInterfaces, TRUE);
|
249
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
|
250
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiDestroyDeviceInfoList, TRUE);
|
251
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDevRegKey, TRUE);
|
252
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
|
253
|
-
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
|
254
|
-
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE);
|
255
|
-
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE);
|
256
|
-
DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE);
|
257
|
-
DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE);
|
258
|
-
DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE);
|
259
|
-
return LIBUSB_SUCCESS;
|
260
|
-
}
|
261
|
-
|
262
|
-
/*
|
263
|
-
* enumerate interfaces for the whole USB class
|
264
|
-
*
|
265
|
-
* Parameters:
|
266
|
-
* dev_info: a pointer to a dev_info list
|
267
|
-
* dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
|
268
|
-
* usb_class: the generic USB class for which to retrieve interface details
|
269
|
-
* index: zero based index of the interface in the device info list
|
270
|
-
*
|
271
|
-
* Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
|
272
|
-
* structure returned and call this function repeatedly using the same guid (with an
|
273
|
-
* incremented index starting at zero) until all interfaces have been returned.
|
274
|
-
*/
|
275
|
-
static bool get_devinfo_data(struct libusb_context *ctx,
|
276
|
-
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char* usb_class, unsigned _index)
|
277
|
-
{
|
278
|
-
if (_index <= 0) {
|
279
|
-
*dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
|
280
|
-
if (*dev_info == INVALID_HANDLE_VALUE) {
|
281
|
-
return false;
|
282
|
-
}
|
283
|
-
}
|
284
|
-
|
285
|
-
dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
|
286
|
-
if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
|
287
|
-
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
|
288
|
-
usbi_err(ctx, "Could not obtain device info data for index %u: %s",
|
289
|
-
_index, windows_error_str(0));
|
290
|
-
}
|
291
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
292
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
293
|
-
return false;
|
294
|
-
}
|
295
|
-
return true;
|
296
|
-
}
|
297
|
-
|
298
|
-
/*
|
299
|
-
* enumerate interfaces for a specific GUID
|
300
|
-
*
|
301
|
-
* Parameters:
|
302
|
-
* dev_info: a pointer to a dev_info list
|
303
|
-
* dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
|
304
|
-
* guid: the GUID for which to retrieve interface details
|
305
|
-
* index: zero based index of the interface in the device info list
|
306
|
-
*
|
307
|
-
* Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
|
308
|
-
* structure returned and call this function repeatedly using the same guid (with an
|
309
|
-
* incremented index starting at zero) until all interfaces have been returned.
|
310
|
-
*/
|
311
|
-
static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx,
|
312
|
-
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID* guid, unsigned _index)
|
313
|
-
{
|
314
|
-
SP_DEVICE_INTERFACE_DATA dev_interface_data;
|
315
|
-
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
316
|
-
DWORD size;
|
317
|
-
|
318
|
-
if (_index <= 0) {
|
319
|
-
*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
320
|
-
}
|
321
|
-
|
322
|
-
if (dev_info_data != NULL) {
|
323
|
-
dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
|
324
|
-
if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
|
325
|
-
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
|
326
|
-
usbi_err(ctx, "Could not obtain device info data for index %u: %s",
|
327
|
-
_index, windows_error_str(0));
|
328
|
-
}
|
329
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
330
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
331
|
-
return NULL;
|
332
|
-
}
|
333
|
-
}
|
334
|
-
|
335
|
-
dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
336
|
-
if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
|
337
|
-
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
|
338
|
-
usbi_err(ctx, "Could not obtain interface data for index %u: %s",
|
339
|
-
_index, windows_error_str(0));
|
340
|
-
}
|
341
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
342
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
343
|
-
return NULL;
|
344
|
-
}
|
345
|
-
|
346
|
-
// Read interface data (dummy + actual) to access the device path
|
347
|
-
if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
|
348
|
-
// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
|
349
|
-
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
350
|
-
usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
|
351
|
-
_index, windows_error_str(0));
|
352
|
-
goto err_exit;
|
353
|
-
}
|
354
|
-
} else {
|
355
|
-
usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
|
356
|
-
goto err_exit;
|
357
|
-
}
|
358
|
-
|
359
|
-
if ((dev_interface_details = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) calloc(size, 1)) == NULL) {
|
360
|
-
usbi_err(ctx, "could not allocate interface data for index %u.", _index);
|
361
|
-
goto err_exit;
|
362
|
-
}
|
363
|
-
|
364
|
-
dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
365
|
-
if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data,
|
366
|
-
dev_interface_details, size, &size, NULL)) {
|
367
|
-
usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
|
368
|
-
_index, windows_error_str(0));
|
369
|
-
}
|
370
|
-
|
371
|
-
return dev_interface_details;
|
372
|
-
|
373
|
-
err_exit:
|
374
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
375
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
376
|
-
return NULL;
|
377
|
-
}
|
378
|
-
|
379
|
-
/* For libusb0 filter */
|
380
|
-
static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
|
381
|
-
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID* guid, unsigned _index, char* filter_path){
|
382
|
-
SP_DEVICE_INTERFACE_DATA dev_interface_data;
|
383
|
-
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
384
|
-
DWORD size;
|
385
|
-
if (_index <= 0) {
|
386
|
-
*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
387
|
-
}
|
388
|
-
if (dev_info_data != NULL) {
|
389
|
-
dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
|
390
|
-
if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
|
391
|
-
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
|
392
|
-
usbi_err(ctx, "Could not obtain device info data for index %u: %s",
|
393
|
-
_index, windows_error_str(0));
|
394
|
-
}
|
395
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
396
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
397
|
-
return NULL;
|
398
|
-
}
|
399
|
-
}
|
400
|
-
dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
401
|
-
if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
|
402
|
-
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
|
403
|
-
usbi_err(ctx, "Could not obtain interface data for index %u: %s",
|
404
|
-
_index, windows_error_str(0));
|
405
|
-
}
|
406
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
407
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
408
|
-
return NULL;
|
409
|
-
}
|
410
|
-
// Read interface data (dummy + actual) to access the device path
|
411
|
-
if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
|
412
|
-
// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
|
413
|
-
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
414
|
-
usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
|
415
|
-
_index, windows_error_str(0));
|
416
|
-
goto err_exit;
|
417
|
-
}
|
418
|
-
} else {
|
419
|
-
usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
|
420
|
-
goto err_exit;
|
421
|
-
}
|
422
|
-
if ((dev_interface_details = malloc(size)) == NULL) {
|
423
|
-
usbi_err(ctx, "could not allocate interface data for index %u.", _index);
|
424
|
-
goto err_exit;
|
425
|
-
}
|
426
|
-
dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
427
|
-
if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data,
|
428
|
-
dev_interface_details, size, &size, NULL)) {
|
429
|
-
usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
|
430
|
-
_index, windows_error_str(0));
|
431
|
-
}
|
432
|
-
// [trobinso] lookup the libusb0 symbolic index.
|
433
|
-
if (dev_interface_details) {
|
434
|
-
HKEY hkey_device_interface=pSetupDiOpenDeviceInterfaceRegKey(*dev_info,&dev_interface_data,0,KEY_READ);
|
435
|
-
if (hkey_device_interface != INVALID_HANDLE_VALUE) {
|
436
|
-
DWORD libusb0_symboliclink_index=0;
|
437
|
-
DWORD value_length=sizeof(DWORD);
|
438
|
-
DWORD value_type=0;
|
439
|
-
LONG status;
|
440
|
-
status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type,
|
441
|
-
(LPBYTE) &libusb0_symboliclink_index, &value_length);
|
442
|
-
if (status == ERROR_SUCCESS) {
|
443
|
-
if (libusb0_symboliclink_index < 256) {
|
444
|
-
// libusb0.sys is connected to this device instance.
|
445
|
-
// If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
|
446
|
-
safe_sprintf(filter_path, sizeof("\\\\.\\libusb0-0000"), "\\\\.\\libusb0-%04d", libusb0_symboliclink_index);
|
447
|
-
usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
|
448
|
-
} else {
|
449
|
-
// libusb0.sys was connected to this device instance at one time; but not anymore.
|
450
|
-
}
|
451
|
-
}
|
452
|
-
pRegCloseKey(hkey_device_interface);
|
453
|
-
}
|
454
|
-
}
|
455
|
-
return dev_interface_details;
|
456
|
-
err_exit:
|
457
|
-
pSetupDiDestroyDeviceInfoList(*dev_info);
|
458
|
-
*dev_info = INVALID_HANDLE_VALUE;
|
459
|
-
return NULL;}
|
460
|
-
|
461
|
-
/* Hash table functions - modified From glibc 2.3.2:
|
462
|
-
[Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
463
|
-
[Knuth] The Art of Computer Programming, part 3 (6.4) */
|
464
|
-
typedef struct htab_entry {
|
465
|
-
unsigned long used;
|
466
|
-
char* str;
|
467
|
-
} htab_entry;
|
468
|
-
htab_entry* htab_table = NULL;
|
469
|
-
usbi_mutex_t htab_write_mutex = NULL;
|
470
|
-
unsigned long htab_size, htab_filled;
|
471
|
-
|
472
|
-
/* For the used double hash method the table size has to be a prime. To
|
473
|
-
correct the user given table size we need a prime test. This trivial
|
474
|
-
algorithm is adequate because the code is called only during init and
|
475
|
-
the number is likely to be small */
|
476
|
-
static int isprime(unsigned long number)
|
477
|
-
{
|
478
|
-
// no even number will be passed
|
479
|
-
unsigned int divider = 3;
|
480
|
-
|
481
|
-
while((divider * divider < number) && (number % divider != 0))
|
482
|
-
divider += 2;
|
483
|
-
|
484
|
-
return (number % divider != 0);
|
485
|
-
}
|
486
|
-
|
487
|
-
/* Before using the hash table we must allocate memory for it.
|
488
|
-
We allocate one element more as the found prime number says.
|
489
|
-
This is done for more effective indexing as explained in the
|
490
|
-
comment for the hash function. */
|
491
|
-
static int htab_create(struct libusb_context *ctx, unsigned long nel)
|
492
|
-
{
|
493
|
-
if (htab_table != NULL) {
|
494
|
-
usbi_err(ctx, "hash table already allocated");
|
495
|
-
}
|
496
|
-
|
497
|
-
// Create a mutex
|
498
|
-
usbi_mutex_init(&htab_write_mutex, NULL);
|
499
|
-
|
500
|
-
// Change nel to the first prime number not smaller as nel.
|
501
|
-
nel |= 1;
|
502
|
-
while(!isprime(nel))
|
503
|
-
nel += 2;
|
504
|
-
|
505
|
-
htab_size = nel;
|
506
|
-
usbi_dbg("using %d entries hash table", nel);
|
507
|
-
htab_filled = 0;
|
508
|
-
|
509
|
-
// allocate memory and zero out.
|
510
|
-
htab_table = (htab_entry*) calloc(htab_size + 1, sizeof(htab_entry));
|
511
|
-
if (htab_table == NULL) {
|
512
|
-
usbi_err(ctx, "could not allocate space for hash table");
|
513
|
-
return 0;
|
514
|
-
}
|
515
|
-
|
516
|
-
return 1;
|
517
|
-
}
|
518
|
-
|
519
|
-
/* After using the hash table it has to be destroyed. */
|
520
|
-
static void htab_destroy(void)
|
521
|
-
{
|
522
|
-
size_t i;
|
523
|
-
if (htab_table == NULL) {
|
524
|
-
return;
|
525
|
-
}
|
526
|
-
|
527
|
-
for (i=0; i<htab_size; i++) {
|
528
|
-
if (htab_table[i].used) {
|
529
|
-
safe_free(htab_table[i].str);
|
530
|
-
}
|
531
|
-
}
|
532
|
-
usbi_mutex_destroy(&htab_write_mutex);
|
533
|
-
safe_free(htab_table);
|
534
|
-
}
|
535
|
-
|
536
|
-
/* This is the search function. It uses double hashing with open addressing.
|
537
|
-
We use an trick to speed up the lookup. The table is created with one
|
538
|
-
more element available. This enables us to use the index zero special.
|
539
|
-
This index will never be used because we store the first hash index in
|
540
|
-
the field used where zero means not used. Every other value means used.
|
541
|
-
The used field can be used as a first fast comparison for equality of
|
542
|
-
the stored and the parameter value. This helps to prevent unnecessary
|
543
|
-
expensive calls of strcmp. */
|
544
|
-
static unsigned long htab_hash(char* str)
|
545
|
-
{
|
546
|
-
unsigned long hval, hval2;
|
547
|
-
unsigned long idx;
|
548
|
-
unsigned long r = 5381;
|
549
|
-
int c;
|
550
|
-
char* sz = str;
|
551
|
-
|
552
|
-
if (str == NULL)
|
553
|
-
return 0;
|
554
|
-
|
555
|
-
// Compute main hash value (algorithm suggested by Nokia)
|
556
|
-
while ((c = *sz++) != 0)
|
557
|
-
r = ((r << 5) + r) + c;
|
558
|
-
if (r == 0)
|
559
|
-
++r;
|
560
|
-
|
561
|
-
// compute table hash: simply take the modulus
|
562
|
-
hval = r % htab_size;
|
563
|
-
if (hval == 0)
|
564
|
-
++hval;
|
565
|
-
|
566
|
-
// Try the first index
|
567
|
-
idx = hval;
|
568
|
-
|
569
|
-
if (htab_table[idx].used) {
|
570
|
-
if ( (htab_table[idx].used == hval)
|
571
|
-
&& (safe_strcmp(str, htab_table[idx].str) == 0) ) {
|
572
|
-
// existing hash
|
573
|
-
return idx;
|
574
|
-
}
|
575
|
-
usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
|
576
|
-
|
577
|
-
// Second hash function, as suggested in [Knuth]
|
578
|
-
hval2 = 1 + hval % (htab_size - 2);
|
579
|
-
|
580
|
-
do {
|
581
|
-
// Because size is prime this guarantees to step through all available indexes
|
582
|
-
if (idx <= hval2) {
|
583
|
-
idx = htab_size + idx - hval2;
|
584
|
-
} else {
|
585
|
-
idx -= hval2;
|
586
|
-
}
|
587
|
-
|
588
|
-
// If we visited all entries leave the loop unsuccessfully
|
589
|
-
if (idx == hval) {
|
590
|
-
break;
|
591
|
-
}
|
592
|
-
|
593
|
-
// If entry is found use it.
|
594
|
-
if ( (htab_table[idx].used == hval)
|
595
|
-
&& (safe_strcmp(str, htab_table[idx].str) == 0) ) {
|
596
|
-
return idx;
|
597
|
-
}
|
598
|
-
}
|
599
|
-
while (htab_table[idx].used);
|
600
|
-
}
|
601
|
-
|
602
|
-
// Not found => New entry
|
603
|
-
|
604
|
-
// If the table is full return an error
|
605
|
-
if (htab_filled >= htab_size) {
|
606
|
-
usbi_err(NULL, "hash table is full (%d entries)", htab_size);
|
607
|
-
return 0;
|
608
|
-
}
|
609
|
-
|
610
|
-
// Concurrent threads might be storing the same entry at the same time
|
611
|
-
// (eg. "simultaneous" enums from different threads) => use a mutex
|
612
|
-
usbi_mutex_lock(&htab_write_mutex);
|
613
|
-
// Just free any previously allocated string (which should be the same as
|
614
|
-
// new one). The possibility of concurrent threads storing a collision
|
615
|
-
// string (same hash, different string) at the same time is extremely low
|
616
|
-
safe_free(htab_table[idx].str);
|
617
|
-
htab_table[idx].used = hval;
|
618
|
-
htab_table[idx].str = (char*) malloc(safe_strlen(str)+1);
|
619
|
-
if (htab_table[idx].str == NULL) {
|
620
|
-
usbi_err(NULL, "could not duplicate string for hash table");
|
621
|
-
usbi_mutex_unlock(&htab_write_mutex);
|
622
|
-
return 0;
|
623
|
-
}
|
624
|
-
memcpy(htab_table[idx].str, str, safe_strlen(str)+1);
|
625
|
-
++htab_filled;
|
626
|
-
usbi_mutex_unlock(&htab_write_mutex);
|
627
|
-
|
628
|
-
return idx;
|
629
|
-
}
|
630
|
-
|
631
|
-
/*
|
632
|
-
* Returns the session ID of a device's nth level ancestor
|
633
|
-
* If there's no device at the nth level, return 0
|
634
|
-
*/
|
635
|
-
static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
|
636
|
-
{
|
637
|
-
DWORD parent_devinst;
|
638
|
-
unsigned long session_id = 0;
|
639
|
-
char* sanitized_path = NULL;
|
640
|
-
char path[MAX_PATH_LENGTH];
|
641
|
-
unsigned i;
|
642
|
-
|
643
|
-
if (level < 1) return 0;
|
644
|
-
for (i = 0; i<level; i++) {
|
645
|
-
if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) {
|
646
|
-
return 0;
|
647
|
-
}
|
648
|
-
devinst = parent_devinst;
|
649
|
-
}
|
650
|
-
if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) {
|
651
|
-
return 0;
|
652
|
-
}
|
653
|
-
// TODO: (post hotplug): try without sanitizing
|
654
|
-
sanitized_path = sanitize_path(path);
|
655
|
-
if (sanitized_path == NULL) {
|
656
|
-
return 0;
|
657
|
-
}
|
658
|
-
session_id = htab_hash(sanitized_path);
|
659
|
-
safe_free(sanitized_path);
|
660
|
-
return session_id;
|
661
|
-
}
|
662
|
-
|
663
|
-
/*
|
664
|
-
* Determine which interface the given endpoint address belongs to
|
665
|
-
*/
|
666
|
-
static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
|
667
|
-
{
|
668
|
-
const struct libusb_interface *intf;
|
669
|
-
const struct libusb_interface_descriptor *intf_desc;
|
670
|
-
int i, j, k;
|
671
|
-
|
672
|
-
for (i = 0; i < conf_desc->bNumInterfaces; i++) {
|
673
|
-
intf = &conf_desc->interface[i];
|
674
|
-
for (j = 0; j < intf->num_altsetting; j++) {
|
675
|
-
intf_desc = &intf->altsetting[j];
|
676
|
-
for (k = 0; k < intf_desc->bNumEndpoints; k++) {
|
677
|
-
if (intf_desc->endpoint[k].bEndpointAddress == ep) {
|
678
|
-
usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber);
|
679
|
-
return intf_desc->bInterfaceNumber;
|
680
|
-
}
|
681
|
-
}
|
682
|
-
}
|
683
|
-
}
|
684
|
-
|
685
|
-
usbi_dbg("endpoint %02X not found on any interface", ep);
|
686
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
687
|
-
}
|
688
|
-
|
689
|
-
/*
|
690
|
-
* Populate the endpoints addresses of the device_priv interface helper structs
|
691
|
-
*/
|
692
|
-
static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
693
|
-
{
|
694
|
-
int i, r;
|
695
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
696
|
-
struct libusb_config_descriptor *conf_desc;
|
697
|
-
const struct libusb_interface_descriptor *if_desc;
|
698
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
699
|
-
|
700
|
-
r = libusb_get_config_descriptor(dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
|
701
|
-
if (r != LIBUSB_SUCCESS) {
|
702
|
-
usbi_warn(ctx, "could not read config descriptor: error %d", r);
|
703
|
-
return r;
|
704
|
-
}
|
705
|
-
|
706
|
-
if_desc = &conf_desc->interface[iface].altsetting[altsetting];
|
707
|
-
safe_free(priv->usb_interface[iface].endpoint);
|
708
|
-
|
709
|
-
if (if_desc->bNumEndpoints == 0) {
|
710
|
-
usbi_dbg("no endpoints found for interface %d", iface);
|
711
|
-
return LIBUSB_SUCCESS;
|
712
|
-
}
|
713
|
-
|
714
|
-
priv->usb_interface[iface].endpoint = (uint8_t*) malloc(if_desc->bNumEndpoints);
|
715
|
-
if (priv->usb_interface[iface].endpoint == NULL) {
|
716
|
-
return LIBUSB_ERROR_NO_MEM;
|
717
|
-
}
|
718
|
-
|
719
|
-
priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
|
720
|
-
for (i=0; i<if_desc->bNumEndpoints; i++) {
|
721
|
-
priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
|
722
|
-
usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface);
|
723
|
-
}
|
724
|
-
libusb_free_config_descriptor(conf_desc);
|
725
|
-
|
726
|
-
// Extra init may be required to configure endpoints
|
727
|
-
return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface);
|
728
|
-
}
|
729
|
-
|
730
|
-
// Lookup for a match in the list of API driver names
|
731
|
-
// return -1 if not found, driver match number otherwise
|
732
|
-
static int get_sub_api(char* driver, int api){
|
733
|
-
int i;
|
734
|
-
const char sep_str[2] = {LIST_SEPARATOR, 0};
|
735
|
-
char *tok, *tmp_str;
|
736
|
-
size_t len = safe_strlen(driver);
|
737
|
-
|
738
|
-
if (len == 0) return SUB_API_NOTSET;
|
739
|
-
tmp_str = (char*) calloc(len+1, 1);
|
740
|
-
if (tmp_str == NULL) return SUB_API_NOTSET;
|
741
|
-
memcpy(tmp_str, driver, len+1);
|
742
|
-
tok = strtok(tmp_str, sep_str);
|
743
|
-
while (tok != NULL) {
|
744
|
-
for (i=0; i<usb_api_backend[api].nb_driver_names; i++) {
|
745
|
-
if (safe_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
|
746
|
-
free(tmp_str);
|
747
|
-
return i;
|
748
|
-
}
|
749
|
-
}
|
750
|
-
tok = strtok(NULL, sep_str);
|
751
|
-
}
|
752
|
-
free (tmp_str);
|
753
|
-
return SUB_API_NOTSET;
|
754
|
-
}
|
755
|
-
|
756
|
-
/*
|
757
|
-
* auto-claiming and auto-release helper functions
|
758
|
-
*/
|
759
|
-
static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
|
760
|
-
{
|
761
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
762
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(
|
763
|
-
transfer->dev_handle);
|
764
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
765
|
-
int current_interface = *interface_number;
|
766
|
-
int r = LIBUSB_SUCCESS;
|
767
|
-
|
768
|
-
switch(api_type) {
|
769
|
-
case USB_API_WINUSBX:
|
770
|
-
case USB_API_HID:
|
771
|
-
break;
|
772
|
-
default:
|
773
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
774
|
-
}
|
775
|
-
|
776
|
-
usbi_mutex_lock(&autoclaim_lock);
|
777
|
-
if (current_interface < 0) // No serviceable interface was found
|
778
|
-
{
|
779
|
-
for (current_interface=0; current_interface<USB_MAXINTERFACES; current_interface++) {
|
780
|
-
// Must claim an interface of the same API type
|
781
|
-
if ( (priv->usb_interface[current_interface].apib->id == api_type)
|
782
|
-
&& (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS) ) {
|
783
|
-
usbi_dbg("auto-claimed interface %d for control request", current_interface);
|
784
|
-
if (handle_priv->autoclaim_count[current_interface] != 0) {
|
785
|
-
usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
|
786
|
-
}
|
787
|
-
handle_priv->autoclaim_count[current_interface]++;
|
788
|
-
break;
|
789
|
-
}
|
790
|
-
}
|
791
|
-
if (current_interface == USB_MAXINTERFACES) {
|
792
|
-
usbi_err(ctx, "could not auto-claim any interface");
|
793
|
-
r = LIBUSB_ERROR_NOT_FOUND;
|
794
|
-
}
|
795
|
-
} else {
|
796
|
-
// If we have a valid interface that was autoclaimed, we must increment
|
797
|
-
// its autoclaim count so that we can prevent an early release.
|
798
|
-
if (handle_priv->autoclaim_count[current_interface] != 0) {
|
799
|
-
handle_priv->autoclaim_count[current_interface]++;
|
800
|
-
}
|
801
|
-
}
|
802
|
-
usbi_mutex_unlock(&autoclaim_lock);
|
803
|
-
|
804
|
-
*interface_number = current_interface;
|
805
|
-
return r;
|
806
|
-
|
807
|
-
}
|
808
|
-
|
809
|
-
static void auto_release(struct usbi_transfer *itransfer)
|
810
|
-
{
|
811
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
812
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
813
|
-
libusb_device_handle *dev_handle = transfer->dev_handle;
|
814
|
-
struct windows_device_handle_priv* handle_priv = _device_handle_priv(dev_handle);
|
815
|
-
int r;
|
816
|
-
|
817
|
-
usbi_mutex_lock(&autoclaim_lock);
|
818
|
-
if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) {
|
819
|
-
handle_priv->autoclaim_count[transfer_priv->interface_number]--;
|
820
|
-
if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
|
821
|
-
r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
|
822
|
-
if (r == LIBUSB_SUCCESS) {
|
823
|
-
usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
|
824
|
-
} else {
|
825
|
-
usbi_dbg("failed to auto-release interface %d (%s)",
|
826
|
-
transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
|
827
|
-
}
|
828
|
-
}
|
829
|
-
}
|
830
|
-
usbi_mutex_unlock(&autoclaim_lock);
|
831
|
-
}
|
832
|
-
|
833
|
-
/* Windows version dtection */
|
834
|
-
static BOOL is_x64(void)
|
835
|
-
{
|
836
|
-
BOOL ret = FALSE;
|
837
|
-
// Detect if we're running a 32 or 64 bit system
|
838
|
-
if (sizeof(uintptr_t) < 8) {
|
839
|
-
DLL_LOAD_PREFIXED(Kernel32.dll, p, IsWow64Process, FALSE);
|
840
|
-
if (pIsWow64Process != NULL) {
|
841
|
-
(*pIsWow64Process)(GetCurrentProcess(), &ret);
|
842
|
-
}
|
843
|
-
} else {
|
844
|
-
ret = TRUE;
|
845
|
-
}
|
846
|
-
return ret;
|
847
|
-
}
|
848
|
-
|
849
|
-
static void get_windows_version(void)
|
850
|
-
{
|
851
|
-
OSVERSIONINFOEXA vi, vi2;
|
852
|
-
const char* w = 0;
|
853
|
-
const char* w64 = "32 bit";
|
854
|
-
char* vptr;
|
855
|
-
size_t vlen;
|
856
|
-
unsigned major, minor;
|
857
|
-
ULONGLONG major_equal, minor_equal;
|
858
|
-
BOOL ws;
|
859
|
-
|
860
|
-
memset(&vi, 0, sizeof(vi));
|
861
|
-
vi.dwOSVersionInfoSize = sizeof(vi);
|
862
|
-
if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
|
863
|
-
memset(&vi, 0, sizeof(vi));
|
864
|
-
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
865
|
-
if (!GetVersionExA((OSVERSIONINFOA *)&vi))
|
866
|
-
return;
|
867
|
-
}
|
868
|
-
|
869
|
-
if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
870
|
-
|
871
|
-
if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
|
872
|
-
// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
|
873
|
-
// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
|
874
|
-
|
875
|
-
major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
|
876
|
-
for (major = vi.dwMajorVersion; major <= 9; major++) {
|
877
|
-
memset(&vi2, 0, sizeof(vi2));
|
878
|
-
vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;
|
879
|
-
if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
|
880
|
-
continue;
|
881
|
-
if (vi.dwMajorVersion < major) {
|
882
|
-
vi.dwMajorVersion = major; vi.dwMinorVersion = 0;
|
883
|
-
}
|
884
|
-
|
885
|
-
minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
|
886
|
-
for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
|
887
|
-
memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);
|
888
|
-
vi2.dwMinorVersion = minor;
|
889
|
-
if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
|
890
|
-
continue;
|
891
|
-
vi.dwMinorVersion = minor;
|
892
|
-
break;
|
893
|
-
}
|
894
|
-
|
895
|
-
break;
|
896
|
-
}
|
897
|
-
}
|
898
|
-
|
899
|
-
if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
|
900
|
-
ws = (vi.wProductType <= VER_NT_WORKSTATION);
|
901
|
-
windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
|
902
|
-
switch (windows_version) {
|
903
|
-
case 0x50: w = "2000";
|
904
|
-
break;
|
905
|
-
case 0x51: w = "XP";
|
906
|
-
break;
|
907
|
-
case 0x52: w = ("2003");
|
908
|
-
break;
|
909
|
-
case 0x60: w = (ws?"Vista":"2008");
|
910
|
-
break;
|
911
|
-
case 0x61: w = (ws?"7":"2008_R2");
|
912
|
-
break;
|
913
|
-
case 0x62: w = (ws?"8":"2012");
|
914
|
-
break;
|
915
|
-
case 0x63: w = (ws?"8.1":"2012_R2");
|
916
|
-
break;
|
917
|
-
case 0x64: w = (ws?"10":"2015");
|
918
|
-
break;
|
919
|
-
default:
|
920
|
-
if (windows_version < 0x50)
|
921
|
-
windows_version = WINDOWS_UNSUPPORTED;
|
922
|
-
else
|
923
|
-
w = "11 or later";
|
924
|
-
break;
|
925
|
-
}
|
926
|
-
}
|
927
|
-
}
|
928
|
-
|
929
|
-
if (is_x64())
|
930
|
-
w64 = "64-bit";
|
931
|
-
|
932
|
-
vptr = &windows_version_str[sizeof("Windows ") - 1];
|
933
|
-
vlen = sizeof(windows_version_str) - sizeof("Windows ") - 1;
|
934
|
-
if (!w)
|
935
|
-
safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"),
|
936
|
-
(unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
|
937
|
-
else if (vi.wServicePackMinor)
|
938
|
-
safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
|
939
|
-
else if (vi.wServicePackMajor)
|
940
|
-
safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);
|
941
|
-
else
|
942
|
-
safe_sprintf(vptr, vlen, "%s %s", w, w64);
|
943
|
-
}
|
944
|
-
|
945
|
-
/*
|
946
|
-
* init: libusb backend init function
|
947
|
-
*
|
948
|
-
* This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list
|
949
|
-
* In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed.
|
950
|
-
* HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?)
|
951
|
-
*/
|
952
|
-
static int windows_init(struct libusb_context *ctx)
|
953
|
-
{
|
954
|
-
int i, r = LIBUSB_ERROR_OTHER;
|
955
|
-
DWORD_PTR affinity, dummy;
|
956
|
-
HANDLE event = NULL;
|
957
|
-
HANDLE semaphore;
|
958
|
-
LARGE_INTEGER li_frequency;
|
959
|
-
char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
|
960
|
-
|
961
|
-
sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
|
962
|
-
semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
|
963
|
-
if (semaphore == NULL) {
|
964
|
-
usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
|
965
|
-
return LIBUSB_ERROR_NO_MEM;
|
966
|
-
}
|
967
|
-
|
968
|
-
// A successful wait brings our semaphore count to 0 (unsignaled)
|
969
|
-
// => any concurent wait stalls until the semaphore's release
|
970
|
-
if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
|
971
|
-
usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
|
972
|
-
CloseHandle(semaphore);
|
973
|
-
return LIBUSB_ERROR_NO_MEM;
|
974
|
-
}
|
975
|
-
|
976
|
-
// NB: concurrent usage supposes that init calls are equally balanced with
|
977
|
-
// exit calls. If init is called more than exit, we will not exit properly
|
978
|
-
if ( ++concurrent_usage == 0 ) { // First init?
|
979
|
-
get_windows_version();
|
980
|
-
usbi_dbg(windows_version_str);
|
981
|
-
if (windows_version == WINDOWS_UNSUPPORTED) {
|
982
|
-
usbi_err(ctx, "This version of Windows is NOT supported");
|
983
|
-
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
984
|
-
goto init_exit;
|
985
|
-
}
|
986
|
-
|
987
|
-
// We need a lock for proper auto-release
|
988
|
-
usbi_mutex_init(&autoclaim_lock, NULL);
|
989
|
-
|
990
|
-
// Initialize pollable file descriptors
|
991
|
-
init_polling();
|
992
|
-
|
993
|
-
// Load DLL imports
|
994
|
-
if (init_dlls() != LIBUSB_SUCCESS) {
|
995
|
-
usbi_err(ctx, "could not resolve DLL functions");
|
996
|
-
goto init_exit;
|
997
|
-
}
|
998
|
-
|
999
|
-
// Initialize the low level APIs (we don't care about errors at this stage)
|
1000
|
-
for (i=0; i<USB_API_MAX; i++) {
|
1001
|
-
usb_api_backend[i].init(SUB_API_NOTSET, ctx);
|
1002
|
-
}
|
1003
|
-
|
1004
|
-
if (QueryPerformanceFrequency(&li_frequency)) {
|
1005
|
-
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
|
1006
|
-
// to picoseconds to compute the tv_nsecs part in clock_gettime
|
1007
|
-
hires_frequency = li_frequency.QuadPart;
|
1008
|
-
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
|
1009
|
-
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
|
1010
|
-
|
1011
|
-
// Because QueryPerformanceCounter might report different values when
|
1012
|
-
// running on different cores, we create a separate thread for the timer
|
1013
|
-
// calls, which we glue to the first available core always to prevent timing discrepancies.
|
1014
|
-
if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
|
1015
|
-
usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
|
1016
|
-
goto init_exit;
|
1017
|
-
}
|
1018
|
-
// The process affinity mask is a bitmask where each set bit represents a core on
|
1019
|
-
// which this process is allowed to run, so we find the first set bit
|
1020
|
-
for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
|
1021
|
-
affinity = (DWORD_PTR)(1 << i);
|
1022
|
-
|
1023
|
-
usbi_dbg("timer thread will run on core #%d", i);
|
1024
|
-
|
1025
|
-
r = LIBUSB_ERROR_NO_MEM;
|
1026
|
-
event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
1027
|
-
if (event == NULL) {
|
1028
|
-
usbi_err(ctx, "could not create event: %s", windows_error_str(0));
|
1029
|
-
goto init_exit;
|
1030
|
-
}
|
1031
|
-
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
|
1032
|
-
0, (unsigned int *)&timer_thread_id);
|
1033
|
-
if (timer_thread == NULL) {
|
1034
|
-
usbi_err(ctx, "unable to create timer thread - aborting");
|
1035
|
-
goto init_exit;
|
1036
|
-
}
|
1037
|
-
if (!SetThreadAffinityMask(timer_thread, affinity)) {
|
1038
|
-
usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
|
1039
|
-
}
|
1040
|
-
|
1041
|
-
// Wait for timer thread to init before continuing.
|
1042
|
-
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
|
1043
|
-
usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
|
1044
|
-
goto init_exit;
|
1045
|
-
}
|
1046
|
-
}
|
1047
|
-
else {
|
1048
|
-
usbi_dbg("no hires timer available on this platform");
|
1049
|
-
hires_frequency = 0;
|
1050
|
-
hires_ticks_to_ps = UINT64_C(0);
|
1051
|
-
}
|
1052
|
-
|
1053
|
-
// Create a hash table to store session ids. Second parameter is better if prime
|
1054
|
-
htab_create(ctx, HTAB_SIZE);
|
1055
|
-
}
|
1056
|
-
// At this stage, either we went through full init successfully, or didn't need to
|
1057
|
-
r = LIBUSB_SUCCESS;
|
1058
|
-
|
1059
|
-
init_exit: // Holds semaphore here.
|
1060
|
-
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
|
1061
|
-
if (timer_thread) {
|
1062
|
-
// actually the signal to quit the thread.
|
1063
|
-
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
|
1064
|
-
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
|
1065
|
-
usbi_warn(ctx, "could not wait for timer thread to quit");
|
1066
|
-
TerminateThread(timer_thread, 1);
|
1067
|
-
// shouldn't happen, but we're destroying
|
1068
|
-
// all objects it might have held anyway.
|
1069
|
-
}
|
1070
|
-
CloseHandle(timer_thread);
|
1071
|
-
timer_thread = NULL;
|
1072
|
-
timer_thread_id = 0;
|
1073
|
-
}
|
1074
|
-
htab_destroy();
|
1075
|
-
usbi_mutex_destroy(&autoclaim_lock);
|
1076
|
-
}
|
1077
|
-
|
1078
|
-
if (r != LIBUSB_SUCCESS)
|
1079
|
-
--concurrent_usage; // Not expected to call libusb_exit if we failed.
|
1080
|
-
|
1081
|
-
if (event)
|
1082
|
-
CloseHandle(event);
|
1083
|
-
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
|
1084
|
-
CloseHandle(semaphore);
|
1085
|
-
return r;
|
1086
|
-
}
|
1087
|
-
|
1088
|
-
/*
|
1089
|
-
* HCD (root) hubs need to have their device descriptor manually populated
|
1090
|
-
*
|
1091
|
-
* Note that, like Microsoft does in the device manager, we populate the
|
1092
|
-
* Vendor and Device ID for HCD hubs with the ones from the PCI HCD device.
|
1093
|
-
*/
|
1094
|
-
static int force_hcd_device_descriptor(struct libusb_device *dev)
|
1095
|
-
{
|
1096
|
-
struct windows_device_priv *parent_priv, *priv = _device_priv(dev);
|
1097
|
-
struct libusb_context *ctx = DEVICE_CTX(dev);
|
1098
|
-
int vid, pid;
|
1099
|
-
|
1100
|
-
dev->num_configurations = 1;
|
1101
|
-
priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
1102
|
-
priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
|
1103
|
-
priv->dev_descriptor.bNumConfigurations = 1;
|
1104
|
-
priv->active_config = 1;
|
1105
|
-
|
1106
|
-
if (priv->parent_dev == NULL) {
|
1107
|
-
usbi_err(ctx, "program assertion failed - HCD hub has no parent");
|
1108
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1109
|
-
}
|
1110
|
-
parent_priv = _device_priv(priv->parent_dev);
|
1111
|
-
if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) {
|
1112
|
-
priv->dev_descriptor.idVendor = (uint16_t)vid;
|
1113
|
-
priv->dev_descriptor.idProduct = (uint16_t)pid;
|
1114
|
-
} else {
|
1115
|
-
usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path);
|
1116
|
-
priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
|
1117
|
-
priv->dev_descriptor.idProduct = 1;
|
1118
|
-
}
|
1119
|
-
return LIBUSB_SUCCESS;
|
1120
|
-
}
|
1121
|
-
|
1122
|
-
/*
|
1123
|
-
* fetch and cache all the config descriptors through I/O
|
1124
|
-
*/
|
1125
|
-
static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char* device_id)
|
1126
|
-
{
|
1127
|
-
DWORD size, ret_size;
|
1128
|
-
struct libusb_context *ctx = DEVICE_CTX(dev);
|
1129
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1130
|
-
int r;
|
1131
|
-
uint8_t i;
|
1132
|
-
|
1133
|
-
USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
|
1134
|
-
PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request
|
1135
|
-
PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL;
|
1136
|
-
|
1137
|
-
if (dev->num_configurations == 0)
|
1138
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
1139
|
-
|
1140
|
-
priv->config_descriptor = (unsigned char**) calloc(dev->num_configurations, sizeof(unsigned char*));
|
1141
|
-
if (priv->config_descriptor == NULL)
|
1142
|
-
return LIBUSB_ERROR_NO_MEM;
|
1143
|
-
for (i=0; i<dev->num_configurations; i++)
|
1144
|
-
priv->config_descriptor[i] = NULL;
|
1145
|
-
|
1146
|
-
for (i=0, r=LIBUSB_SUCCESS; ; i++)
|
1147
|
-
{
|
1148
|
-
// safe loop: release all dynamic resources
|
1149
|
-
safe_free(cd_buf_actual);
|
1150
|
-
|
1151
|
-
// safe loop: end of loop condition
|
1152
|
-
if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS))
|
1153
|
-
break;
|
1154
|
-
|
1155
|
-
size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT);
|
1156
|
-
memset(&cd_buf_short, 0, size);
|
1157
|
-
|
1158
|
-
cd_buf_short.req.ConnectionIndex = (ULONG)priv->port;
|
1159
|
-
cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
|
1160
|
-
cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
1161
|
-
cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
|
1162
|
-
cd_buf_short.req.SetupPacket.wIndex = 0;
|
1163
|
-
cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
|
1164
|
-
|
1165
|
-
// Dummy call to get the required data size. Initial failures are reported as info rather
|
1166
|
-
// than error as they can occur for non-penalizing situations, such as with some hubs.
|
1167
|
-
// coverity[tainted_data_argument]
|
1168
|
-
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
|
1169
|
-
&cd_buf_short, size, &ret_size, NULL)) {
|
1170
|
-
usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0));
|
1171
|
-
LOOP_BREAK(LIBUSB_ERROR_IO);
|
1172
|
-
}
|
1173
|
-
|
1174
|
-
if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
|
1175
|
-
usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id);
|
1176
|
-
LOOP_BREAK(LIBUSB_ERROR_IO);
|
1177
|
-
}
|
1178
|
-
|
1179
|
-
size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength;
|
1180
|
-
if ((cd_buf_actual = (PUSB_DESCRIPTOR_REQUEST) calloc(1, size)) == NULL) {
|
1181
|
-
usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id);
|
1182
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1183
|
-
}
|
1184
|
-
memset(cd_buf_actual, 0, size);
|
1185
|
-
|
1186
|
-
// Actual call
|
1187
|
-
cd_buf_actual->ConnectionIndex = (ULONG)priv->port;
|
1188
|
-
cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
|
1189
|
-
cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
1190
|
-
cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
|
1191
|
-
cd_buf_actual->SetupPacket.wIndex = 0;
|
1192
|
-
cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
|
1193
|
-
|
1194
|
-
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
|
1195
|
-
cd_buf_actual, size, &ret_size, NULL)) {
|
1196
|
-
usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0));
|
1197
|
-
LOOP_BREAK(LIBUSB_ERROR_IO);
|
1198
|
-
}
|
1199
|
-
|
1200
|
-
cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR*)cd_buf_actual+sizeof(USB_DESCRIPTOR_REQUEST));
|
1201
|
-
|
1202
|
-
if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) {
|
1203
|
-
usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id);
|
1204
|
-
LOOP_BREAK(LIBUSB_ERROR_IO);
|
1205
|
-
}
|
1206
|
-
|
1207
|
-
if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) {
|
1208
|
-
usbi_err(ctx, "not a configuration descriptor for '%s'", device_id);
|
1209
|
-
LOOP_BREAK(LIBUSB_ERROR_IO);
|
1210
|
-
}
|
1211
|
-
|
1212
|
-
usbi_dbg("cached config descriptor %d (bConfigurationValue=%d, %d bytes)",
|
1213
|
-
i, cd_data->bConfigurationValue, cd_data->wTotalLength);
|
1214
|
-
|
1215
|
-
// Cache the descriptor
|
1216
|
-
priv->config_descriptor[i] = (unsigned char*) malloc(cd_data->wTotalLength);
|
1217
|
-
if (priv->config_descriptor[i] == NULL)
|
1218
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1219
|
-
memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
|
1220
|
-
}
|
1221
|
-
return LIBUSB_SUCCESS;
|
1222
|
-
}
|
1223
|
-
|
1224
|
-
/*
|
1225
|
-
* Populate a libusb device structure
|
1226
|
-
*/
|
1227
|
-
static int init_device(struct libusb_device* dev, struct libusb_device* parent_dev,
|
1228
|
-
uint8_t port_number, char* device_id, DWORD devinst)
|
1229
|
-
{
|
1230
|
-
HANDLE handle;
|
1231
|
-
DWORD size;
|
1232
|
-
USB_NODE_CONNECTION_INFORMATION_EX conn_info;
|
1233
|
-
USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
|
1234
|
-
struct windows_device_priv *priv, *parent_priv;
|
1235
|
-
struct libusb_context *ctx;
|
1236
|
-
struct libusb_device* tmp_dev;
|
1237
|
-
unsigned long tmp_id;
|
1238
|
-
unsigned i;
|
1239
|
-
|
1240
|
-
if ((dev == NULL) || (parent_dev == NULL)) {
|
1241
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1242
|
-
}
|
1243
|
-
ctx = DEVICE_CTX(dev);
|
1244
|
-
priv = _device_priv(dev);
|
1245
|
-
parent_priv = _device_priv(parent_dev);
|
1246
|
-
if (parent_priv->apib->id != USB_API_HUB) {
|
1247
|
-
usbi_warn(ctx, "parent for device '%s' is not a hub", device_id);
|
1248
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1249
|
-
}
|
1250
|
-
|
1251
|
-
// It is possible for the parent hub not to have been initialized yet
|
1252
|
-
// If that's the case, lookup the ancestors to set the bus number
|
1253
|
-
if (parent_dev->bus_number == 0) {
|
1254
|
-
for (i=2; ; i++) {
|
1255
|
-
tmp_id = get_ancestor_session_id(devinst, i);
|
1256
|
-
if (tmp_id == 0) break;
|
1257
|
-
tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id);
|
1258
|
-
if (tmp_dev == NULL) continue;
|
1259
|
-
if (tmp_dev->bus_number != 0) {
|
1260
|
-
usbi_dbg("got bus number from ancestor #%d", i);
|
1261
|
-
parent_dev->bus_number = tmp_dev->bus_number;
|
1262
|
-
libusb_unref_device(tmp_dev);
|
1263
|
-
break;
|
1264
|
-
}
|
1265
|
-
libusb_unref_device(tmp_dev);
|
1266
|
-
}
|
1267
|
-
}
|
1268
|
-
if (parent_dev->bus_number == 0) {
|
1269
|
-
usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id);
|
1270
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1271
|
-
}
|
1272
|
-
dev->bus_number = parent_dev->bus_number;
|
1273
|
-
priv->port = port_number;
|
1274
|
-
dev->port_number = port_number;
|
1275
|
-
priv->depth = parent_priv->depth + 1;
|
1276
|
-
priv->parent_dev = parent_dev;
|
1277
|
-
dev->parent_dev = parent_dev;
|
1278
|
-
|
1279
|
-
// If the device address is already set, we can stop here
|
1280
|
-
if (dev->device_address != 0) {
|
1281
|
-
return LIBUSB_SUCCESS;
|
1282
|
-
}
|
1283
|
-
memset(&conn_info, 0, sizeof(conn_info));
|
1284
|
-
if (priv->depth != 0) { // Not a HCD hub
|
1285
|
-
handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
1286
|
-
FILE_FLAG_OVERLAPPED, NULL);
|
1287
|
-
if (handle == INVALID_HANDLE_VALUE) {
|
1288
|
-
usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0));
|
1289
|
-
return LIBUSB_ERROR_ACCESS;
|
1290
|
-
}
|
1291
|
-
size = sizeof(conn_info);
|
1292
|
-
conn_info.ConnectionIndex = (ULONG)port_number;
|
1293
|
-
// coverity[tainted_data_argument]
|
1294
|
-
if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size,
|
1295
|
-
&conn_info, size, &size, NULL)) {
|
1296
|
-
usbi_warn(ctx, "could not get node connection information for device '%s': %s",
|
1297
|
-
device_id, windows_error_str(0));
|
1298
|
-
safe_closehandle(handle);
|
1299
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1300
|
-
}
|
1301
|
-
if (conn_info.ConnectionStatus == NoDeviceConnected) {
|
1302
|
-
usbi_err(ctx, "device '%s' is no longer connected!", device_id);
|
1303
|
-
safe_closehandle(handle);
|
1304
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1305
|
-
}
|
1306
|
-
memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
|
1307
|
-
dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
|
1308
|
-
priv->active_config = conn_info.CurrentConfigurationValue;
|
1309
|
-
usbi_dbg("found %d configurations (active conf: %d)", dev->num_configurations, priv->active_config);
|
1310
|
-
// If we can't read the config descriptors, just set the number of confs to zero
|
1311
|
-
if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) {
|
1312
|
-
dev->num_configurations = 0;
|
1313
|
-
priv->dev_descriptor.bNumConfigurations = 0;
|
1314
|
-
}
|
1315
|
-
|
1316
|
-
// In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
|
1317
|
-
if (windows_version >= WINDOWS_8) {
|
1318
|
-
memset(&conn_info_v2, 0, sizeof(conn_info_v2));
|
1319
|
-
size = sizeof(conn_info_v2);
|
1320
|
-
conn_info_v2.ConnectionIndex = (ULONG)port_number;
|
1321
|
-
conn_info_v2.Length = size;
|
1322
|
-
conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
|
1323
|
-
if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
|
1324
|
-
&conn_info_v2, size, &conn_info_v2, size, &size, NULL)) {
|
1325
|
-
usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
|
1326
|
-
device_id, windows_error_str(0));
|
1327
|
-
} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
|
1328
|
-
conn_info.Speed = 3;
|
1329
|
-
}
|
1330
|
-
}
|
1331
|
-
|
1332
|
-
safe_closehandle(handle);
|
1333
|
-
|
1334
|
-
if (conn_info.DeviceAddress > UINT8_MAX) {
|
1335
|
-
usbi_err(ctx, "program assertion failed: device address overflow");
|
1336
|
-
}
|
1337
|
-
dev->device_address = (uint8_t)conn_info.DeviceAddress + 1;
|
1338
|
-
if (dev->device_address == 1) {
|
1339
|
-
usbi_err(ctx, "program assertion failed: device address collision with root hub");
|
1340
|
-
}
|
1341
|
-
switch (conn_info.Speed) {
|
1342
|
-
case 0: dev->speed = LIBUSB_SPEED_LOW; break;
|
1343
|
-
case 1: dev->speed = LIBUSB_SPEED_FULL; break;
|
1344
|
-
case 2: dev->speed = LIBUSB_SPEED_HIGH; break;
|
1345
|
-
case 3: dev->speed = LIBUSB_SPEED_SUPER; break;
|
1346
|
-
default:
|
1347
|
-
usbi_warn(ctx, "Got unknown device speed %d", conn_info.Speed);
|
1348
|
-
break;
|
1349
|
-
}
|
1350
|
-
} else {
|
1351
|
-
dev->device_address = 1; // root hubs are set to use device number 1
|
1352
|
-
force_hcd_device_descriptor(dev);
|
1353
|
-
}
|
1354
|
-
|
1355
|
-
usbi_sanitize_device(dev);
|
1356
|
-
|
1357
|
-
usbi_dbg("(bus: %d, addr: %d, depth: %d, port: %d): '%s'",
|
1358
|
-
dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
|
1359
|
-
|
1360
|
-
return LIBUSB_SUCCESS;
|
1361
|
-
}
|
1362
|
-
|
1363
|
-
// Returns the api type, or 0 if not found/unsupported
|
1364
|
-
static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
|
1365
|
-
SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
|
1366
|
-
{
|
1367
|
-
// Precedence for filter drivers vs driver is in the order of this array
|
1368
|
-
struct driver_lookup lookup[3] = {
|
1369
|
-
{"\0\0", SPDRP_SERVICE, "driver"},
|
1370
|
-
{"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"},
|
1371
|
-
{"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"}
|
1372
|
-
};
|
1373
|
-
DWORD size, reg_type;
|
1374
|
-
unsigned k, l;
|
1375
|
-
int i, j;
|
1376
|
-
|
1377
|
-
*api = USB_API_UNSUPPORTED;
|
1378
|
-
*sub_api = SUB_API_NOTSET;
|
1379
|
-
// Check the service & filter names to know the API we should use
|
1380
|
-
for (k=0; k<3; k++) {
|
1381
|
-
if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop,
|
1382
|
-
®_type, (BYTE*)lookup[k].list, MAX_KEY_LENGTH, &size)) {
|
1383
|
-
// Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
|
1384
|
-
if (lookup[k].reg_prop == SPDRP_SERVICE) {
|
1385
|
-
// our buffers are MAX_KEY_LENGTH+1 so we can overflow if needed
|
1386
|
-
lookup[k].list[safe_strlen(lookup[k].list)+1] = 0;
|
1387
|
-
}
|
1388
|
-
// MULTI_SZ is a pain to work with. Turn it into something much more manageable
|
1389
|
-
// NB: none of the driver names we check against contain LIST_SEPARATOR,
|
1390
|
-
// (currently ';'), so even if an unsuported one does, it's not an issue
|
1391
|
-
for (l=0; (lookup[k].list[l] != 0) || (lookup[k].list[l+1] != 0); l++) {
|
1392
|
-
if (lookup[k].list[l] == 0) {
|
1393
|
-
lookup[k].list[l] = LIST_SEPARATOR;
|
1394
|
-
}
|
1395
|
-
}
|
1396
|
-
usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
|
1397
|
-
} else {
|
1398
|
-
if (GetLastError() != ERROR_INVALID_DATA) {
|
1399
|
-
usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
|
1400
|
-
}
|
1401
|
-
lookup[k].list[0] = 0;
|
1402
|
-
}
|
1403
|
-
}
|
1404
|
-
|
1405
|
-
for (i=1; i<USB_API_MAX; i++) {
|
1406
|
-
for (k=0; k<3; k++) {
|
1407
|
-
j = get_sub_api(lookup[k].list, i);
|
1408
|
-
if (j >= 0) {
|
1409
|
-
usbi_dbg("matched %s name against %s",
|
1410
|
-
lookup[k].designation, (i!=USB_API_WINUSBX)?usb_api_backend[i].designation:sub_api_name[j]);
|
1411
|
-
*api = i;
|
1412
|
-
*sub_api = j;
|
1413
|
-
return;
|
1414
|
-
}
|
1415
|
-
}
|
1416
|
-
}
|
1417
|
-
}
|
1418
|
-
|
1419
|
-
static int set_composite_interface(struct libusb_context* ctx, struct libusb_device* dev,
|
1420
|
-
char* dev_interface_path, char* device_id, int api, int sub_api)
|
1421
|
-
{
|
1422
|
-
unsigned i;
|
1423
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1424
|
-
int interface_number;
|
1425
|
-
|
1426
|
-
if (priv->apib->id != USB_API_COMPOSITE) {
|
1427
|
-
usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id);
|
1428
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1429
|
-
}
|
1430
|
-
|
1431
|
-
// Because MI_## are not necessarily in sequential order (some composite
|
1432
|
-
// devices will have only MI_00 & MI_03 for instance), we retrieve the actual
|
1433
|
-
// interface number from the path's MI value
|
1434
|
-
interface_number = 0;
|
1435
|
-
for (i=0; device_id[i] != 0; ) {
|
1436
|
-
if ( (device_id[i++] == 'M') && (device_id[i++] == 'I')
|
1437
|
-
&& (device_id[i++] == '_') ) {
|
1438
|
-
interface_number = (device_id[i++] - '0')*10;
|
1439
|
-
interface_number += device_id[i] - '0';
|
1440
|
-
break;
|
1441
|
-
}
|
1442
|
-
}
|
1443
|
-
|
1444
|
-
if (device_id[i] == 0) {
|
1445
|
-
usbi_warn(ctx, "failure to read interface number for %s. Using default value %d",
|
1446
|
-
device_id, interface_number);
|
1447
|
-
}
|
1448
|
-
|
1449
|
-
if (priv->usb_interface[interface_number].path != NULL) {
|
1450
|
-
if (api == USB_API_HID) {
|
1451
|
-
// HID devices can have multiple collections (COL##) for each MI_## interface
|
1452
|
-
usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
|
1453
|
-
interface_number, device_id);
|
1454
|
-
return LIBUSB_ERROR_ACCESS;
|
1455
|
-
}
|
1456
|
-
// In other cases, just use the latest data
|
1457
|
-
safe_free(priv->usb_interface[interface_number].path);
|
1458
|
-
}
|
1459
|
-
|
1460
|
-
usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
|
1461
|
-
priv->usb_interface[interface_number].path = dev_interface_path;
|
1462
|
-
priv->usb_interface[interface_number].apib = &usb_api_backend[api];
|
1463
|
-
priv->usb_interface[interface_number].sub_api = sub_api;
|
1464
|
-
if ((api == USB_API_HID) && (priv->hid == NULL)) {
|
1465
|
-
priv->hid = (struct hid_device_priv*) calloc(1, sizeof(struct hid_device_priv));
|
1466
|
-
if (priv->hid == NULL)
|
1467
|
-
return LIBUSB_ERROR_NO_MEM;
|
1468
|
-
}
|
1469
|
-
|
1470
|
-
return LIBUSB_SUCCESS;
|
1471
|
-
}
|
1472
|
-
|
1473
|
-
static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* dev,
|
1474
|
-
char* dev_interface_path)
|
1475
|
-
{
|
1476
|
-
int i;
|
1477
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1478
|
-
|
1479
|
-
if (priv->hid == NULL) {
|
1480
|
-
usbi_err(ctx, "program assertion failed: parent is not HID");
|
1481
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1482
|
-
}
|
1483
|
-
if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
|
1484
|
-
usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
|
1485
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1486
|
-
}
|
1487
|
-
for (i=0; i<priv->hid->nb_interfaces; i++) {
|
1488
|
-
if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
|
1489
|
-
usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
|
1490
|
-
return LIBUSB_SUCCESS;
|
1491
|
-
}
|
1492
|
-
}
|
1493
|
-
|
1494
|
-
priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
|
1495
|
-
priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
|
1496
|
-
usbi_dbg("interface[%d] = %s", priv->hid->nb_interfaces, dev_interface_path);
|
1497
|
-
priv->hid->nb_interfaces++;
|
1498
|
-
return LIBUSB_SUCCESS;
|
1499
|
-
}
|
1500
|
-
|
1501
|
-
/*
|
1502
|
-
* get_device_list: libusb backend device enumeration function
|
1503
|
-
*/
|
1504
|
-
static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
|
1505
|
-
{
|
1506
|
-
struct discovered_devs *discdevs;
|
1507
|
-
HDEVINFO dev_info = { 0 };
|
1508
|
-
const char* usb_class[] = {"USB", "NUSB3", "IUSB3"};
|
1509
|
-
SP_DEVINFO_DATA dev_info_data = { 0 };
|
1510
|
-
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
1511
|
-
GUID hid_guid;
|
1512
|
-
#define MAX_ENUM_GUIDS 64
|
1513
|
-
const GUID* guid[MAX_ENUM_GUIDS];
|
1514
|
-
#define HCD_PASS 0
|
1515
|
-
#define HUB_PASS 1
|
1516
|
-
#define GEN_PASS 2
|
1517
|
-
#define DEV_PASS 3
|
1518
|
-
#define HID_PASS 4
|
1519
|
-
int r = LIBUSB_SUCCESS;
|
1520
|
-
int api, sub_api;
|
1521
|
-
size_t class_index = 0;
|
1522
|
-
unsigned int nb_guids, pass, i, j, ancestor;
|
1523
|
-
char path[MAX_PATH_LENGTH];
|
1524
|
-
char strbuf[MAX_PATH_LENGTH];
|
1525
|
-
struct libusb_device *dev, *parent_dev;
|
1526
|
-
struct windows_device_priv *priv, *parent_priv;
|
1527
|
-
char* dev_interface_path = NULL;
|
1528
|
-
char* dev_id_path = NULL;
|
1529
|
-
unsigned long session_id;
|
1530
|
-
DWORD size, reg_type, port_nr, install_state;
|
1531
|
-
HKEY key;
|
1532
|
-
WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
|
1533
|
-
GUID* if_guid;
|
1534
|
-
LONG s;
|
1535
|
-
// Keep a list of newly allocated devs to unref
|
1536
|
-
libusb_device** unref_list;
|
1537
|
-
unsigned int unref_size = 64;
|
1538
|
-
unsigned int unref_cur = 0;
|
1539
|
-
|
1540
|
-
// PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
|
1541
|
-
// PASS 2 : (re)enumerate HUBS
|
1542
|
-
// PASS 3 : (re)enumerate generic USB devices (including driverless)
|
1543
|
-
// and list additional USB device interface GUIDs to explore
|
1544
|
-
// PASS 4 : (re)enumerate master USB devices that have a device interface
|
1545
|
-
// PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and
|
1546
|
-
// set the device interfaces.
|
1547
|
-
|
1548
|
-
// Init the GUID table
|
1549
|
-
guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
|
1550
|
-
guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB;
|
1551
|
-
guid[GEN_PASS] = NULL;
|
1552
|
-
guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
|
1553
|
-
HidD_GetHidGuid(&hid_guid);
|
1554
|
-
guid[HID_PASS] = &hid_guid;
|
1555
|
-
nb_guids = HID_PASS+1;
|
1556
|
-
|
1557
|
-
unref_list = (libusb_device**) calloc(unref_size, sizeof(libusb_device*));
|
1558
|
-
if (unref_list == NULL) {
|
1559
|
-
return LIBUSB_ERROR_NO_MEM;
|
1560
|
-
}
|
1561
|
-
|
1562
|
-
for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
|
1563
|
-
//#define ENUM_DEBUG
|
1564
|
-
#ifdef ENUM_DEBUG
|
1565
|
-
const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
|
1566
|
-
usbi_dbg("#### PROCESSING %ss %s", passname[(pass<=HID_PASS)?pass:HID_PASS+1],
|
1567
|
-
(pass!=GEN_PASS)?guid_to_string(guid[pass]):"");
|
1568
|
-
#endif
|
1569
|
-
for (i = 0; ; i++) {
|
1570
|
-
// safe loop: free up any (unprotected) dynamic resource
|
1571
|
-
// NB: this is always executed before breaking the loop
|
1572
|
-
safe_free(dev_interface_details);
|
1573
|
-
safe_free(dev_interface_path);
|
1574
|
-
safe_free(dev_id_path);
|
1575
|
-
priv = parent_priv = NULL;
|
1576
|
-
dev = parent_dev = NULL;
|
1577
|
-
|
1578
|
-
// Safe loop: end of loop conditions
|
1579
|
-
if (r != LIBUSB_SUCCESS) {
|
1580
|
-
break;
|
1581
|
-
}
|
1582
|
-
if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
|
1583
|
-
usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX);
|
1584
|
-
break;
|
1585
|
-
}
|
1586
|
-
if (pass != GEN_PASS) {
|
1587
|
-
// Except for GEN, all passes deal with device interfaces
|
1588
|
-
dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i);
|
1589
|
-
if (dev_interface_details == NULL) {
|
1590
|
-
break;
|
1591
|
-
} else {
|
1592
|
-
dev_interface_path = sanitize_path(dev_interface_details->DevicePath);
|
1593
|
-
if (dev_interface_path == NULL) {
|
1594
|
-
usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath);
|
1595
|
-
continue;
|
1596
|
-
}
|
1597
|
-
}
|
1598
|
-
} else {
|
1599
|
-
// Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
|
1600
|
-
// being listed under the "NUSB3" PnP Symbolic Name rather than "USB".
|
1601
|
-
// The Intel USB 3.0 driver behaves similar, but uses "IUSB3"
|
1602
|
-
for (; class_index < ARRAYSIZE(usb_class); class_index++) {
|
1603
|
-
if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i))
|
1604
|
-
break;
|
1605
|
-
i = 0;
|
1606
|
-
}
|
1607
|
-
if (class_index >= ARRAYSIZE(usb_class))
|
1608
|
-
break;
|
1609
|
-
}
|
1610
|
-
|
1611
|
-
// Read the Device ID path. This is what we'll use as UID
|
1612
|
-
// Note that if the device is plugged in a different port or hub, the Device ID changes
|
1613
|
-
if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) {
|
1614
|
-
usbi_warn(ctx, "could not read the device id path for devinst %X, skipping",
|
1615
|
-
dev_info_data.DevInst);
|
1616
|
-
continue;
|
1617
|
-
}
|
1618
|
-
dev_id_path = sanitize_path(path);
|
1619
|
-
if (dev_id_path == NULL) {
|
1620
|
-
usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping",
|
1621
|
-
dev_info_data.DevInst);
|
1622
|
-
continue;
|
1623
|
-
}
|
1624
|
-
#ifdef ENUM_DEBUG
|
1625
|
-
usbi_dbg("PRO: %s", dev_id_path);
|
1626
|
-
#endif
|
1627
|
-
|
1628
|
-
// The SPDRP_ADDRESS for USB devices is the device port number on the hub
|
1629
|
-
port_nr = 0;
|
1630
|
-
if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) {
|
1631
|
-
if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS,
|
1632
|
-
®_type, (BYTE*)&port_nr, 4, &size))
|
1633
|
-
|| (size != 4) ) {
|
1634
|
-
usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s",
|
1635
|
-
dev_id_path, windows_error_str(0));
|
1636
|
-
continue;
|
1637
|
-
}
|
1638
|
-
}
|
1639
|
-
|
1640
|
-
// Set API to use or get additional data from generic pass
|
1641
|
-
api = USB_API_UNSUPPORTED;
|
1642
|
-
sub_api = SUB_API_NOTSET;
|
1643
|
-
switch (pass) {
|
1644
|
-
case HCD_PASS:
|
1645
|
-
break;
|
1646
|
-
case GEN_PASS:
|
1647
|
-
// We use the GEN pass to detect driverless devices...
|
1648
|
-
size = sizeof(strbuf);
|
1649
|
-
if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER,
|
1650
|
-
®_type, (BYTE*)strbuf, size, &size)) {
|
1651
|
-
usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path);
|
1652
|
-
usbi_info(ctx, "libusb will not be able to access it.");
|
1653
|
-
}
|
1654
|
-
// ...and to add the additional device interface GUIDs
|
1655
|
-
key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
|
1656
|
-
if (key != INVALID_HANDLE_VALUE) {
|
1657
|
-
size = sizeof(guid_string_w);
|
1658
|
-
s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type,
|
1659
|
-
(BYTE*)guid_string_w, &size);
|
1660
|
-
pRegCloseKey(key);
|
1661
|
-
if (s == ERROR_SUCCESS) {
|
1662
|
-
if (nb_guids >= MAX_ENUM_GUIDS) {
|
1663
|
-
// If this assert is ever reported, grow a GUID table dynamically
|
1664
|
-
usbi_err(ctx, "program assertion failed: too many GUIDs");
|
1665
|
-
LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
|
1666
|
-
}
|
1667
|
-
if_guid = (GUID*) calloc(1, sizeof(GUID));
|
1668
|
-
if (if_guid == NULL) {
|
1669
|
-
usbi_err(ctx, "could not calloc for if_guid: not enough memory");
|
1670
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1671
|
-
}
|
1672
|
-
pCLSIDFromString(guid_string_w, if_guid);
|
1673
|
-
guid[nb_guids++] = if_guid;
|
1674
|
-
usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
|
1675
|
-
}
|
1676
|
-
}
|
1677
|
-
break;
|
1678
|
-
case HID_PASS:
|
1679
|
-
api = USB_API_HID;
|
1680
|
-
break;
|
1681
|
-
default:
|
1682
|
-
// Get the API type (after checking that the driver installation is OK)
|
1683
|
-
if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
|
1684
|
-
®_type, (BYTE*)&install_state, 4, &size))
|
1685
|
-
|| (size != 4) ){
|
1686
|
-
usbi_warn(ctx, "could not detect installation state of driver for '%s': %s",
|
1687
|
-
dev_id_path, windows_error_str(0));
|
1688
|
-
} else if (install_state != 0) {
|
1689
|
-
usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %d) - skipping",
|
1690
|
-
dev_id_path, install_state);
|
1691
|
-
continue;
|
1692
|
-
}
|
1693
|
-
get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api);
|
1694
|
-
break;
|
1695
|
-
}
|
1696
|
-
|
1697
|
-
// Find parent device (for the passes that need it)
|
1698
|
-
switch (pass) {
|
1699
|
-
case HCD_PASS:
|
1700
|
-
case DEV_PASS:
|
1701
|
-
case HUB_PASS:
|
1702
|
-
break;
|
1703
|
-
default:
|
1704
|
-
// Go through the ancestors until we see a face we recognize
|
1705
|
-
parent_dev = NULL;
|
1706
|
-
for (ancestor = 1; parent_dev == NULL; ancestor++) {
|
1707
|
-
session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor);
|
1708
|
-
if (session_id == 0) {
|
1709
|
-
break;
|
1710
|
-
}
|
1711
|
-
parent_dev = usbi_get_device_by_session_id(ctx, session_id);
|
1712
|
-
}
|
1713
|
-
if (parent_dev == NULL) {
|
1714
|
-
usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path);
|
1715
|
-
continue;
|
1716
|
-
}
|
1717
|
-
parent_priv = _device_priv(parent_dev);
|
1718
|
-
// virtual USB devices are also listed during GEN - don't process these yet
|
1719
|
-
if ( (pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB) ) {
|
1720
|
-
libusb_unref_device(parent_dev);
|
1721
|
-
continue;
|
1722
|
-
}
|
1723
|
-
break;
|
1724
|
-
}
|
1725
|
-
|
1726
|
-
// Create new or match existing device, using the (hashed) device_id as session id
|
1727
|
-
if (pass <= DEV_PASS) { // For subsequent passes, we'll lookup the parent
|
1728
|
-
// These are the passes that create "new" devices
|
1729
|
-
session_id = htab_hash(dev_id_path);
|
1730
|
-
dev = usbi_get_device_by_session_id(ctx, session_id);
|
1731
|
-
if (dev == NULL) {
|
1732
|
-
if (pass == DEV_PASS) {
|
1733
|
-
// This can occur if the OS only reports a newly plugged device after we started enum
|
1734
|
-
usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)"
|
1735
|
-
" - ignoring", dev_id_path);
|
1736
|
-
continue;
|
1737
|
-
}
|
1738
|
-
usbi_dbg("allocating new device for session [%X]", session_id);
|
1739
|
-
if ((dev = usbi_alloc_device(ctx, session_id)) == NULL) {
|
1740
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1741
|
-
}
|
1742
|
-
windows_device_priv_init(dev);
|
1743
|
-
} else {
|
1744
|
-
usbi_dbg("found existing device for session [%X] (%d.%d)",
|
1745
|
-
session_id, dev->bus_number, dev->device_address);
|
1746
|
-
}
|
1747
|
-
// Keep track of devices that need unref
|
1748
|
-
unref_list[unref_cur++] = dev;
|
1749
|
-
if (unref_cur >= unref_size) {
|
1750
|
-
unref_size += 64;
|
1751
|
-
unref_list = usbi_reallocf(unref_list, unref_size*sizeof(libusb_device*));
|
1752
|
-
if (unref_list == NULL) {
|
1753
|
-
usbi_err(ctx, "could not realloc list for unref - aborting.");
|
1754
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1755
|
-
}
|
1756
|
-
}
|
1757
|
-
priv = _device_priv(dev);
|
1758
|
-
}
|
1759
|
-
|
1760
|
-
// Setup device
|
1761
|
-
switch (pass) {
|
1762
|
-
case HCD_PASS:
|
1763
|
-
dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected
|
1764
|
-
dev->device_address = 0;
|
1765
|
-
dev->num_configurations = 0;
|
1766
|
-
priv->apib = &usb_api_backend[USB_API_HUB];
|
1767
|
-
priv->sub_api = SUB_API_NOTSET;
|
1768
|
-
priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs
|
1769
|
-
priv->path = dev_interface_path; dev_interface_path = NULL;
|
1770
|
-
break;
|
1771
|
-
case HUB_PASS:
|
1772
|
-
case DEV_PASS:
|
1773
|
-
// If the device has already been setup, don't do it again
|
1774
|
-
if (priv->path != NULL)
|
1775
|
-
break;
|
1776
|
-
// Take care of API initialization
|
1777
|
-
priv->path = dev_interface_path; dev_interface_path = NULL;
|
1778
|
-
priv->apib = &usb_api_backend[api];
|
1779
|
-
priv->sub_api = sub_api;
|
1780
|
-
switch(api) {
|
1781
|
-
case USB_API_COMPOSITE:
|
1782
|
-
case USB_API_HUB:
|
1783
|
-
break;
|
1784
|
-
case USB_API_HID:
|
1785
|
-
priv->hid = calloc(1, sizeof(struct hid_device_priv));
|
1786
|
-
if (priv->hid == NULL) {
|
1787
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1788
|
-
}
|
1789
|
-
priv->hid->nb_interfaces = 0;
|
1790
|
-
break;
|
1791
|
-
default:
|
1792
|
-
// For other devices, the first interface is the same as the device
|
1793
|
-
priv->usb_interface[0].path = (char*) calloc(safe_strlen(priv->path)+1, 1);
|
1794
|
-
if (priv->usb_interface[0].path != NULL) {
|
1795
|
-
safe_strcpy(priv->usb_interface[0].path, safe_strlen(priv->path)+1, priv->path);
|
1796
|
-
} else {
|
1797
|
-
usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path);
|
1798
|
-
}
|
1799
|
-
// The following is needed if we want API calls to work for both simple
|
1800
|
-
// and composite devices.
|
1801
|
-
for(j=0; j<USB_MAXINTERFACES; j++) {
|
1802
|
-
priv->usb_interface[j].apib = &usb_api_backend[api];
|
1803
|
-
}
|
1804
|
-
break;
|
1805
|
-
}
|
1806
|
-
break;
|
1807
|
-
case GEN_PASS:
|
1808
|
-
r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst);
|
1809
|
-
if (r == LIBUSB_SUCCESS) {
|
1810
|
-
// Append device to the list of discovered devices
|
1811
|
-
discdevs = discovered_devs_append(*_discdevs, dev);
|
1812
|
-
if (!discdevs) {
|
1813
|
-
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1814
|
-
}
|
1815
|
-
*_discdevs = discdevs;
|
1816
|
-
} else if (r == LIBUSB_ERROR_NO_DEVICE) {
|
1817
|
-
// This can occur if the device was disconnected but Windows hasn't
|
1818
|
-
// refreshed its enumeration yet - in that case, we ignore the device
|
1819
|
-
r = LIBUSB_SUCCESS;
|
1820
|
-
}
|
1821
|
-
break;
|
1822
|
-
default: // HID_PASS and later
|
1823
|
-
if (parent_priv->apib->id == USB_API_HID) {
|
1824
|
-
usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
|
1825
|
-
r = set_hid_interface(ctx, parent_dev, dev_interface_path);
|
1826
|
-
if (r != LIBUSB_SUCCESS) LOOP_BREAK(r);
|
1827
|
-
dev_interface_path = NULL;
|
1828
|
-
} else if (parent_priv->apib->id == USB_API_COMPOSITE) {
|
1829
|
-
usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
|
1830
|
-
switch (set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api)) {
|
1831
|
-
case LIBUSB_SUCCESS:
|
1832
|
-
dev_interface_path = NULL;
|
1833
|
-
break;
|
1834
|
-
case LIBUSB_ERROR_ACCESS:
|
1835
|
-
// interface has already been set => make sure dev_interface_path is freed then
|
1836
|
-
break;
|
1837
|
-
default:
|
1838
|
-
LOOP_BREAK(r);
|
1839
|
-
break;
|
1840
|
-
}
|
1841
|
-
}
|
1842
|
-
libusb_unref_device(parent_dev);
|
1843
|
-
break;
|
1844
|
-
}
|
1845
|
-
}
|
1846
|
-
}
|
1847
|
-
|
1848
|
-
// Free any additional GUIDs
|
1849
|
-
for (pass = HID_PASS+1; pass < nb_guids; pass++) {
|
1850
|
-
safe_free(guid[pass]);
|
1851
|
-
}
|
1852
|
-
|
1853
|
-
// Unref newly allocated devs
|
1854
|
-
if (unref_list != NULL) {
|
1855
|
-
for (i=0; i<unref_cur; i++) {
|
1856
|
-
safe_unref_device(unref_list[i]);
|
1857
|
-
}
|
1858
|
-
free(unref_list);
|
1859
|
-
}
|
1860
|
-
|
1861
|
-
return r;
|
1862
|
-
}
|
1863
|
-
|
1864
|
-
/*
|
1865
|
-
* exit: libusb backend deinitialization function
|
1866
|
-
*/
|
1867
|
-
static void windows_exit(void)
|
1868
|
-
{
|
1869
|
-
int i;
|
1870
|
-
HANDLE semaphore;
|
1871
|
-
char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
|
1872
|
-
|
1873
|
-
sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
|
1874
|
-
semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
|
1875
|
-
if (semaphore == NULL) {
|
1876
|
-
return;
|
1877
|
-
}
|
1878
|
-
|
1879
|
-
// A successful wait brings our semaphore count to 0 (unsignaled)
|
1880
|
-
// => any concurent wait stalls until the semaphore release
|
1881
|
-
if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
|
1882
|
-
CloseHandle(semaphore);
|
1883
|
-
return;
|
1884
|
-
}
|
1885
|
-
|
1886
|
-
// Only works if exits and inits are balanced exactly
|
1887
|
-
if (--concurrent_usage < 0) { // Last exit
|
1888
|
-
for (i=0; i<USB_API_MAX; i++) {
|
1889
|
-
usb_api_backend[i].exit(SUB_API_NOTSET);
|
1890
|
-
}
|
1891
|
-
exit_polling();
|
1892
|
-
|
1893
|
-
if (timer_thread) {
|
1894
|
-
// actually the signal to quit the thread.
|
1895
|
-
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
|
1896
|
-
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
|
1897
|
-
usbi_dbg("could not wait for timer thread to quit");
|
1898
|
-
TerminateThread(timer_thread, 1);
|
1899
|
-
}
|
1900
|
-
CloseHandle(timer_thread);
|
1901
|
-
timer_thread = NULL;
|
1902
|
-
timer_thread_id = 0;
|
1903
|
-
}
|
1904
|
-
htab_destroy();
|
1905
|
-
usbi_mutex_destroy(&autoclaim_lock);
|
1906
|
-
}
|
1907
|
-
|
1908
|
-
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
|
1909
|
-
CloseHandle(semaphore);
|
1910
|
-
}
|
1911
|
-
|
1912
|
-
static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
|
1913
|
-
{
|
1914
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1915
|
-
|
1916
|
-
memcpy(buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH);
|
1917
|
-
*host_endian = 0;
|
1918
|
-
|
1919
|
-
return LIBUSB_SUCCESS;
|
1920
|
-
}
|
1921
|
-
|
1922
|
-
static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
|
1923
|
-
{
|
1924
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1925
|
-
PUSB_CONFIGURATION_DESCRIPTOR config_header;
|
1926
|
-
size_t size;
|
1927
|
-
|
1928
|
-
// config index is zero based
|
1929
|
-
if (config_index >= dev->num_configurations)
|
1930
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
1931
|
-
|
1932
|
-
if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
|
1933
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1934
|
-
|
1935
|
-
config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
|
1936
|
-
|
1937
|
-
size = MIN(config_header->wTotalLength, len);
|
1938
|
-
memcpy(buffer, priv->config_descriptor[config_index], size);
|
1939
|
-
*host_endian = 0;
|
1940
|
-
|
1941
|
-
return (int)size;
|
1942
|
-
}
|
1943
|
-
|
1944
|
-
/*
|
1945
|
-
* return the cached copy of the active config descriptor
|
1946
|
-
*/
|
1947
|
-
static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
|
1948
|
-
{
|
1949
|
-
struct windows_device_priv *priv = _device_priv(dev);
|
1950
|
-
|
1951
|
-
if (priv->active_config == 0)
|
1952
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1953
|
-
|
1954
|
-
// config index is zero based
|
1955
|
-
return windows_get_config_descriptor(dev, (uint8_t)(priv->active_config-1), buffer, len, host_endian);
|
1956
|
-
}
|
1957
|
-
|
1958
|
-
static int windows_open(struct libusb_device_handle *dev_handle)
|
1959
|
-
{
|
1960
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
1961
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
1962
|
-
|
1963
|
-
if (priv->apib == NULL) {
|
1964
|
-
usbi_err(ctx, "program assertion failed - device is not initialized");
|
1965
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
1966
|
-
}
|
1967
|
-
|
1968
|
-
return priv->apib->open(SUB_API_NOTSET, dev_handle);
|
1969
|
-
}
|
1970
|
-
|
1971
|
-
static void windows_close(struct libusb_device_handle *dev_handle)
|
1972
|
-
{
|
1973
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
1974
|
-
|
1975
|
-
priv->apib->close(SUB_API_NOTSET, dev_handle);
|
1976
|
-
}
|
1977
|
-
|
1978
|
-
static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
|
1979
|
-
{
|
1980
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
1981
|
-
|
1982
|
-
if (priv->active_config == 0) {
|
1983
|
-
*config = 0;
|
1984
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
1985
|
-
}
|
1986
|
-
|
1987
|
-
*config = priv->active_config;
|
1988
|
-
return LIBUSB_SUCCESS;
|
1989
|
-
}
|
1990
|
-
|
1991
|
-
/*
|
1992
|
-
* from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver
|
1993
|
-
* does not currently expose a service that allows higher-level drivers to set
|
1994
|
-
* the configuration."
|
1995
|
-
*/
|
1996
|
-
static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
|
1997
|
-
{
|
1998
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
1999
|
-
int r = LIBUSB_SUCCESS;
|
2000
|
-
|
2001
|
-
if (config >= USB_MAXCONFIG)
|
2002
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
2003
|
-
|
2004
|
-
r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
|
2005
|
-
LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
|
2006
|
-
LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
|
2007
|
-
0, NULL, 0, 1000);
|
2008
|
-
|
2009
|
-
if (r == LIBUSB_SUCCESS) {
|
2010
|
-
priv->active_config = (uint8_t)config;
|
2011
|
-
}
|
2012
|
-
return r;
|
2013
|
-
}
|
2014
|
-
|
2015
|
-
static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface)
|
2016
|
-
{
|
2017
|
-
int r = LIBUSB_SUCCESS;
|
2018
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2019
|
-
|
2020
|
-
safe_free(priv->usb_interface[iface].endpoint);
|
2021
|
-
priv->usb_interface[iface].nb_endpoints= 0;
|
2022
|
-
|
2023
|
-
r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface);
|
2024
|
-
|
2025
|
-
if (r == LIBUSB_SUCCESS) {
|
2026
|
-
r = windows_assign_endpoints(dev_handle, iface, 0);
|
2027
|
-
}
|
2028
|
-
|
2029
|
-
return r;
|
2030
|
-
}
|
2031
|
-
|
2032
|
-
static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
2033
|
-
{
|
2034
|
-
int r = LIBUSB_SUCCESS;
|
2035
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2036
|
-
|
2037
|
-
safe_free(priv->usb_interface[iface].endpoint);
|
2038
|
-
priv->usb_interface[iface].nb_endpoints= 0;
|
2039
|
-
|
2040
|
-
r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting);
|
2041
|
-
|
2042
|
-
if (r == LIBUSB_SUCCESS) {
|
2043
|
-
r = windows_assign_endpoints(dev_handle, iface, altsetting);
|
2044
|
-
}
|
2045
|
-
|
2046
|
-
return r;
|
2047
|
-
}
|
2048
|
-
|
2049
|
-
static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface)
|
2050
|
-
{
|
2051
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2052
|
-
|
2053
|
-
return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
|
2054
|
-
}
|
2055
|
-
|
2056
|
-
static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
|
2057
|
-
{
|
2058
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2059
|
-
return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
|
2060
|
-
}
|
2061
|
-
|
2062
|
-
static int windows_reset_device(struct libusb_device_handle *dev_handle)
|
2063
|
-
{
|
2064
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2065
|
-
return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
|
2066
|
-
}
|
2067
|
-
|
2068
|
-
// The 3 functions below are unlikely to ever get supported on Windows
|
2069
|
-
static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
|
2070
|
-
{
|
2071
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2072
|
-
}
|
2073
|
-
|
2074
|
-
static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
|
2075
|
-
{
|
2076
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2077
|
-
}
|
2078
|
-
|
2079
|
-
static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
|
2080
|
-
{
|
2081
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2082
|
-
}
|
2083
|
-
|
2084
|
-
static void windows_destroy_device(struct libusb_device *dev)
|
2085
|
-
{
|
2086
|
-
windows_device_priv_release(dev);
|
2087
|
-
}
|
2088
|
-
|
2089
|
-
static void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
|
2090
|
-
{
|
2091
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
2092
|
-
|
2093
|
-
usbi_free_fd(&transfer_priv->pollable_fd);
|
2094
|
-
safe_free(transfer_priv->hid_buffer);
|
2095
|
-
// When auto claim is in use, attempt to release the auto-claimed interface
|
2096
|
-
auto_release(itransfer);
|
2097
|
-
}
|
2098
|
-
|
2099
|
-
static int submit_bulk_transfer(struct usbi_transfer *itransfer)
|
2100
|
-
{
|
2101
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2102
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
2103
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
2104
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2105
|
-
int r;
|
2106
|
-
|
2107
|
-
r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer);
|
2108
|
-
if (r != LIBUSB_SUCCESS) {
|
2109
|
-
return r;
|
2110
|
-
}
|
2111
|
-
|
2112
|
-
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
|
2113
|
-
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
|
2114
|
-
|
2115
|
-
return LIBUSB_SUCCESS;
|
2116
|
-
}
|
2117
|
-
|
2118
|
-
static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
2119
|
-
{
|
2120
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2121
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
2122
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
2123
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2124
|
-
int r;
|
2125
|
-
|
2126
|
-
r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer);
|
2127
|
-
if (r != LIBUSB_SUCCESS) {
|
2128
|
-
return r;
|
2129
|
-
}
|
2130
|
-
|
2131
|
-
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
|
2132
|
-
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
|
2133
|
-
|
2134
|
-
return LIBUSB_SUCCESS;
|
2135
|
-
}
|
2136
|
-
|
2137
|
-
static int submit_control_transfer(struct usbi_transfer *itransfer)
|
2138
|
-
{
|
2139
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2140
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
2141
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
2142
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2143
|
-
int r;
|
2144
|
-
|
2145
|
-
r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer);
|
2146
|
-
if (r != LIBUSB_SUCCESS) {
|
2147
|
-
return r;
|
2148
|
-
}
|
2149
|
-
|
2150
|
-
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
|
2151
|
-
|
2152
|
-
return LIBUSB_SUCCESS;
|
2153
|
-
|
2154
|
-
}
|
2155
|
-
|
2156
|
-
static int windows_submit_transfer(struct usbi_transfer *itransfer)
|
2157
|
-
{
|
2158
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2159
|
-
|
2160
|
-
switch (transfer->type) {
|
2161
|
-
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
2162
|
-
return submit_control_transfer(itransfer);
|
2163
|
-
case LIBUSB_TRANSFER_TYPE_BULK:
|
2164
|
-
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
2165
|
-
if (IS_XFEROUT(transfer) &&
|
2166
|
-
transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)
|
2167
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2168
|
-
return submit_bulk_transfer(itransfer);
|
2169
|
-
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
2170
|
-
return submit_iso_transfer(itransfer);
|
2171
|
-
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
2172
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2173
|
-
default:
|
2174
|
-
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
|
2175
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
2176
|
-
}
|
2177
|
-
}
|
2178
|
-
|
2179
|
-
static int windows_abort_control(struct usbi_transfer *itransfer)
|
2180
|
-
{
|
2181
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2182
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2183
|
-
|
2184
|
-
return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
|
2185
|
-
}
|
2186
|
-
|
2187
|
-
static int windows_abort_transfers(struct usbi_transfer *itransfer)
|
2188
|
-
{
|
2189
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2190
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2191
|
-
|
2192
|
-
return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
|
2193
|
-
}
|
2194
|
-
|
2195
|
-
static int windows_cancel_transfer(struct usbi_transfer *itransfer)
|
2196
|
-
{
|
2197
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2198
|
-
|
2199
|
-
switch (transfer->type) {
|
2200
|
-
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
2201
|
-
return windows_abort_control(itransfer);
|
2202
|
-
case LIBUSB_TRANSFER_TYPE_BULK:
|
2203
|
-
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
2204
|
-
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
2205
|
-
return windows_abort_transfers(itransfer);
|
2206
|
-
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
2207
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
2208
|
-
default:
|
2209
|
-
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
|
2210
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
2211
|
-
}
|
2212
|
-
}
|
2213
|
-
|
2214
|
-
static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
|
2215
|
-
{
|
2216
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2217
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2218
|
-
int status, istatus;
|
2219
|
-
|
2220
|
-
usbi_dbg("handling I/O completion with errcode %d, size %d", io_result, io_size);
|
2221
|
-
|
2222
|
-
switch(io_result) {
|
2223
|
-
case NO_ERROR:
|
2224
|
-
status = priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
|
2225
|
-
break;
|
2226
|
-
case ERROR_GEN_FAILURE:
|
2227
|
-
usbi_dbg("detected endpoint stall");
|
2228
|
-
status = LIBUSB_TRANSFER_STALL;
|
2229
|
-
break;
|
2230
|
-
case ERROR_SEM_TIMEOUT:
|
2231
|
-
usbi_dbg("detected semaphore timeout");
|
2232
|
-
status = LIBUSB_TRANSFER_TIMED_OUT;
|
2233
|
-
break;
|
2234
|
-
case ERROR_OPERATION_ABORTED:
|
2235
|
-
istatus = priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
|
2236
|
-
if (istatus != LIBUSB_TRANSFER_COMPLETED) {
|
2237
|
-
usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
|
2238
|
-
}
|
2239
|
-
if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) {
|
2240
|
-
usbi_dbg("detected timeout");
|
2241
|
-
status = LIBUSB_TRANSFER_TIMED_OUT;
|
2242
|
-
} else {
|
2243
|
-
usbi_dbg("detected operation aborted");
|
2244
|
-
status = LIBUSB_TRANSFER_CANCELLED;
|
2245
|
-
}
|
2246
|
-
break;
|
2247
|
-
default:
|
2248
|
-
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %d: %s", io_result, windows_error_str(io_result));
|
2249
|
-
status = LIBUSB_TRANSFER_ERROR;
|
2250
|
-
break;
|
2251
|
-
}
|
2252
|
-
windows_clear_transfer_priv(itransfer); // Cancel polling
|
2253
|
-
usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
|
2254
|
-
}
|
2255
|
-
|
2256
|
-
static void windows_handle_callback (struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
|
2257
|
-
{
|
2258
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2259
|
-
|
2260
|
-
switch (transfer->type) {
|
2261
|
-
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
2262
|
-
case LIBUSB_TRANSFER_TYPE_BULK:
|
2263
|
-
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
2264
|
-
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
2265
|
-
windows_transfer_callback (itransfer, io_result, io_size);
|
2266
|
-
break;
|
2267
|
-
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
2268
|
-
usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
|
2269
|
-
break;
|
2270
|
-
default:
|
2271
|
-
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
|
2272
|
-
}
|
2273
|
-
}
|
2274
|
-
|
2275
|
-
static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
|
2276
|
-
{
|
2277
|
-
struct windows_transfer_priv* transfer_priv = NULL;
|
2278
|
-
POLL_NFDS_TYPE i = 0;
|
2279
|
-
bool found;
|
2280
|
-
struct usbi_transfer *transfer;
|
2281
|
-
DWORD io_size, io_result;
|
2282
|
-
|
2283
|
-
usbi_mutex_lock(&ctx->open_devs_lock);
|
2284
|
-
for (i = 0; i < nfds && num_ready > 0; i++) {
|
2285
|
-
|
2286
|
-
usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
|
2287
|
-
|
2288
|
-
if (!fds[i].revents) {
|
2289
|
-
continue;
|
2290
|
-
}
|
2291
|
-
|
2292
|
-
num_ready--;
|
2293
|
-
|
2294
|
-
// Because a Windows OVERLAPPED is used for poll emulation,
|
2295
|
-
// a pollable fd is created and stored with each transfer
|
2296
|
-
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
2297
|
-
found = false;
|
2298
|
-
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
|
2299
|
-
transfer_priv = usbi_transfer_get_os_priv(transfer);
|
2300
|
-
if (transfer_priv->pollable_fd.fd == fds[i].fd) {
|
2301
|
-
found = true;
|
2302
|
-
break;
|
2303
|
-
}
|
2304
|
-
}
|
2305
|
-
usbi_mutex_unlock(&ctx->flying_transfers_lock);
|
2306
|
-
|
2307
|
-
if (found) {
|
2308
|
-
// Handle async requests that completed synchronously first
|
2309
|
-
if (HasOverlappedIoCompletedSync(transfer_priv->pollable_fd.overlapped)) {
|
2310
|
-
io_result = NO_ERROR;
|
2311
|
-
io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh;
|
2312
|
-
// Regular async overlapped
|
2313
|
-
} else if (GetOverlappedResult(transfer_priv->pollable_fd.handle,
|
2314
|
-
transfer_priv->pollable_fd.overlapped, &io_size, false)) {
|
2315
|
-
io_result = NO_ERROR;
|
2316
|
-
} else {
|
2317
|
-
io_result = GetLastError();
|
2318
|
-
}
|
2319
|
-
usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
|
2320
|
-
// let handle_callback free the event using the transfer wfd
|
2321
|
-
// If you don't use the transfer wfd, you run a risk of trying to free a
|
2322
|
-
// newly allocated wfd that took the place of the one from the transfer.
|
2323
|
-
windows_handle_callback(transfer, io_result, io_size);
|
2324
|
-
} else {
|
2325
|
-
usbi_mutex_unlock(&ctx->open_devs_lock);
|
2326
|
-
usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]);
|
2327
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2328
|
-
}
|
2329
|
-
}
|
2330
|
-
|
2331
|
-
usbi_mutex_unlock(&ctx->open_devs_lock);
|
2332
|
-
return LIBUSB_SUCCESS;
|
2333
|
-
}
|
2334
|
-
|
2335
|
-
/*
|
2336
|
-
* Monotonic and real time functions
|
2337
|
-
*/
|
2338
|
-
unsigned __stdcall windows_clock_gettime_threaded(void* param)
|
2339
|
-
{
|
2340
|
-
struct timer_request *request;
|
2341
|
-
LARGE_INTEGER hires_counter;
|
2342
|
-
MSG msg;
|
2343
|
-
|
2344
|
-
// The following call will create this thread's message queue
|
2345
|
-
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
|
2346
|
-
pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
2347
|
-
|
2348
|
-
// Signal windows_init() that we're ready to service requests
|
2349
|
-
if (!SetEvent((HANDLE)param)) {
|
2350
|
-
usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
|
2351
|
-
}
|
2352
|
-
param = NULL;
|
2353
|
-
|
2354
|
-
// Main loop - wait for requests
|
2355
|
-
while (1) {
|
2356
|
-
if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
|
2357
|
-
usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
|
2358
|
-
return 1;
|
2359
|
-
}
|
2360
|
-
|
2361
|
-
switch (msg.message) {
|
2362
|
-
case WM_TIMER_REQUEST:
|
2363
|
-
// Requests to this thread are for hires always
|
2364
|
-
// Microsoft says that this function always succeeds on XP and later
|
2365
|
-
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
|
2366
|
-
request = (struct timer_request *)msg.lParam;
|
2367
|
-
QueryPerformanceCounter(&hires_counter);
|
2368
|
-
request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
|
2369
|
-
request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
|
2370
|
-
if (!SetEvent(request->event)) {
|
2371
|
-
usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
|
2372
|
-
}
|
2373
|
-
break;
|
2374
|
-
|
2375
|
-
case WM_TIMER_EXIT:
|
2376
|
-
usbi_dbg("timer thread quitting");
|
2377
|
-
return 0;
|
2378
|
-
}
|
2379
|
-
}
|
2380
|
-
}
|
2381
|
-
|
2382
|
-
static int windows_clock_gettime(int clk_id, struct timespec *tp)
|
2383
|
-
{
|
2384
|
-
struct timer_request request;
|
2385
|
-
FILETIME filetime;
|
2386
|
-
ULARGE_INTEGER rtime;
|
2387
|
-
DWORD r;
|
2388
|
-
switch(clk_id) {
|
2389
|
-
case USBI_CLOCK_MONOTONIC:
|
2390
|
-
if (timer_thread) {
|
2391
|
-
request.tp = tp;
|
2392
|
-
request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
2393
|
-
if (request.event == NULL) {
|
2394
|
-
return LIBUSB_ERROR_NO_MEM;
|
2395
|
-
}
|
2396
|
-
|
2397
|
-
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
|
2398
|
-
usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
|
2399
|
-
CloseHandle(request.event);
|
2400
|
-
return LIBUSB_ERROR_OTHER;
|
2401
|
-
}
|
2402
|
-
|
2403
|
-
do {
|
2404
|
-
r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
|
2405
|
-
if (r == WAIT_TIMEOUT) {
|
2406
|
-
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
|
2407
|
-
}
|
2408
|
-
else if (r == WAIT_FAILED) {
|
2409
|
-
usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
|
2410
|
-
}
|
2411
|
-
} while (r == WAIT_TIMEOUT);
|
2412
|
-
CloseHandle(request.event);
|
2413
|
-
|
2414
|
-
if (r == WAIT_OBJECT_0) {
|
2415
|
-
return LIBUSB_SUCCESS;
|
2416
|
-
}
|
2417
|
-
else {
|
2418
|
-
return LIBUSB_ERROR_OTHER;
|
2419
|
-
}
|
2420
|
-
}
|
2421
|
-
// Fall through and return real-time if monotonic was not detected @ timer init
|
2422
|
-
case USBI_CLOCK_REALTIME:
|
2423
|
-
// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
|
2424
|
-
// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
|
2425
|
-
// Note however that our resolution is bounded by the Windows system time
|
2426
|
-
// functions and is at best of the order of 1 ms (or, usually, worse)
|
2427
|
-
GetSystemTimeAsFileTime(&filetime);
|
2428
|
-
rtime.LowPart = filetime.dwLowDateTime;
|
2429
|
-
rtime.HighPart = filetime.dwHighDateTime;
|
2430
|
-
rtime.QuadPart -= epoch_time;
|
2431
|
-
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
|
2432
|
-
tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
|
2433
|
-
return LIBUSB_SUCCESS;
|
2434
|
-
default:
|
2435
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
2436
|
-
}
|
2437
|
-
}
|
2438
|
-
|
2439
|
-
|
2440
|
-
// NB: MSVC6 does not support named initializers.
|
2441
|
-
const struct usbi_os_backend windows_backend = {
|
2442
|
-
"Windows",
|
2443
|
-
USBI_CAP_HAS_HID_ACCESS,
|
2444
|
-
windows_init,
|
2445
|
-
windows_exit,
|
2446
|
-
|
2447
|
-
windows_get_device_list,
|
2448
|
-
NULL, /* hotplug_poll */
|
2449
|
-
windows_open,
|
2450
|
-
windows_close,
|
2451
|
-
|
2452
|
-
windows_get_device_descriptor,
|
2453
|
-
windows_get_active_config_descriptor,
|
2454
|
-
windows_get_config_descriptor,
|
2455
|
-
NULL, /* get_config_descriptor_by_value() */
|
2456
|
-
|
2457
|
-
windows_get_configuration,
|
2458
|
-
windows_set_configuration,
|
2459
|
-
windows_claim_interface,
|
2460
|
-
windows_release_interface,
|
2461
|
-
|
2462
|
-
windows_set_interface_altsetting,
|
2463
|
-
windows_clear_halt,
|
2464
|
-
windows_reset_device,
|
2465
|
-
|
2466
|
-
NULL, /* alloc_streams */
|
2467
|
-
NULL, /* free_streams */
|
2468
|
-
|
2469
|
-
windows_kernel_driver_active,
|
2470
|
-
windows_detach_kernel_driver,
|
2471
|
-
windows_attach_kernel_driver,
|
2472
|
-
|
2473
|
-
windows_destroy_device,
|
2474
|
-
|
2475
|
-
windows_submit_transfer,
|
2476
|
-
windows_cancel_transfer,
|
2477
|
-
windows_clear_transfer_priv,
|
2478
|
-
|
2479
|
-
windows_handle_events,
|
2480
|
-
NULL, /* handle_transfer_completion() */
|
2481
|
-
|
2482
|
-
windows_clock_gettime,
|
2483
|
-
#if defined(USBI_TIMERFD_AVAILABLE)
|
2484
|
-
NULL,
|
2485
|
-
#endif
|
2486
|
-
sizeof(struct windows_device_priv),
|
2487
|
-
sizeof(struct windows_device_handle_priv),
|
2488
|
-
sizeof(struct windows_transfer_priv),
|
2489
|
-
};
|
2490
|
-
|
2491
|
-
|
2492
|
-
/*
|
2493
|
-
* USB API backends
|
2494
|
-
*/
|
2495
|
-
static int unsupported_init(int sub_api, struct libusb_context *ctx) {
|
2496
|
-
return LIBUSB_SUCCESS;
|
2497
|
-
}
|
2498
|
-
static int unsupported_exit(int sub_api) {
|
2499
|
-
return LIBUSB_SUCCESS;
|
2500
|
-
}
|
2501
|
-
static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) {
|
2502
|
-
PRINT_UNSUPPORTED_API(open);
|
2503
|
-
}
|
2504
|
-
static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) {
|
2505
|
-
usbi_dbg("unsupported API call for 'close'");
|
2506
|
-
}
|
2507
|
-
static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) {
|
2508
|
-
PRINT_UNSUPPORTED_API(configure_endpoints);
|
2509
|
-
}
|
2510
|
-
static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) {
|
2511
|
-
PRINT_UNSUPPORTED_API(claim_interface);
|
2512
|
-
}
|
2513
|
-
static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) {
|
2514
|
-
PRINT_UNSUPPORTED_API(set_interface_altsetting);
|
2515
|
-
}
|
2516
|
-
static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) {
|
2517
|
-
PRINT_UNSUPPORTED_API(release_interface);
|
2518
|
-
}
|
2519
|
-
static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) {
|
2520
|
-
PRINT_UNSUPPORTED_API(clear_halt);
|
2521
|
-
}
|
2522
|
-
static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) {
|
2523
|
-
PRINT_UNSUPPORTED_API(reset_device);
|
2524
|
-
}
|
2525
|
-
static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
2526
|
-
PRINT_UNSUPPORTED_API(submit_bulk_transfer);
|
2527
|
-
}
|
2528
|
-
static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
2529
|
-
PRINT_UNSUPPORTED_API(submit_iso_transfer);
|
2530
|
-
}
|
2531
|
-
static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
2532
|
-
PRINT_UNSUPPORTED_API(submit_control_transfer);
|
2533
|
-
}
|
2534
|
-
static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) {
|
2535
|
-
PRINT_UNSUPPORTED_API(abort_control);
|
2536
|
-
}
|
2537
|
-
static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) {
|
2538
|
-
PRINT_UNSUPPORTED_API(abort_transfers);
|
2539
|
-
}
|
2540
|
-
static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) {
|
2541
|
-
PRINT_UNSUPPORTED_API(copy_transfer_data);
|
2542
|
-
}
|
2543
|
-
static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) {
|
2544
|
-
return LIBUSB_SUCCESS;
|
2545
|
-
}
|
2546
|
-
// These names must be uppercase
|
2547
|
-
const char* hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30"};
|
2548
|
-
const char* composite_driver_names[] = {"USBCCGP"};
|
2549
|
-
const char* winusbx_driver_names[] = WINUSBX_DRV_NAMES;
|
2550
|
-
const char* hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
|
2551
|
-
const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
|
2552
|
-
{
|
2553
|
-
USB_API_UNSUPPORTED,
|
2554
|
-
"Unsupported API",
|
2555
|
-
NULL,
|
2556
|
-
0,
|
2557
|
-
unsupported_init,
|
2558
|
-
unsupported_exit,
|
2559
|
-
unsupported_open,
|
2560
|
-
unsupported_close,
|
2561
|
-
unsupported_configure_endpoints,
|
2562
|
-
unsupported_claim_interface,
|
2563
|
-
unsupported_set_interface_altsetting,
|
2564
|
-
unsupported_release_interface,
|
2565
|
-
unsupported_clear_halt,
|
2566
|
-
unsupported_reset_device,
|
2567
|
-
unsupported_submit_bulk_transfer,
|
2568
|
-
unsupported_submit_iso_transfer,
|
2569
|
-
unsupported_submit_control_transfer,
|
2570
|
-
unsupported_abort_control,
|
2571
|
-
unsupported_abort_transfers,
|
2572
|
-
unsupported_copy_transfer_data,
|
2573
|
-
}, {
|
2574
|
-
USB_API_HUB,
|
2575
|
-
"HUB API",
|
2576
|
-
hub_driver_names,
|
2577
|
-
ARRAYSIZE(hub_driver_names),
|
2578
|
-
unsupported_init,
|
2579
|
-
unsupported_exit,
|
2580
|
-
unsupported_open,
|
2581
|
-
unsupported_close,
|
2582
|
-
unsupported_configure_endpoints,
|
2583
|
-
unsupported_claim_interface,
|
2584
|
-
unsupported_set_interface_altsetting,
|
2585
|
-
unsupported_release_interface,
|
2586
|
-
unsupported_clear_halt,
|
2587
|
-
unsupported_reset_device,
|
2588
|
-
unsupported_submit_bulk_transfer,
|
2589
|
-
unsupported_submit_iso_transfer,
|
2590
|
-
unsupported_submit_control_transfer,
|
2591
|
-
unsupported_abort_control,
|
2592
|
-
unsupported_abort_transfers,
|
2593
|
-
unsupported_copy_transfer_data,
|
2594
|
-
}, {
|
2595
|
-
USB_API_COMPOSITE,
|
2596
|
-
"Composite API",
|
2597
|
-
composite_driver_names,
|
2598
|
-
ARRAYSIZE(composite_driver_names),
|
2599
|
-
composite_init,
|
2600
|
-
composite_exit,
|
2601
|
-
composite_open,
|
2602
|
-
composite_close,
|
2603
|
-
common_configure_endpoints,
|
2604
|
-
composite_claim_interface,
|
2605
|
-
composite_set_interface_altsetting,
|
2606
|
-
composite_release_interface,
|
2607
|
-
composite_clear_halt,
|
2608
|
-
composite_reset_device,
|
2609
|
-
composite_submit_bulk_transfer,
|
2610
|
-
composite_submit_iso_transfer,
|
2611
|
-
composite_submit_control_transfer,
|
2612
|
-
composite_abort_control,
|
2613
|
-
composite_abort_transfers,
|
2614
|
-
composite_copy_transfer_data,
|
2615
|
-
}, {
|
2616
|
-
USB_API_WINUSBX,
|
2617
|
-
"WinUSB-like APIs",
|
2618
|
-
winusbx_driver_names,
|
2619
|
-
ARRAYSIZE(winusbx_driver_names),
|
2620
|
-
winusbx_init,
|
2621
|
-
winusbx_exit,
|
2622
|
-
winusbx_open,
|
2623
|
-
winusbx_close,
|
2624
|
-
winusbx_configure_endpoints,
|
2625
|
-
winusbx_claim_interface,
|
2626
|
-
winusbx_set_interface_altsetting,
|
2627
|
-
winusbx_release_interface,
|
2628
|
-
winusbx_clear_halt,
|
2629
|
-
winusbx_reset_device,
|
2630
|
-
winusbx_submit_bulk_transfer,
|
2631
|
-
unsupported_submit_iso_transfer,
|
2632
|
-
winusbx_submit_control_transfer,
|
2633
|
-
winusbx_abort_control,
|
2634
|
-
winusbx_abort_transfers,
|
2635
|
-
winusbx_copy_transfer_data,
|
2636
|
-
}, {
|
2637
|
-
USB_API_HID,
|
2638
|
-
"HID API",
|
2639
|
-
hid_driver_names,
|
2640
|
-
ARRAYSIZE(hid_driver_names),
|
2641
|
-
hid_init,
|
2642
|
-
hid_exit,
|
2643
|
-
hid_open,
|
2644
|
-
hid_close,
|
2645
|
-
common_configure_endpoints,
|
2646
|
-
hid_claim_interface,
|
2647
|
-
hid_set_interface_altsetting,
|
2648
|
-
hid_release_interface,
|
2649
|
-
hid_clear_halt,
|
2650
|
-
hid_reset_device,
|
2651
|
-
hid_submit_bulk_transfer,
|
2652
|
-
unsupported_submit_iso_transfer,
|
2653
|
-
hid_submit_control_transfer,
|
2654
|
-
hid_abort_transfers,
|
2655
|
-
hid_abort_transfers,
|
2656
|
-
hid_copy_transfer_data,
|
2657
|
-
},
|
2658
|
-
};
|
2659
|
-
|
2660
|
-
|
2661
|
-
/*
|
2662
|
-
* WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
|
2663
|
-
*/
|
2664
|
-
#define WinUSBX_Set(fn) do { if (native_winusb) WinUSBX[i].fn = (WinUsb_##fn##_t) GetProcAddress(h, "WinUsb_" #fn); \
|
2665
|
-
else pLibK_GetProcAddress((PVOID*)&WinUSBX[i].fn, i, KUSB_FNID_##fn); } while (0)
|
2666
|
-
|
2667
|
-
static int winusbx_init(int sub_api, struct libusb_context *ctx)
|
2668
|
-
{
|
2669
|
-
HMODULE h = NULL;
|
2670
|
-
bool native_winusb = false;
|
2671
|
-
int i;
|
2672
|
-
KLIB_VERSION LibK_Version;
|
2673
|
-
LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
|
2674
|
-
LibK_GetVersion_t pLibK_GetVersion = NULL;
|
2675
|
-
|
2676
|
-
h = GetModuleHandleA("libusbK");
|
2677
|
-
if (h == NULL) {
|
2678
|
-
h = LoadLibraryA("libusbK");
|
2679
|
-
}
|
2680
|
-
if (h == NULL) {
|
2681
|
-
usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
|
2682
|
-
h = GetModuleHandleA("WinUSB");
|
2683
|
-
if (h == NULL) {
|
2684
|
-
h = LoadLibraryA("WinUSB");
|
2685
|
-
} if (h == NULL) {
|
2686
|
-
usbi_warn(ctx, "WinUSB DLL is not available either, "
|
2687
|
-
"you will not be able to access devices outside of enumeration");
|
2688
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2689
|
-
}
|
2690
|
-
} else {
|
2691
|
-
usbi_dbg("using libusbK DLL for universal access");
|
2692
|
-
pLibK_GetVersion = (LibK_GetVersion_t) GetProcAddress(h, "LibK_GetVersion");
|
2693
|
-
if (pLibK_GetVersion != NULL) {
|
2694
|
-
pLibK_GetVersion(&LibK_Version);
|
2695
|
-
usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
|
2696
|
-
LibK_Version.Micro, LibK_Version.Nano);
|
2697
|
-
}
|
2698
|
-
pLibK_GetProcAddress = (LibK_GetProcAddress_t) GetProcAddress(h, "LibK_GetProcAddress");
|
2699
|
-
if (pLibK_GetProcAddress == NULL) {
|
2700
|
-
usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
|
2701
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2702
|
-
}
|
2703
|
-
}
|
2704
|
-
native_winusb = (pLibK_GetProcAddress == NULL);
|
2705
|
-
for (i=SUB_API_LIBUSBK; i<SUB_API_MAX; i++) {
|
2706
|
-
WinUSBX_Set(AbortPipe);
|
2707
|
-
WinUSBX_Set(ControlTransfer);
|
2708
|
-
WinUSBX_Set(FlushPipe);
|
2709
|
-
WinUSBX_Set(Free);
|
2710
|
-
WinUSBX_Set(GetAssociatedInterface);
|
2711
|
-
WinUSBX_Set(GetCurrentAlternateSetting);
|
2712
|
-
WinUSBX_Set(GetDescriptor);
|
2713
|
-
WinUSBX_Set(GetOverlappedResult);
|
2714
|
-
WinUSBX_Set(GetPipePolicy);
|
2715
|
-
WinUSBX_Set(GetPowerPolicy);
|
2716
|
-
WinUSBX_Set(Initialize);
|
2717
|
-
WinUSBX_Set(QueryDeviceInformation);
|
2718
|
-
WinUSBX_Set(QueryInterfaceSettings);
|
2719
|
-
WinUSBX_Set(QueryPipe);
|
2720
|
-
WinUSBX_Set(ReadPipe);
|
2721
|
-
WinUSBX_Set(ResetPipe);
|
2722
|
-
WinUSBX_Set(SetCurrentAlternateSetting);
|
2723
|
-
WinUSBX_Set(SetPipePolicy);
|
2724
|
-
WinUSBX_Set(SetPowerPolicy);
|
2725
|
-
WinUSBX_Set(WritePipe);
|
2726
|
-
if (!native_winusb) {
|
2727
|
-
WinUSBX_Set(ResetDevice);
|
2728
|
-
}
|
2729
|
-
if (WinUSBX[i].Initialize != NULL) {
|
2730
|
-
WinUSBX[i].initialized = true;
|
2731
|
-
usbi_dbg("initalized sub API %s", sub_api_name[i]);
|
2732
|
-
} else {
|
2733
|
-
usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]);
|
2734
|
-
WinUSBX[i].initialized = false;
|
2735
|
-
}
|
2736
|
-
}
|
2737
|
-
return LIBUSB_SUCCESS;
|
2738
|
-
}
|
2739
|
-
|
2740
|
-
static int winusbx_exit(int sub_api)
|
2741
|
-
{
|
2742
|
-
return LIBUSB_SUCCESS;
|
2743
|
-
}
|
2744
|
-
|
2745
|
-
// NB: open and close must ensure that they only handle interface of
|
2746
|
-
// the right API type, as these functions can be called wholesale from
|
2747
|
-
// composite_open(), with interfaces belonging to different APIs
|
2748
|
-
static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
|
2749
|
-
{
|
2750
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
2751
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2752
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2753
|
-
|
2754
|
-
HANDLE file_handle;
|
2755
|
-
int i;
|
2756
|
-
|
2757
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
2758
|
-
|
2759
|
-
// WinUSB requires a seperate handle for each interface
|
2760
|
-
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
2761
|
-
if ( (priv->usb_interface[i].path != NULL)
|
2762
|
-
&& (priv->usb_interface[i].apib->id == USB_API_WINUSBX) ) {
|
2763
|
-
file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
|
2764
|
-
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
2765
|
-
if (file_handle == INVALID_HANDLE_VALUE) {
|
2766
|
-
usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
|
2767
|
-
switch(GetLastError()) {
|
2768
|
-
case ERROR_FILE_NOT_FOUND: // The device was disconnected
|
2769
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
2770
|
-
case ERROR_ACCESS_DENIED:
|
2771
|
-
return LIBUSB_ERROR_ACCESS;
|
2772
|
-
default:
|
2773
|
-
return LIBUSB_ERROR_IO;
|
2774
|
-
}
|
2775
|
-
}
|
2776
|
-
handle_priv->interface_handle[i].dev_handle = file_handle;
|
2777
|
-
}
|
2778
|
-
}
|
2779
|
-
|
2780
|
-
return LIBUSB_SUCCESS;
|
2781
|
-
}
|
2782
|
-
|
2783
|
-
static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
|
2784
|
-
{
|
2785
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2786
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2787
|
-
HANDLE handle;
|
2788
|
-
int i;
|
2789
|
-
|
2790
|
-
if (sub_api == SUB_API_NOTSET)
|
2791
|
-
sub_api = priv->sub_api;
|
2792
|
-
if (!WinUSBX[sub_api].initialized)
|
2793
|
-
return;
|
2794
|
-
|
2795
|
-
if (priv->apib->id == USB_API_COMPOSITE) {
|
2796
|
-
// If this is a composite device, just free and close all WinUSB-like
|
2797
|
-
// interfaces directly (each is independent and not associated with another)
|
2798
|
-
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
2799
|
-
if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
|
2800
|
-
handle = handle_priv->interface_handle[i].api_handle;
|
2801
|
-
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2802
|
-
WinUSBX[sub_api].Free(handle);
|
2803
|
-
}
|
2804
|
-
handle = handle_priv->interface_handle[i].dev_handle;
|
2805
|
-
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2806
|
-
CloseHandle(handle);
|
2807
|
-
}
|
2808
|
-
}
|
2809
|
-
}
|
2810
|
-
}
|
2811
|
-
else {
|
2812
|
-
// If this is a WinUSB device, free all interfaces above interface 0,
|
2813
|
-
// then free and close interface 0 last
|
2814
|
-
for (i = 1; i < USB_MAXINTERFACES; i++) {
|
2815
|
-
handle = handle_priv->interface_handle[i].api_handle;
|
2816
|
-
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2817
|
-
WinUSBX[sub_api].Free(handle);
|
2818
|
-
}
|
2819
|
-
}
|
2820
|
-
handle = handle_priv->interface_handle[0].api_handle;
|
2821
|
-
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2822
|
-
WinUSBX[sub_api].Free(handle);
|
2823
|
-
}
|
2824
|
-
handle = handle_priv->interface_handle[0].dev_handle;
|
2825
|
-
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2826
|
-
CloseHandle(handle);
|
2827
|
-
}
|
2828
|
-
}
|
2829
|
-
}
|
2830
|
-
|
2831
|
-
static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
2832
|
-
{
|
2833
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2834
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2835
|
-
HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
|
2836
|
-
UCHAR policy;
|
2837
|
-
ULONG timeout = 0;
|
2838
|
-
uint8_t endpoint_address;
|
2839
|
-
int i;
|
2840
|
-
|
2841
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
2842
|
-
|
2843
|
-
// With handle and enpoints set (in parent), we can setup the default pipe properties
|
2844
|
-
// see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
|
2845
|
-
for (i=-1; i<priv->usb_interface[iface].nb_endpoints; i++) {
|
2846
|
-
endpoint_address =(i==-1)?0:priv->usb_interface[iface].endpoint[i];
|
2847
|
-
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
|
2848
|
-
PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) {
|
2849
|
-
usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
|
2850
|
-
}
|
2851
|
-
if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) {
|
2852
|
-
continue; // Other policies don't apply to control endpoint or libusb0
|
2853
|
-
}
|
2854
|
-
policy = false;
|
2855
|
-
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
|
2856
|
-
SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
|
2857
|
-
usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
|
2858
|
-
}
|
2859
|
-
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
|
2860
|
-
IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) {
|
2861
|
-
usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
|
2862
|
-
}
|
2863
|
-
policy = true;
|
2864
|
-
/* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
|
2865
|
-
https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
|
2866
|
-
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
|
2867
|
-
ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) {
|
2868
|
-
usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
|
2869
|
-
}
|
2870
|
-
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
|
2871
|
-
AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) {
|
2872
|
-
usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
|
2873
|
-
}
|
2874
|
-
}
|
2875
|
-
|
2876
|
-
return LIBUSB_SUCCESS;
|
2877
|
-
}
|
2878
|
-
|
2879
|
-
static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
2880
|
-
{
|
2881
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
2882
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2883
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2884
|
-
bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
|
2885
|
-
HANDLE file_handle, winusb_handle;
|
2886
|
-
DWORD err;
|
2887
|
-
int i;
|
2888
|
-
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
2889
|
-
HDEVINFO dev_info = INVALID_HANDLE_VALUE;
|
2890
|
-
SP_DEVINFO_DATA dev_info_data;
|
2891
|
-
char* dev_path_no_guid = NULL;
|
2892
|
-
char filter_path[] = "\\\\.\\libusb0-0000";
|
2893
|
-
bool found_filter = false;
|
2894
|
-
|
2895
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
2896
|
-
|
2897
|
-
// If the device is composite, but using the default Windows composite parent driver (usbccgp)
|
2898
|
-
// or if it's the first WinUSB-like interface, we get a handle through Initialize().
|
2899
|
-
if ((is_using_usbccgp) || (iface == 0)) {
|
2900
|
-
// composite device (independent interfaces) or interface 0
|
2901
|
-
file_handle = handle_priv->interface_handle[iface].dev_handle;
|
2902
|
-
if ((file_handle == 0) || (file_handle == INVALID_HANDLE_VALUE)) {
|
2903
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2904
|
-
}
|
2905
|
-
|
2906
|
-
if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
|
2907
|
-
handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
|
2908
|
-
err = GetLastError();
|
2909
|
-
switch(err) {
|
2910
|
-
case ERROR_BAD_COMMAND:
|
2911
|
-
// The device was disconnected
|
2912
|
-
usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
|
2913
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
2914
|
-
default:
|
2915
|
-
// it may be that we're using the libusb0 filter driver.
|
2916
|
-
// TODO: can we move this whole business into the K/0 DLL?
|
2917
|
-
for (i = 0; ; i++) {
|
2918
|
-
safe_free(dev_interface_details);
|
2919
|
-
safe_free(dev_path_no_guid);
|
2920
|
-
dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path);
|
2921
|
-
if ((found_filter) || (dev_interface_details == NULL)) {
|
2922
|
-
break;
|
2923
|
-
}
|
2924
|
-
// ignore GUID part
|
2925
|
-
dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{"));
|
2926
|
-
if (safe_strncmp(dev_path_no_guid, priv->usb_interface[iface].path, safe_strlen(dev_path_no_guid)) == 0) {
|
2927
|
-
file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
|
2928
|
-
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
2929
|
-
if (file_handle == INVALID_HANDLE_VALUE) {
|
2930
|
-
usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0));
|
2931
|
-
} else {
|
2932
|
-
WinUSBX[sub_api].Free(winusb_handle);
|
2933
|
-
if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle))
|
2934
|
-
found_filter = true;
|
2935
|
-
else
|
2936
|
-
usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
|
2937
|
-
}
|
2938
|
-
}
|
2939
|
-
}
|
2940
|
-
if (!found_filter) {
|
2941
|
-
usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
|
2942
|
-
return LIBUSB_ERROR_ACCESS;
|
2943
|
-
}
|
2944
|
-
}
|
2945
|
-
}
|
2946
|
-
handle_priv->interface_handle[iface].api_handle = winusb_handle;
|
2947
|
-
} else {
|
2948
|
-
// For all other interfaces, use GetAssociatedInterface()
|
2949
|
-
winusb_handle = handle_priv->interface_handle[0].api_handle;
|
2950
|
-
// It is a requirement for multiple interface devices on Windows that, to you
|
2951
|
-
// must first claim the first interface before you claim the others
|
2952
|
-
if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) {
|
2953
|
-
file_handle = handle_priv->interface_handle[0].dev_handle;
|
2954
|
-
if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
|
2955
|
-
handle_priv->interface_handle[0].api_handle = winusb_handle;
|
2956
|
-
usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
|
2957
|
-
} else {
|
2958
|
-
usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
|
2959
|
-
return LIBUSB_ERROR_ACCESS;
|
2960
|
-
}
|
2961
|
-
}
|
2962
|
-
if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface-1),
|
2963
|
-
&handle_priv->interface_handle[iface].api_handle)) {
|
2964
|
-
handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
|
2965
|
-
switch(GetLastError()) {
|
2966
|
-
case ERROR_NO_MORE_ITEMS: // invalid iface
|
2967
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2968
|
-
case ERROR_BAD_COMMAND: // The device was disconnected
|
2969
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
2970
|
-
case ERROR_ALREADY_EXISTS: // already claimed
|
2971
|
-
return LIBUSB_ERROR_BUSY;
|
2972
|
-
default:
|
2973
|
-
usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
|
2974
|
-
return LIBUSB_ERROR_ACCESS;
|
2975
|
-
}
|
2976
|
-
}
|
2977
|
-
}
|
2978
|
-
usbi_dbg("claimed interface %d", iface);
|
2979
|
-
handle_priv->active_interface = iface;
|
2980
|
-
|
2981
|
-
return LIBUSB_SUCCESS;
|
2982
|
-
}
|
2983
|
-
|
2984
|
-
static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
2985
|
-
{
|
2986
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2987
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2988
|
-
HANDLE winusb_handle;
|
2989
|
-
|
2990
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
2991
|
-
|
2992
|
-
winusb_handle = handle_priv->interface_handle[iface].api_handle;
|
2993
|
-
if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) {
|
2994
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
2995
|
-
}
|
2996
|
-
|
2997
|
-
WinUSBX[sub_api].Free(winusb_handle);
|
2998
|
-
handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
|
2999
|
-
|
3000
|
-
return LIBUSB_SUCCESS;
|
3001
|
-
}
|
3002
|
-
|
3003
|
-
/*
|
3004
|
-
* Return the first valid interface (of the same API type), for control transfers
|
3005
|
-
*/
|
3006
|
-
static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
|
3007
|
-
{
|
3008
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3009
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3010
|
-
int i;
|
3011
|
-
|
3012
|
-
if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
|
3013
|
-
usbi_dbg("unsupported API ID");
|
3014
|
-
return -1;
|
3015
|
-
}
|
3016
|
-
|
3017
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
3018
|
-
if ( (handle_priv->interface_handle[i].dev_handle != 0)
|
3019
|
-
&& (handle_priv->interface_handle[i].dev_handle != INVALID_HANDLE_VALUE)
|
3020
|
-
&& (handle_priv->interface_handle[i].api_handle != 0)
|
3021
|
-
&& (handle_priv->interface_handle[i].api_handle != INVALID_HANDLE_VALUE)
|
3022
|
-
&& (priv->usb_interface[i].apib->id == api_id) ) {
|
3023
|
-
return i;
|
3024
|
-
}
|
3025
|
-
}
|
3026
|
-
return -1;
|
3027
|
-
}
|
3028
|
-
|
3029
|
-
/*
|
3030
|
-
* Lookup interface by endpoint address. -1 if not found
|
3031
|
-
*/
|
3032
|
-
static int interface_by_endpoint(struct windows_device_priv *priv,
|
3033
|
-
struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address)
|
3034
|
-
{
|
3035
|
-
int i, j;
|
3036
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
3037
|
-
if (handle_priv->interface_handle[i].api_handle == INVALID_HANDLE_VALUE)
|
3038
|
-
continue;
|
3039
|
-
if (handle_priv->interface_handle[i].api_handle == 0)
|
3040
|
-
continue;
|
3041
|
-
if (priv->usb_interface[i].endpoint == NULL)
|
3042
|
-
continue;
|
3043
|
-
for (j=0; j<priv->usb_interface[i].nb_endpoints; j++) {
|
3044
|
-
if (priv->usb_interface[i].endpoint[j] == endpoint_address) {
|
3045
|
-
return i;
|
3046
|
-
}
|
3047
|
-
}
|
3048
|
-
}
|
3049
|
-
return -1;
|
3050
|
-
}
|
3051
|
-
|
3052
|
-
static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
|
3053
|
-
{
|
3054
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
3055
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
3056
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
3057
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
3058
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(
|
3059
|
-
transfer->dev_handle);
|
3060
|
-
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer;
|
3061
|
-
ULONG size;
|
3062
|
-
HANDLE winusb_handle;
|
3063
|
-
int current_interface;
|
3064
|
-
struct winfd wfd;
|
3065
|
-
|
3066
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3067
|
-
|
3068
|
-
transfer_priv->pollable_fd = INVALID_WINFD;
|
3069
|
-
size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
|
3070
|
-
|
3071
|
-
if (size > MAX_CTRL_BUFFER_LENGTH)
|
3072
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3073
|
-
|
3074
|
-
current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX);
|
3075
|
-
if (current_interface < 0) {
|
3076
|
-
if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) {
|
3077
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3078
|
-
}
|
3079
|
-
}
|
3080
|
-
|
3081
|
-
usbi_dbg("will use interface %d", current_interface);
|
3082
|
-
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3083
|
-
|
3084
|
-
wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL);
|
3085
|
-
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
3086
|
-
if (wfd.fd < 0) {
|
3087
|
-
return LIBUSB_ERROR_NO_MEM;
|
3088
|
-
}
|
3089
|
-
|
3090
|
-
// Sending of set configuration control requests from WinUSB creates issues
|
3091
|
-
if ( ((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD)
|
3092
|
-
&& (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION) ) {
|
3093
|
-
if (setup->value != priv->active_config) {
|
3094
|
-
usbi_warn(ctx, "cannot set configuration other than the default one");
|
3095
|
-
usbi_free_fd(&wfd);
|
3096
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3097
|
-
}
|
3098
|
-
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
3099
|
-
wfd.overlapped->InternalHigh = 0;
|
3100
|
-
} else {
|
3101
|
-
if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) {
|
3102
|
-
if(GetLastError() != ERROR_IO_PENDING) {
|
3103
|
-
usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
|
3104
|
-
usbi_free_fd(&wfd);
|
3105
|
-
return LIBUSB_ERROR_IO;
|
3106
|
-
}
|
3107
|
-
} else {
|
3108
|
-
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
3109
|
-
wfd.overlapped->InternalHigh = (DWORD)size;
|
3110
|
-
}
|
3111
|
-
}
|
3112
|
-
|
3113
|
-
// Use priv_transfer to store data needed for async polling
|
3114
|
-
transfer_priv->pollable_fd = wfd;
|
3115
|
-
transfer_priv->interface_number = (uint8_t)current_interface;
|
3116
|
-
|
3117
|
-
return LIBUSB_SUCCESS;
|
3118
|
-
}
|
3119
|
-
|
3120
|
-
static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
3121
|
-
{
|
3122
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
3123
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3124
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3125
|
-
HANDLE winusb_handle;
|
3126
|
-
|
3127
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3128
|
-
|
3129
|
-
if (altsetting > 255) {
|
3130
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3131
|
-
}
|
3132
|
-
|
3133
|
-
winusb_handle = handle_priv->interface_handle[iface].api_handle;
|
3134
|
-
if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) {
|
3135
|
-
usbi_err(ctx, "interface must be claimed first");
|
3136
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3137
|
-
}
|
3138
|
-
|
3139
|
-
if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
|
3140
|
-
usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
|
3141
|
-
return LIBUSB_ERROR_IO;
|
3142
|
-
}
|
3143
|
-
|
3144
|
-
return LIBUSB_SUCCESS;
|
3145
|
-
}
|
3146
|
-
|
3147
|
-
static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
|
3148
|
-
{
|
3149
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
3150
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
3151
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
3152
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
3153
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
3154
|
-
HANDLE winusb_handle;
|
3155
|
-
bool ret;
|
3156
|
-
int current_interface;
|
3157
|
-
struct winfd wfd;
|
3158
|
-
|
3159
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3160
|
-
|
3161
|
-
transfer_priv->pollable_fd = INVALID_WINFD;
|
3162
|
-
|
3163
|
-
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
|
3164
|
-
if (current_interface < 0) {
|
3165
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
|
3166
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3167
|
-
}
|
3168
|
-
|
3169
|
-
usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
|
3170
|
-
|
3171
|
-
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3172
|
-
|
3173
|
-
wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
|
3174
|
-
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
3175
|
-
if (wfd.fd < 0) {
|
3176
|
-
return LIBUSB_ERROR_NO_MEM;
|
3177
|
-
}
|
3178
|
-
|
3179
|
-
if (IS_XFERIN(transfer)) {
|
3180
|
-
usbi_dbg("reading %d bytes", transfer->length);
|
3181
|
-
ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
|
3182
|
-
} else {
|
3183
|
-
usbi_dbg("writing %d bytes", transfer->length);
|
3184
|
-
ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
|
3185
|
-
}
|
3186
|
-
if (!ret) {
|
3187
|
-
if(GetLastError() != ERROR_IO_PENDING) {
|
3188
|
-
usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
|
3189
|
-
usbi_free_fd(&wfd);
|
3190
|
-
return LIBUSB_ERROR_IO;
|
3191
|
-
}
|
3192
|
-
} else {
|
3193
|
-
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
3194
|
-
wfd.overlapped->InternalHigh = (DWORD)transfer->length;
|
3195
|
-
}
|
3196
|
-
|
3197
|
-
transfer_priv->pollable_fd = wfd;
|
3198
|
-
transfer_priv->interface_number = (uint8_t)current_interface;
|
3199
|
-
|
3200
|
-
return LIBUSB_SUCCESS;
|
3201
|
-
}
|
3202
|
-
|
3203
|
-
static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
|
3204
|
-
{
|
3205
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
3206
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3207
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3208
|
-
HANDLE winusb_handle;
|
3209
|
-
int current_interface;
|
3210
|
-
|
3211
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3212
|
-
|
3213
|
-
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
|
3214
|
-
if (current_interface < 0) {
|
3215
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
|
3216
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3217
|
-
}
|
3218
|
-
|
3219
|
-
usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
|
3220
|
-
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3221
|
-
|
3222
|
-
if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
|
3223
|
-
usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
|
3224
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
3225
|
-
}
|
3226
|
-
|
3227
|
-
return LIBUSB_SUCCESS;
|
3228
|
-
}
|
3229
|
-
|
3230
|
-
/*
|
3231
|
-
* from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
|
3232
|
-
* through testing as well):
|
3233
|
-
* "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
|
3234
|
-
* the control transfer using CancelIo"
|
3235
|
-
*/
|
3236
|
-
static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
|
3237
|
-
{
|
3238
|
-
// Cancelling of the I/O is done in the parent
|
3239
|
-
return LIBUSB_SUCCESS;
|
3240
|
-
}
|
3241
|
-
|
3242
|
-
static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
|
3243
|
-
{
|
3244
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
3245
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
3246
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
3247
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
3248
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
3249
|
-
HANDLE winusb_handle;
|
3250
|
-
int current_interface;
|
3251
|
-
|
3252
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3253
|
-
|
3254
|
-
current_interface = transfer_priv->interface_number;
|
3255
|
-
if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
|
3256
|
-
usbi_err(ctx, "program assertion failed: invalid interface_number");
|
3257
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3258
|
-
}
|
3259
|
-
usbi_dbg("will use interface %d", current_interface);
|
3260
|
-
|
3261
|
-
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3262
|
-
|
3263
|
-
if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) {
|
3264
|
-
usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
|
3265
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
3266
|
-
}
|
3267
|
-
|
3268
|
-
return LIBUSB_SUCCESS;
|
3269
|
-
}
|
3270
|
-
|
3271
|
-
/*
|
3272
|
-
* from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper
|
3273
|
-
* (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx):
|
3274
|
-
* "WinUSB does not support host-initiated reset port and cycle port operations" and
|
3275
|
-
* IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the
|
3276
|
-
* IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
|
3277
|
-
* cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
|
3278
|
-
*/
|
3279
|
-
// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
|
3280
|
-
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
|
3281
|
-
{
|
3282
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
3283
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3284
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3285
|
-
struct winfd wfd;
|
3286
|
-
HANDLE winusb_handle;
|
3287
|
-
int i, j;
|
3288
|
-
|
3289
|
-
CHECK_WINUSBX_AVAILABLE(sub_api);
|
3290
|
-
|
3291
|
-
// Reset any available pipe (except control)
|
3292
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
3293
|
-
winusb_handle = handle_priv->interface_handle[i].api_handle;
|
3294
|
-
for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0;)
|
3295
|
-
{
|
3296
|
-
// Cancel any pollable I/O
|
3297
|
-
usbi_remove_pollfd(ctx, wfd.fd);
|
3298
|
-
usbi_free_fd(&wfd);
|
3299
|
-
wfd = handle_to_winfd(winusb_handle);
|
3300
|
-
}
|
3301
|
-
|
3302
|
-
if ( (winusb_handle != 0) && (winusb_handle != INVALID_HANDLE_VALUE)) {
|
3303
|
-
for (j=0; j<priv->usb_interface[i].nb_endpoints; j++) {
|
3304
|
-
usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
|
3305
|
-
if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) {
|
3306
|
-
usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
|
3307
|
-
priv->usb_interface[i].endpoint[j], windows_error_str(0));
|
3308
|
-
}
|
3309
|
-
// FlushPipe seems to fail on OUT pipes
|
3310
|
-
if (IS_EPIN(priv->usb_interface[i].endpoint[j])
|
3311
|
-
&& (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) ) {
|
3312
|
-
usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
|
3313
|
-
priv->usb_interface[i].endpoint[j], windows_error_str(0));
|
3314
|
-
}
|
3315
|
-
if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) {
|
3316
|
-
usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
|
3317
|
-
priv->usb_interface[i].endpoint[j], windows_error_str(0));
|
3318
|
-
}
|
3319
|
-
}
|
3320
|
-
}
|
3321
|
-
}
|
3322
|
-
|
3323
|
-
// libusbK & libusb0 have the ability to issue an actual device reset
|
3324
|
-
if (WinUSBX[sub_api].ResetDevice != NULL) {
|
3325
|
-
winusb_handle = handle_priv->interface_handle[0].api_handle;
|
3326
|
-
if ( (winusb_handle != 0) && (winusb_handle != INVALID_HANDLE_VALUE)) {
|
3327
|
-
WinUSBX[sub_api].ResetDevice(winusb_handle);
|
3328
|
-
}
|
3329
|
-
}
|
3330
|
-
return LIBUSB_SUCCESS;
|
3331
|
-
}
|
3332
|
-
|
3333
|
-
static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
|
3334
|
-
{
|
3335
|
-
itransfer->transferred += io_size;
|
3336
|
-
return LIBUSB_TRANSFER_COMPLETED;
|
3337
|
-
}
|
3338
|
-
|
3339
|
-
/*
|
3340
|
-
* Internal HID Support functions (from libusb-win32)
|
3341
|
-
* Note that functions that complete data transfer synchronously must return
|
3342
|
-
* LIBUSB_COMPLETED instead of LIBUSB_SUCCESS
|
3343
|
-
*/
|
3344
|
-
static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size_t *size);
|
3345
|
-
static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, size_t *size);
|
3346
|
-
|
3347
|
-
static int _hid_wcslen(WCHAR *str)
|
3348
|
-
{
|
3349
|
-
int i = 0;
|
3350
|
-
while (str[i] && (str[i] != 0x409)) {
|
3351
|
-
i++;
|
3352
|
-
}
|
3353
|
-
return i;
|
3354
|
-
}
|
3355
|
-
|
3356
|
-
static int _hid_get_device_descriptor(struct hid_device_priv* dev, void *data, size_t *size)
|
3357
|
-
{
|
3358
|
-
struct libusb_device_descriptor d;
|
3359
|
-
|
3360
|
-
d.bLength = LIBUSB_DT_DEVICE_SIZE;
|
3361
|
-
d.bDescriptorType = LIBUSB_DT_DEVICE;
|
3362
|
-
d.bcdUSB = 0x0200; /* 2.00 */
|
3363
|
-
d.bDeviceClass = 0;
|
3364
|
-
d.bDeviceSubClass = 0;
|
3365
|
-
d.bDeviceProtocol = 0;
|
3366
|
-
d.bMaxPacketSize0 = 64; /* fix this! */
|
3367
|
-
d.idVendor = (uint16_t)dev->vid;
|
3368
|
-
d.idProduct = (uint16_t)dev->pid;
|
3369
|
-
d.bcdDevice = 0x0100;
|
3370
|
-
d.iManufacturer = dev->string_index[0];
|
3371
|
-
d.iProduct = dev->string_index[1];
|
3372
|
-
d.iSerialNumber = dev->string_index[2];
|
3373
|
-
d.bNumConfigurations = 1;
|
3374
|
-
|
3375
|
-
if (*size > LIBUSB_DT_DEVICE_SIZE)
|
3376
|
-
*size = LIBUSB_DT_DEVICE_SIZE;
|
3377
|
-
memcpy(data, &d, *size);
|
3378
|
-
return LIBUSB_COMPLETED;
|
3379
|
-
}
|
3380
|
-
|
3381
|
-
static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, size_t *size)
|
3382
|
-
{
|
3383
|
-
char num_endpoints = 0;
|
3384
|
-
size_t config_total_len = 0;
|
3385
|
-
char tmp[HID_MAX_CONFIG_DESC_SIZE];
|
3386
|
-
struct libusb_config_descriptor *cd;
|
3387
|
-
struct libusb_interface_descriptor *id;
|
3388
|
-
struct libusb_hid_descriptor *hd;
|
3389
|
-
struct libusb_endpoint_descriptor *ed;
|
3390
|
-
size_t tmp_size;
|
3391
|
-
|
3392
|
-
if (dev->input_report_size)
|
3393
|
-
num_endpoints++;
|
3394
|
-
if (dev->output_report_size)
|
3395
|
-
num_endpoints++;
|
3396
|
-
|
3397
|
-
config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
|
3398
|
-
+ LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE;
|
3399
|
-
|
3400
|
-
|
3401
|
-
cd = (struct libusb_config_descriptor *)tmp;
|
3402
|
-
id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE);
|
3403
|
-
hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
|
3404
|
-
+ LIBUSB_DT_INTERFACE_SIZE);
|
3405
|
-
ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
|
3406
|
-
+ LIBUSB_DT_INTERFACE_SIZE
|
3407
|
-
+ LIBUSB_DT_HID_SIZE);
|
3408
|
-
|
3409
|
-
cd->bLength = LIBUSB_DT_CONFIG_SIZE;
|
3410
|
-
cd->bDescriptorType = LIBUSB_DT_CONFIG;
|
3411
|
-
cd->wTotalLength = (uint16_t) config_total_len;
|
3412
|
-
cd->bNumInterfaces = 1;
|
3413
|
-
cd->bConfigurationValue = 1;
|
3414
|
-
cd->iConfiguration = 0;
|
3415
|
-
cd->bmAttributes = 1 << 7; /* bus powered */
|
3416
|
-
cd->MaxPower = 50;
|
3417
|
-
|
3418
|
-
id->bLength = LIBUSB_DT_INTERFACE_SIZE;
|
3419
|
-
id->bDescriptorType = LIBUSB_DT_INTERFACE;
|
3420
|
-
id->bInterfaceNumber = 0;
|
3421
|
-
id->bAlternateSetting = 0;
|
3422
|
-
id->bNumEndpoints = num_endpoints;
|
3423
|
-
id->bInterfaceClass = 3;
|
3424
|
-
id->bInterfaceSubClass = 0;
|
3425
|
-
id->bInterfaceProtocol = 0;
|
3426
|
-
id->iInterface = 0;
|
3427
|
-
|
3428
|
-
tmp_size = LIBUSB_DT_HID_SIZE;
|
3429
|
-
_hid_get_hid_descriptor(dev, hd, &tmp_size);
|
3430
|
-
|
3431
|
-
if (dev->input_report_size) {
|
3432
|
-
ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
|
3433
|
-
ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
|
3434
|
-
ed->bEndpointAddress = HID_IN_EP;
|
3435
|
-
ed->bmAttributes = 3;
|
3436
|
-
ed->wMaxPacketSize = dev->input_report_size - 1;
|
3437
|
-
ed->bInterval = 10;
|
3438
|
-
ed = (struct libusb_endpoint_descriptor *)((char*)ed + LIBUSB_DT_ENDPOINT_SIZE);
|
3439
|
-
}
|
3440
|
-
|
3441
|
-
if (dev->output_report_size) {
|
3442
|
-
ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
|
3443
|
-
ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
|
3444
|
-
ed->bEndpointAddress = HID_OUT_EP;
|
3445
|
-
ed->bmAttributes = 3;
|
3446
|
-
ed->wMaxPacketSize = dev->output_report_size - 1;
|
3447
|
-
ed->bInterval = 10;
|
3448
|
-
}
|
3449
|
-
|
3450
|
-
if (*size > config_total_len)
|
3451
|
-
*size = config_total_len;
|
3452
|
-
memcpy(data, tmp, *size);
|
3453
|
-
return LIBUSB_COMPLETED;
|
3454
|
-
}
|
3455
|
-
|
3456
|
-
static int _hid_get_string_descriptor(struct hid_device_priv* dev, int _index,
|
3457
|
-
void *data, size_t *size)
|
3458
|
-
{
|
3459
|
-
void *tmp = NULL;
|
3460
|
-
size_t tmp_size = 0;
|
3461
|
-
int i;
|
3462
|
-
|
3463
|
-
/* language ID, EN-US */
|
3464
|
-
char string_langid[] = {
|
3465
|
-
0x09,
|
3466
|
-
0x04
|
3467
|
-
};
|
3468
|
-
|
3469
|
-
if ((*size < 2) || (*size > 255)) {
|
3470
|
-
return LIBUSB_ERROR_OVERFLOW;
|
3471
|
-
}
|
3472
|
-
|
3473
|
-
if (_index == 0) {
|
3474
|
-
tmp = string_langid;
|
3475
|
-
tmp_size = sizeof(string_langid)+2;
|
3476
|
-
} else {
|
3477
|
-
for (i=0; i<3; i++) {
|
3478
|
-
if (_index == (dev->string_index[i])) {
|
3479
|
-
tmp = dev->string[i];
|
3480
|
-
tmp_size = (_hid_wcslen(dev->string[i])+1) * sizeof(WCHAR);
|
3481
|
-
break;
|
3482
|
-
}
|
3483
|
-
}
|
3484
|
-
if (i == 3) { // not found
|
3485
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3486
|
-
}
|
3487
|
-
}
|
3488
|
-
|
3489
|
-
if(!tmp_size) {
|
3490
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3491
|
-
}
|
3492
|
-
|
3493
|
-
if (tmp_size < *size) {
|
3494
|
-
*size = tmp_size;
|
3495
|
-
}
|
3496
|
-
// 2 byte header
|
3497
|
-
((uint8_t*)data)[0] = (uint8_t)*size;
|
3498
|
-
((uint8_t*)data)[1] = LIBUSB_DT_STRING;
|
3499
|
-
memcpy((uint8_t*)data+2, tmp, *size-2);
|
3500
|
-
return LIBUSB_COMPLETED;
|
3501
|
-
}
|
3502
|
-
|
3503
|
-
static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size_t *size)
|
3504
|
-
{
|
3505
|
-
struct libusb_hid_descriptor d;
|
3506
|
-
uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
|
3507
|
-
size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
|
3508
|
-
|
3509
|
-
_hid_get_report_descriptor(dev, tmp, &report_len);
|
3510
|
-
|
3511
|
-
d.bLength = LIBUSB_DT_HID_SIZE;
|
3512
|
-
d.bDescriptorType = LIBUSB_DT_HID;
|
3513
|
-
d.bcdHID = 0x0110; /* 1.10 */
|
3514
|
-
d.bCountryCode = 0;
|
3515
|
-
d.bNumDescriptors = 1;
|
3516
|
-
d.bClassDescriptorType = LIBUSB_DT_REPORT;
|
3517
|
-
d.wClassDescriptorLength = (uint16_t)report_len;
|
3518
|
-
|
3519
|
-
if (*size > LIBUSB_DT_HID_SIZE)
|
3520
|
-
*size = LIBUSB_DT_HID_SIZE;
|
3521
|
-
memcpy(data, &d, *size);
|
3522
|
-
return LIBUSB_COMPLETED;
|
3523
|
-
}
|
3524
|
-
|
3525
|
-
static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, size_t *size)
|
3526
|
-
{
|
3527
|
-
uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
|
3528
|
-
size_t i = 0;
|
3529
|
-
|
3530
|
-
/* usage page (0xFFA0 == vendor defined) */
|
3531
|
-
d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF;
|
3532
|
-
/* usage (vendor defined) */
|
3533
|
-
d[i++] = 0x09; d[i++] = 0x01;
|
3534
|
-
/* start collection (application) */
|
3535
|
-
d[i++] = 0xA1; d[i++] = 0x01;
|
3536
|
-
/* input report */
|
3537
|
-
if (dev->input_report_size) {
|
3538
|
-
/* usage (vendor defined) */
|
3539
|
-
d[i++] = 0x09; d[i++] = 0x01;
|
3540
|
-
/* logical minimum (0) */
|
3541
|
-
d[i++] = 0x15; d[i++] = 0x00;
|
3542
|
-
/* logical maximum (255) */
|
3543
|
-
d[i++] = 0x25; d[i++] = 0xFF;
|
3544
|
-
/* report size (8 bits) */
|
3545
|
-
d[i++] = 0x75; d[i++] = 0x08;
|
3546
|
-
/* report count */
|
3547
|
-
d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
|
3548
|
-
/* input (data, variable, absolute) */
|
3549
|
-
d[i++] = 0x81; d[i++] = 0x00;
|
3550
|
-
}
|
3551
|
-
/* output report */
|
3552
|
-
if (dev->output_report_size) {
|
3553
|
-
/* usage (vendor defined) */
|
3554
|
-
d[i++] = 0x09; d[i++] = 0x02;
|
3555
|
-
/* logical minimum (0) */
|
3556
|
-
d[i++] = 0x15; d[i++] = 0x00;
|
3557
|
-
/* logical maximum (255) */
|
3558
|
-
d[i++] = 0x25; d[i++] = 0xFF;
|
3559
|
-
/* report size (8 bits) */
|
3560
|
-
d[i++] = 0x75; d[i++] = 0x08;
|
3561
|
-
/* report count */
|
3562
|
-
d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
|
3563
|
-
/* output (data, variable, absolute) */
|
3564
|
-
d[i++] = 0x91; d[i++] = 0x00;
|
3565
|
-
}
|
3566
|
-
/* feature report */
|
3567
|
-
if (dev->feature_report_size) {
|
3568
|
-
/* usage (vendor defined) */
|
3569
|
-
d[i++] = 0x09; d[i++] = 0x03;
|
3570
|
-
/* logical minimum (0) */
|
3571
|
-
d[i++] = 0x15; d[i++] = 0x00;
|
3572
|
-
/* logical maximum (255) */
|
3573
|
-
d[i++] = 0x25; d[i++] = 0xFF;
|
3574
|
-
/* report size (8 bits) */
|
3575
|
-
d[i++] = 0x75; d[i++] = 0x08;
|
3576
|
-
/* report count */
|
3577
|
-
d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
|
3578
|
-
/* feature (data, variable, absolute) */
|
3579
|
-
d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
|
3580
|
-
}
|
3581
|
-
|
3582
|
-
/* end collection */
|
3583
|
-
d[i++] = 0xC0;
|
3584
|
-
|
3585
|
-
if (*size > i)
|
3586
|
-
*size = i;
|
3587
|
-
memcpy(data, d, *size);
|
3588
|
-
return LIBUSB_COMPLETED;
|
3589
|
-
}
|
3590
|
-
|
3591
|
-
static int _hid_get_descriptor(struct hid_device_priv* dev, HANDLE hid_handle, int recipient,
|
3592
|
-
int type, int _index, void *data, size_t *size)
|
3593
|
-
{
|
3594
|
-
switch(type) {
|
3595
|
-
case LIBUSB_DT_DEVICE:
|
3596
|
-
usbi_dbg("LIBUSB_DT_DEVICE");
|
3597
|
-
return _hid_get_device_descriptor(dev, data, size);
|
3598
|
-
case LIBUSB_DT_CONFIG:
|
3599
|
-
usbi_dbg("LIBUSB_DT_CONFIG");
|
3600
|
-
if (!_index)
|
3601
|
-
return _hid_get_config_descriptor(dev, data, size);
|
3602
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3603
|
-
case LIBUSB_DT_STRING:
|
3604
|
-
usbi_dbg("LIBUSB_DT_STRING");
|
3605
|
-
return _hid_get_string_descriptor(dev, _index, data, size);
|
3606
|
-
case LIBUSB_DT_HID:
|
3607
|
-
usbi_dbg("LIBUSB_DT_HID");
|
3608
|
-
if (!_index)
|
3609
|
-
return _hid_get_hid_descriptor(dev, data, size);
|
3610
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3611
|
-
case LIBUSB_DT_REPORT:
|
3612
|
-
usbi_dbg("LIBUSB_DT_REPORT");
|
3613
|
-
if (!_index)
|
3614
|
-
return _hid_get_report_descriptor(dev, data, size);
|
3615
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3616
|
-
case LIBUSB_DT_PHYSICAL:
|
3617
|
-
usbi_dbg("LIBUSB_DT_PHYSICAL");
|
3618
|
-
if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
|
3619
|
-
return LIBUSB_COMPLETED;
|
3620
|
-
return LIBUSB_ERROR_OTHER;
|
3621
|
-
}
|
3622
|
-
usbi_dbg("unsupported");
|
3623
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
3624
|
-
}
|
3625
|
-
|
3626
|
-
static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data,
|
3627
|
-
struct windows_transfer_priv *tp, size_t *size, OVERLAPPED* overlapped,
|
3628
|
-
int report_type)
|
3629
|
-
{
|
3630
|
-
uint8_t *buf;
|
3631
|
-
DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
|
3632
|
-
int r = LIBUSB_SUCCESS;
|
3633
|
-
|
3634
|
-
if (tp->hid_buffer != NULL) {
|
3635
|
-
usbi_dbg("program assertion failed: hid_buffer is not NULL");
|
3636
|
-
}
|
3637
|
-
|
3638
|
-
if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
|
3639
|
-
usbi_dbg("invalid size (%d)", *size);
|
3640
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3641
|
-
}
|
3642
|
-
|
3643
|
-
switch (report_type) {
|
3644
|
-
case HID_REPORT_TYPE_INPUT:
|
3645
|
-
ioctl_code = IOCTL_HID_GET_INPUT_REPORT;
|
3646
|
-
break;
|
3647
|
-
case HID_REPORT_TYPE_FEATURE:
|
3648
|
-
ioctl_code = IOCTL_HID_GET_FEATURE;
|
3649
|
-
break;
|
3650
|
-
default:
|
3651
|
-
usbi_dbg("unknown HID report type %d", report_type);
|
3652
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3653
|
-
}
|
3654
|
-
|
3655
|
-
// Add a trailing byte to detect overflows
|
3656
|
-
buf = (uint8_t*)calloc(expected_size+1, 1);
|
3657
|
-
if (buf == NULL) {
|
3658
|
-
return LIBUSB_ERROR_NO_MEM;
|
3659
|
-
}
|
3660
|
-
buf[0] = (uint8_t)id; // Must be set always
|
3661
|
-
usbi_dbg("report ID: 0x%02X", buf[0]);
|
3662
|
-
|
3663
|
-
tp->hid_expected_size = expected_size;
|
3664
|
-
read_size = expected_size;
|
3665
|
-
|
3666
|
-
// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
|
3667
|
-
if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size+1,
|
3668
|
-
buf, expected_size+1, &read_size, overlapped)) {
|
3669
|
-
if (GetLastError() != ERROR_IO_PENDING) {
|
3670
|
-
usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
|
3671
|
-
safe_free(buf);
|
3672
|
-
return LIBUSB_ERROR_IO;
|
3673
|
-
}
|
3674
|
-
// Asynchronous wait
|
3675
|
-
tp->hid_buffer = buf;
|
3676
|
-
tp->hid_dest = (uint8_t*)data; // copy dest, as not necessarily the start of the transfer buffer
|
3677
|
-
return LIBUSB_SUCCESS;
|
3678
|
-
}
|
3679
|
-
|
3680
|
-
// Transfer completed synchronously => copy and discard extra buffer
|
3681
|
-
if (read_size == 0) {
|
3682
|
-
usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
|
3683
|
-
*size = 0;
|
3684
|
-
} else {
|
3685
|
-
if (buf[0] != id) {
|
3686
|
-
usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
|
3687
|
-
}
|
3688
|
-
if ((size_t)read_size > expected_size) {
|
3689
|
-
r = LIBUSB_ERROR_OVERFLOW;
|
3690
|
-
usbi_dbg("OVERFLOW!");
|
3691
|
-
} else {
|
3692
|
-
r = LIBUSB_COMPLETED;
|
3693
|
-
}
|
3694
|
-
|
3695
|
-
*size = MIN((size_t)read_size, *size);
|
3696
|
-
if (id == 0) {
|
3697
|
-
// Discard report ID
|
3698
|
-
memcpy(data, buf+1, *size);
|
3699
|
-
} else {
|
3700
|
-
memcpy(data, buf, *size);
|
3701
|
-
}
|
3702
|
-
}
|
3703
|
-
safe_free(buf);
|
3704
|
-
return r;
|
3705
|
-
}
|
3706
|
-
|
3707
|
-
static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data,
|
3708
|
-
struct windows_transfer_priv *tp, size_t *size, OVERLAPPED* overlapped,
|
3709
|
-
int report_type)
|
3710
|
-
{
|
3711
|
-
uint8_t *buf = NULL;
|
3712
|
-
DWORD ioctl_code, write_size= (DWORD)*size;
|
3713
|
-
|
3714
|
-
if (tp->hid_buffer != NULL) {
|
3715
|
-
usbi_dbg("program assertion failed: hid_buffer is not NULL");
|
3716
|
-
}
|
3717
|
-
|
3718
|
-
if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
|
3719
|
-
usbi_dbg("invalid size (%d)", *size);
|
3720
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3721
|
-
}
|
3722
|
-
|
3723
|
-
switch (report_type) {
|
3724
|
-
case HID_REPORT_TYPE_OUTPUT:
|
3725
|
-
ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT;
|
3726
|
-
break;
|
3727
|
-
case HID_REPORT_TYPE_FEATURE:
|
3728
|
-
ioctl_code = IOCTL_HID_SET_FEATURE;
|
3729
|
-
break;
|
3730
|
-
default:
|
3731
|
-
usbi_dbg("unknown HID report type %d", report_type);
|
3732
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3733
|
-
}
|
3734
|
-
|
3735
|
-
usbi_dbg("report ID: 0x%02X", id);
|
3736
|
-
// When report IDs are not used (i.e. when id == 0), we must add
|
3737
|
-
// a null report ID. Otherwise, we just use original data buffer
|
3738
|
-
if (id == 0) {
|
3739
|
-
write_size++;
|
3740
|
-
}
|
3741
|
-
buf = (uint8_t*) malloc(write_size);
|
3742
|
-
if (buf == NULL) {
|
3743
|
-
return LIBUSB_ERROR_NO_MEM;
|
3744
|
-
}
|
3745
|
-
if (id == 0) {
|
3746
|
-
buf[0] = 0;
|
3747
|
-
memcpy(buf + 1, data, *size);
|
3748
|
-
} else {
|
3749
|
-
// This seems like a waste, but if we don't duplicate the
|
3750
|
-
// data, we'll get issues when freeing hid_buffer
|
3751
|
-
memcpy(buf, data, *size);
|
3752
|
-
if (buf[0] != id) {
|
3753
|
-
usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
|
3754
|
-
}
|
3755
|
-
}
|
3756
|
-
|
3757
|
-
// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
|
3758
|
-
if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
|
3759
|
-
buf, write_size, &write_size, overlapped)) {
|
3760
|
-
if (GetLastError() != ERROR_IO_PENDING) {
|
3761
|
-
usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
|
3762
|
-
safe_free(buf);
|
3763
|
-
return LIBUSB_ERROR_IO;
|
3764
|
-
}
|
3765
|
-
tp->hid_buffer = buf;
|
3766
|
-
tp->hid_dest = NULL;
|
3767
|
-
return LIBUSB_SUCCESS;
|
3768
|
-
}
|
3769
|
-
|
3770
|
-
// Transfer completed synchronously
|
3771
|
-
*size = write_size;
|
3772
|
-
if (write_size == 0) {
|
3773
|
-
usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
|
3774
|
-
}
|
3775
|
-
safe_free(buf);
|
3776
|
-
return LIBUSB_COMPLETED;
|
3777
|
-
}
|
3778
|
-
|
3779
|
-
static int _hid_class_request(struct hid_device_priv* dev, HANDLE hid_handle, int request_type,
|
3780
|
-
int request, int value, int _index, void *data, struct windows_transfer_priv *tp,
|
3781
|
-
size_t *size, OVERLAPPED* overlapped)
|
3782
|
-
{
|
3783
|
-
int report_type = (value >> 8) & 0xFF;
|
3784
|
-
int report_id = value & 0xFF;
|
3785
|
-
|
3786
|
-
if ( (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
|
3787
|
-
&& (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE) )
|
3788
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3789
|
-
|
3790
|
-
if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT)
|
3791
|
-
return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
|
3792
|
-
|
3793
|
-
if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT)
|
3794
|
-
return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
|
3795
|
-
|
3796
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
3797
|
-
}
|
3798
|
-
|
3799
|
-
|
3800
|
-
/*
|
3801
|
-
* HID API functions
|
3802
|
-
*/
|
3803
|
-
static int hid_init(int sub_api, struct libusb_context *ctx)
|
3804
|
-
{
|
3805
|
-
DLL_LOAD(hid.dll, HidD_GetAttributes, TRUE);
|
3806
|
-
DLL_LOAD(hid.dll, HidD_GetHidGuid, TRUE);
|
3807
|
-
DLL_LOAD(hid.dll, HidD_GetPreparsedData, TRUE);
|
3808
|
-
DLL_LOAD(hid.dll, HidD_FreePreparsedData, TRUE);
|
3809
|
-
DLL_LOAD(hid.dll, HidD_GetManufacturerString, TRUE);
|
3810
|
-
DLL_LOAD(hid.dll, HidD_GetProductString, TRUE);
|
3811
|
-
DLL_LOAD(hid.dll, HidD_GetSerialNumberString, TRUE);
|
3812
|
-
DLL_LOAD(hid.dll, HidP_GetCaps, TRUE);
|
3813
|
-
DLL_LOAD(hid.dll, HidD_SetNumInputBuffers, TRUE);
|
3814
|
-
DLL_LOAD(hid.dll, HidD_SetFeature, TRUE);
|
3815
|
-
DLL_LOAD(hid.dll, HidD_GetFeature, TRUE);
|
3816
|
-
DLL_LOAD(hid.dll, HidD_GetPhysicalDescriptor, TRUE);
|
3817
|
-
DLL_LOAD(hid.dll, HidD_GetInputReport, FALSE);
|
3818
|
-
DLL_LOAD(hid.dll, HidD_SetOutputReport, FALSE);
|
3819
|
-
DLL_LOAD(hid.dll, HidD_FlushQueue, TRUE);
|
3820
|
-
DLL_LOAD(hid.dll, HidP_GetValueCaps, TRUE);
|
3821
|
-
|
3822
|
-
api_hid_available = true;
|
3823
|
-
return LIBUSB_SUCCESS;
|
3824
|
-
}
|
3825
|
-
|
3826
|
-
static int hid_exit(int sub_api)
|
3827
|
-
{
|
3828
|
-
return LIBUSB_SUCCESS;
|
3829
|
-
}
|
3830
|
-
|
3831
|
-
// NB: open and close must ensure that they only handle interface of
|
3832
|
-
// the right API type, as these functions can be called wholesale from
|
3833
|
-
// composite_open(), with interfaces belonging to different APIs
|
3834
|
-
static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
|
3835
|
-
{
|
3836
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
3837
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3838
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3839
|
-
|
3840
|
-
HIDD_ATTRIBUTES hid_attributes;
|
3841
|
-
PHIDP_PREPARSED_DATA preparsed_data = NULL;
|
3842
|
-
HIDP_CAPS capabilities;
|
3843
|
-
HIDP_VALUE_CAPS *value_caps;
|
3844
|
-
|
3845
|
-
HANDLE hid_handle = INVALID_HANDLE_VALUE;
|
3846
|
-
int i, j;
|
3847
|
-
// report IDs handling
|
3848
|
-
ULONG size[3];
|
3849
|
-
const char* type[3] = {"input", "output", "feature"};
|
3850
|
-
int nb_ids[2]; // zero and nonzero report IDs
|
3851
|
-
|
3852
|
-
CHECK_HID_AVAILABLE;
|
3853
|
-
if (priv->hid == NULL) {
|
3854
|
-
usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
|
3855
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
3856
|
-
}
|
3857
|
-
|
3858
|
-
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
3859
|
-
if ( (priv->usb_interface[i].path != NULL)
|
3860
|
-
&& (priv->usb_interface[i].apib->id == USB_API_HID) ) {
|
3861
|
-
hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
|
3862
|
-
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
3863
|
-
/*
|
3864
|
-
* http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
|
3865
|
-
* "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
|
3866
|
-
* keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not
|
3867
|
-
* requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and
|
3868
|
-
* HidD_GetFeature (if the device supports Feature reports)."
|
3869
|
-
*/
|
3870
|
-
if (hid_handle == INVALID_HANDLE_VALUE) {
|
3871
|
-
usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
|
3872
|
-
hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
|
3873
|
-
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
3874
|
-
if (hid_handle == INVALID_HANDLE_VALUE) {
|
3875
|
-
usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
|
3876
|
-
switch(GetLastError()) {
|
3877
|
-
case ERROR_FILE_NOT_FOUND: // The device was disconnected
|
3878
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
3879
|
-
case ERROR_ACCESS_DENIED:
|
3880
|
-
return LIBUSB_ERROR_ACCESS;
|
3881
|
-
default:
|
3882
|
-
return LIBUSB_ERROR_IO;
|
3883
|
-
}
|
3884
|
-
}
|
3885
|
-
priv->usb_interface[i].restricted_functionality = true;
|
3886
|
-
}
|
3887
|
-
handle_priv->interface_handle[i].api_handle = hid_handle;
|
3888
|
-
}
|
3889
|
-
}
|
3890
|
-
|
3891
|
-
hid_attributes.Size = sizeof(hid_attributes);
|
3892
|
-
do {
|
3893
|
-
if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
|
3894
|
-
usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
|
3895
|
-
break;
|
3896
|
-
}
|
3897
|
-
|
3898
|
-
priv->hid->vid = hid_attributes.VendorID;
|
3899
|
-
priv->hid->pid = hid_attributes.ProductID;
|
3900
|
-
|
3901
|
-
// Set the maximum available input buffer size
|
3902
|
-
for (i=32; HidD_SetNumInputBuffers(hid_handle, i); i*=2);
|
3903
|
-
usbi_dbg("set maximum input buffer size to %d", i/2);
|
3904
|
-
|
3905
|
-
// Get the maximum input and output report size
|
3906
|
-
if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
|
3907
|
-
usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
|
3908
|
-
break;
|
3909
|
-
}
|
3910
|
-
if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
|
3911
|
-
usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
|
3912
|
-
break;
|
3913
|
-
}
|
3914
|
-
|
3915
|
-
// Find out if interrupt will need report IDs
|
3916
|
-
size[0] = capabilities.NumberInputValueCaps;
|
3917
|
-
size[1] = capabilities.NumberOutputValueCaps;
|
3918
|
-
size[2] = capabilities.NumberFeatureValueCaps;
|
3919
|
-
for (j=HidP_Input; j<=HidP_Feature; j++) {
|
3920
|
-
usbi_dbg("%d HID %s report value(s) found", size[j], type[j]);
|
3921
|
-
priv->hid->uses_report_ids[j] = false;
|
3922
|
-
if (size[j] > 0) {
|
3923
|
-
value_caps = (HIDP_VALUE_CAPS*) calloc(size[j], sizeof(HIDP_VALUE_CAPS));
|
3924
|
-
if ( (value_caps != NULL)
|
3925
|
-
&& (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS)
|
3926
|
-
&& (size[j] >= 1) ) {
|
3927
|
-
nb_ids[0] = 0;
|
3928
|
-
nb_ids[1] = 0;
|
3929
|
-
for (i=0; i<(int)size[j]; i++) {
|
3930
|
-
usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID);
|
3931
|
-
if (value_caps[i].ReportID != 0) {
|
3932
|
-
nb_ids[1]++;
|
3933
|
-
} else {
|
3934
|
-
nb_ids[0]++;
|
3935
|
-
}
|
3936
|
-
}
|
3937
|
-
if (nb_ids[1] != 0) {
|
3938
|
-
if (nb_ids[0] != 0) {
|
3939
|
-
usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
|
3940
|
-
type[j]);
|
3941
|
-
}
|
3942
|
-
priv->hid->uses_report_ids[j] = true;
|
3943
|
-
}
|
3944
|
-
} else {
|
3945
|
-
usbi_warn(ctx, " could not process %s report IDs", type[j]);
|
3946
|
-
}
|
3947
|
-
safe_free(value_caps);
|
3948
|
-
}
|
3949
|
-
}
|
3950
|
-
|
3951
|
-
// Set the report sizes
|
3952
|
-
priv->hid->input_report_size = capabilities.InputReportByteLength;
|
3953
|
-
priv->hid->output_report_size = capabilities.OutputReportByteLength;
|
3954
|
-
priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
|
3955
|
-
|
3956
|
-
// Fetch string descriptors
|
3957
|
-
priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer;
|
3958
|
-
if (priv->hid->string_index[0] != 0) {
|
3959
|
-
HidD_GetManufacturerString(hid_handle, priv->hid->string[0],
|
3960
|
-
sizeof(priv->hid->string[0]));
|
3961
|
-
} else {
|
3962
|
-
priv->hid->string[0][0] = 0;
|
3963
|
-
}
|
3964
|
-
priv->hid->string_index[1] = priv->dev_descriptor.iProduct;
|
3965
|
-
if (priv->hid->string_index[1] != 0) {
|
3966
|
-
HidD_GetProductString(hid_handle, priv->hid->string[1],
|
3967
|
-
sizeof(priv->hid->string[1]));
|
3968
|
-
} else {
|
3969
|
-
priv->hid->string[1][0] = 0;
|
3970
|
-
}
|
3971
|
-
priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber;
|
3972
|
-
if (priv->hid->string_index[2] != 0) {
|
3973
|
-
HidD_GetSerialNumberString(hid_handle, priv->hid->string[2],
|
3974
|
-
sizeof(priv->hid->string[2]));
|
3975
|
-
} else {
|
3976
|
-
priv->hid->string[2][0] = 0;
|
3977
|
-
}
|
3978
|
-
} while(0);
|
3979
|
-
|
3980
|
-
if (preparsed_data) {
|
3981
|
-
HidD_FreePreparsedData(preparsed_data);
|
3982
|
-
}
|
3983
|
-
|
3984
|
-
return LIBUSB_SUCCESS;
|
3985
|
-
}
|
3986
|
-
|
3987
|
-
static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
|
3988
|
-
{
|
3989
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
3990
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
3991
|
-
HANDLE file_handle;
|
3992
|
-
int i;
|
3993
|
-
|
3994
|
-
if (!api_hid_available)
|
3995
|
-
return;
|
3996
|
-
|
3997
|
-
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
3998
|
-
if (priv->usb_interface[i].apib->id == USB_API_HID) {
|
3999
|
-
file_handle = handle_priv->interface_handle[i].api_handle;
|
4000
|
-
if ( (file_handle != 0) && (file_handle != INVALID_HANDLE_VALUE)) {
|
4001
|
-
CloseHandle(file_handle);
|
4002
|
-
}
|
4003
|
-
}
|
4004
|
-
}
|
4005
|
-
}
|
4006
|
-
|
4007
|
-
static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
4008
|
-
{
|
4009
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
4010
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4011
|
-
|
4012
|
-
CHECK_HID_AVAILABLE;
|
4013
|
-
|
4014
|
-
// NB: Disconnection detection is not possible in this function
|
4015
|
-
if (priv->usb_interface[iface].path == NULL) {
|
4016
|
-
return LIBUSB_ERROR_NOT_FOUND; // invalid iface
|
4017
|
-
}
|
4018
|
-
|
4019
|
-
// We use dev_handle as a flag for interface claimed
|
4020
|
-
if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED) {
|
4021
|
-
return LIBUSB_ERROR_BUSY; // already claimed
|
4022
|
-
}
|
4023
|
-
|
4024
|
-
handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
|
4025
|
-
|
4026
|
-
usbi_dbg("claimed interface %d", iface);
|
4027
|
-
handle_priv->active_interface = iface;
|
4028
|
-
|
4029
|
-
return LIBUSB_SUCCESS;
|
4030
|
-
}
|
4031
|
-
|
4032
|
-
static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
4033
|
-
{
|
4034
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
4035
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4036
|
-
|
4037
|
-
CHECK_HID_AVAILABLE;
|
4038
|
-
|
4039
|
-
if (priv->usb_interface[iface].path == NULL) {
|
4040
|
-
return LIBUSB_ERROR_NOT_FOUND; // invalid iface
|
4041
|
-
}
|
4042
|
-
|
4043
|
-
if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED) {
|
4044
|
-
return LIBUSB_ERROR_NOT_FOUND; // invalid iface
|
4045
|
-
}
|
4046
|
-
|
4047
|
-
handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE;
|
4048
|
-
|
4049
|
-
return LIBUSB_SUCCESS;
|
4050
|
-
}
|
4051
|
-
|
4052
|
-
static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
4053
|
-
{
|
4054
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
4055
|
-
|
4056
|
-
CHECK_HID_AVAILABLE;
|
4057
|
-
|
4058
|
-
if (altsetting > 255) {
|
4059
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
4060
|
-
}
|
4061
|
-
|
4062
|
-
if (altsetting != 0) {
|
4063
|
-
usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
|
4064
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
4065
|
-
}
|
4066
|
-
|
4067
|
-
return LIBUSB_SUCCESS;
|
4068
|
-
}
|
4069
|
-
|
4070
|
-
static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
|
4071
|
-
{
|
4072
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4073
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
4074
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
4075
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4076
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4077
|
-
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer;
|
4078
|
-
HANDLE hid_handle;
|
4079
|
-
struct winfd wfd;
|
4080
|
-
int current_interface, config;
|
4081
|
-
size_t size;
|
4082
|
-
int r = LIBUSB_ERROR_INVALID_PARAM;
|
4083
|
-
|
4084
|
-
CHECK_HID_AVAILABLE;
|
4085
|
-
|
4086
|
-
transfer_priv->pollable_fd = INVALID_WINFD;
|
4087
|
-
safe_free(transfer_priv->hid_buffer);
|
4088
|
-
transfer_priv->hid_dest = NULL;
|
4089
|
-
size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
|
4090
|
-
|
4091
|
-
if (size > MAX_CTRL_BUFFER_LENGTH) {
|
4092
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
4093
|
-
}
|
4094
|
-
|
4095
|
-
current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
|
4096
|
-
if (current_interface < 0) {
|
4097
|
-
if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) {
|
4098
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4099
|
-
}
|
4100
|
-
}
|
4101
|
-
|
4102
|
-
usbi_dbg("will use interface %d", current_interface);
|
4103
|
-
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
4104
|
-
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
4105
|
-
wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
|
4106
|
-
if (wfd.fd < 0) {
|
4107
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4108
|
-
}
|
4109
|
-
|
4110
|
-
switch(LIBUSB_REQ_TYPE(setup->request_type)) {
|
4111
|
-
case LIBUSB_REQUEST_TYPE_STANDARD:
|
4112
|
-
switch(setup->request) {
|
4113
|
-
case LIBUSB_REQUEST_GET_DESCRIPTOR:
|
4114
|
-
r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
|
4115
|
-
(setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
|
4116
|
-
break;
|
4117
|
-
case LIBUSB_REQUEST_GET_CONFIGURATION:
|
4118
|
-
r = windows_get_configuration(transfer->dev_handle, &config);
|
4119
|
-
if (r == LIBUSB_SUCCESS) {
|
4120
|
-
size = 1;
|
4121
|
-
((uint8_t*)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
|
4122
|
-
r = LIBUSB_COMPLETED;
|
4123
|
-
}
|
4124
|
-
break;
|
4125
|
-
case LIBUSB_REQUEST_SET_CONFIGURATION:
|
4126
|
-
if (setup->value == priv->active_config) {
|
4127
|
-
r = LIBUSB_COMPLETED;
|
4128
|
-
} else {
|
4129
|
-
usbi_warn(ctx, "cannot set configuration other than the default one");
|
4130
|
-
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4131
|
-
}
|
4132
|
-
break;
|
4133
|
-
case LIBUSB_REQUEST_GET_INTERFACE:
|
4134
|
-
size = 1;
|
4135
|
-
((uint8_t*)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0;
|
4136
|
-
r = LIBUSB_COMPLETED;
|
4137
|
-
break;
|
4138
|
-
case LIBUSB_REQUEST_SET_INTERFACE:
|
4139
|
-
r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value);
|
4140
|
-
if (r == LIBUSB_SUCCESS) {
|
4141
|
-
r = LIBUSB_COMPLETED;
|
4142
|
-
}
|
4143
|
-
break;
|
4144
|
-
default:
|
4145
|
-
usbi_warn(ctx, "unsupported HID control request");
|
4146
|
-
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4147
|
-
break;
|
4148
|
-
}
|
4149
|
-
break;
|
4150
|
-
case LIBUSB_REQUEST_TYPE_CLASS:
|
4151
|
-
r =_hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value,
|
4152
|
-
setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
|
4153
|
-
&size, wfd.overlapped);
|
4154
|
-
break;
|
4155
|
-
default:
|
4156
|
-
usbi_warn(ctx, "unsupported HID control request");
|
4157
|
-
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4158
|
-
break;
|
4159
|
-
}
|
4160
|
-
|
4161
|
-
if (r == LIBUSB_COMPLETED) {
|
4162
|
-
// Force request to be completed synchronously. Transferred size has been set by previous call
|
4163
|
-
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
4164
|
-
// http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx
|
4165
|
-
// set InternalHigh to the number of bytes transferred
|
4166
|
-
wfd.overlapped->InternalHigh = (DWORD)size;
|
4167
|
-
r = LIBUSB_SUCCESS;
|
4168
|
-
}
|
4169
|
-
|
4170
|
-
if (r == LIBUSB_SUCCESS) {
|
4171
|
-
// Use priv_transfer to store data needed for async polling
|
4172
|
-
transfer_priv->pollable_fd = wfd;
|
4173
|
-
transfer_priv->interface_number = (uint8_t)current_interface;
|
4174
|
-
} else {
|
4175
|
-
usbi_free_fd(&wfd);
|
4176
|
-
}
|
4177
|
-
|
4178
|
-
return r;
|
4179
|
-
}
|
4180
|
-
|
4181
|
-
static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
4182
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4183
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
4184
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4185
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
4186
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4187
|
-
struct winfd wfd;
|
4188
|
-
HANDLE hid_handle;
|
4189
|
-
bool direction_in, ret;
|
4190
|
-
int current_interface, length;
|
4191
|
-
DWORD size;
|
4192
|
-
int r = LIBUSB_SUCCESS;
|
4193
|
-
|
4194
|
-
CHECK_HID_AVAILABLE;
|
4195
|
-
|
4196
|
-
transfer_priv->pollable_fd = INVALID_WINFD;
|
4197
|
-
transfer_priv->hid_dest = NULL;
|
4198
|
-
safe_free(transfer_priv->hid_buffer);
|
4199
|
-
|
4200
|
-
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
|
4201
|
-
if (current_interface < 0) {
|
4202
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
|
4203
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4204
|
-
}
|
4205
|
-
|
4206
|
-
usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
|
4207
|
-
|
4208
|
-
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
4209
|
-
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
|
4210
|
-
|
4211
|
-
wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL);
|
4212
|
-
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
4213
|
-
if (wfd.fd < 0) {
|
4214
|
-
return LIBUSB_ERROR_NO_MEM;
|
4215
|
-
}
|
4216
|
-
|
4217
|
-
// If report IDs are not in use, an extra prefix byte must be added
|
4218
|
-
if ( ((direction_in) && (!priv->hid->uses_report_ids[0]))
|
4219
|
-
|| ((!direction_in) && (!priv->hid->uses_report_ids[1])) ) {
|
4220
|
-
length = transfer->length+1;
|
4221
|
-
} else {
|
4222
|
-
length = transfer->length;
|
4223
|
-
}
|
4224
|
-
// Add a trailing byte to detect overflows on input
|
4225
|
-
transfer_priv->hid_buffer = (uint8_t*)calloc(length+1, 1);
|
4226
|
-
if (transfer_priv->hid_buffer == NULL) {
|
4227
|
-
return LIBUSB_ERROR_NO_MEM;
|
4228
|
-
}
|
4229
|
-
transfer_priv->hid_expected_size = length;
|
4230
|
-
|
4231
|
-
if (direction_in) {
|
4232
|
-
transfer_priv->hid_dest = transfer->buffer;
|
4233
|
-
usbi_dbg("reading %d bytes (report ID: 0x00)", length);
|
4234
|
-
ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length+1, &size, wfd.overlapped);
|
4235
|
-
} else {
|
4236
|
-
if (!priv->hid->uses_report_ids[1]) {
|
4237
|
-
memcpy(transfer_priv->hid_buffer+1, transfer->buffer, transfer->length);
|
4238
|
-
} else {
|
4239
|
-
// We could actually do without the calloc and memcpy in this case
|
4240
|
-
memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
|
4241
|
-
}
|
4242
|
-
usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
|
4243
|
-
ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped);
|
4244
|
-
}
|
4245
|
-
if (!ret) {
|
4246
|
-
if (GetLastError() != ERROR_IO_PENDING) {
|
4247
|
-
usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
|
4248
|
-
usbi_free_fd(&wfd);
|
4249
|
-
safe_free(transfer_priv->hid_buffer);
|
4250
|
-
return LIBUSB_ERROR_IO;
|
4251
|
-
}
|
4252
|
-
} else {
|
4253
|
-
// Only write operations that completed synchronously need to free up
|
4254
|
-
// hid_buffer. For reads, copy_transfer_data() handles that process.
|
4255
|
-
if (!direction_in) {
|
4256
|
-
safe_free(transfer_priv->hid_buffer);
|
4257
|
-
}
|
4258
|
-
if (size == 0) {
|
4259
|
-
usbi_err(ctx, "program assertion failed - no data was transferred");
|
4260
|
-
size = 1;
|
4261
|
-
}
|
4262
|
-
if (size > (size_t)length) {
|
4263
|
-
usbi_err(ctx, "OVERFLOW!");
|
4264
|
-
r = LIBUSB_ERROR_OVERFLOW;
|
4265
|
-
}
|
4266
|
-
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
4267
|
-
wfd.overlapped->InternalHigh = size;
|
4268
|
-
}
|
4269
|
-
|
4270
|
-
transfer_priv->pollable_fd = wfd;
|
4271
|
-
transfer_priv->interface_number = (uint8_t)current_interface;
|
4272
|
-
|
4273
|
-
return r;
|
4274
|
-
}
|
4275
|
-
|
4276
|
-
static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
|
4277
|
-
{
|
4278
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4279
|
-
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
4280
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
4281
|
-
HANDLE hid_handle;
|
4282
|
-
int current_interface;
|
4283
|
-
|
4284
|
-
CHECK_HID_AVAILABLE;
|
4285
|
-
|
4286
|
-
current_interface = transfer_priv->interface_number;
|
4287
|
-
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
4288
|
-
CancelIo(hid_handle);
|
4289
|
-
|
4290
|
-
return LIBUSB_SUCCESS;
|
4291
|
-
}
|
4292
|
-
|
4293
|
-
static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
|
4294
|
-
{
|
4295
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
4296
|
-
HANDLE hid_handle;
|
4297
|
-
int current_interface;
|
4298
|
-
|
4299
|
-
CHECK_HID_AVAILABLE;
|
4300
|
-
|
4301
|
-
// Flushing the queues on all interfaces is the best we can achieve
|
4302
|
-
for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
|
4303
|
-
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
4304
|
-
if ((hid_handle != 0) && (hid_handle != INVALID_HANDLE_VALUE)) {
|
4305
|
-
HidD_FlushQueue(hid_handle);
|
4306
|
-
}
|
4307
|
-
}
|
4308
|
-
return LIBUSB_SUCCESS;
|
4309
|
-
}
|
4310
|
-
|
4311
|
-
static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
|
4312
|
-
{
|
4313
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
4314
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
4315
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4316
|
-
HANDLE hid_handle;
|
4317
|
-
int current_interface;
|
4318
|
-
|
4319
|
-
CHECK_HID_AVAILABLE;
|
4320
|
-
|
4321
|
-
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
|
4322
|
-
if (current_interface < 0) {
|
4323
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
|
4324
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4325
|
-
}
|
4326
|
-
|
4327
|
-
usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
|
4328
|
-
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
4329
|
-
|
4330
|
-
// No endpoint selection with Microsoft's implementation, so we try to flush the
|
4331
|
-
// whole interface. Should be OK for most case scenarios
|
4332
|
-
if (!HidD_FlushQueue(hid_handle)) {
|
4333
|
-
usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
|
4334
|
-
// Device was probably disconnected
|
4335
|
-
return LIBUSB_ERROR_NO_DEVICE;
|
4336
|
-
}
|
4337
|
-
|
4338
|
-
return LIBUSB_SUCCESS;
|
4339
|
-
}
|
4340
|
-
|
4341
|
-
// This extra function is only needed for HID
|
4342
|
-
static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) {
|
4343
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4344
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4345
|
-
struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
4346
|
-
int r = LIBUSB_TRANSFER_COMPLETED;
|
4347
|
-
uint32_t corrected_size = io_size;
|
4348
|
-
|
4349
|
-
if (transfer_priv->hid_buffer != NULL) {
|
4350
|
-
// If we have a valid hid_buffer, it means the transfer was async
|
4351
|
-
if (transfer_priv->hid_dest != NULL) { // Data readout
|
4352
|
-
if (corrected_size > 0) {
|
4353
|
-
// First, check for overflow
|
4354
|
-
if (corrected_size > transfer_priv->hid_expected_size) {
|
4355
|
-
usbi_err(ctx, "OVERFLOW!");
|
4356
|
-
corrected_size = (uint32_t)transfer_priv->hid_expected_size;
|
4357
|
-
r = LIBUSB_TRANSFER_OVERFLOW;
|
4358
|
-
}
|
4359
|
-
|
4360
|
-
if (transfer_priv->hid_buffer[0] == 0) {
|
4361
|
-
// Discard the 1 byte report ID prefix
|
4362
|
-
corrected_size--;
|
4363
|
-
memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer+1, corrected_size);
|
4364
|
-
} else {
|
4365
|
-
memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
|
4366
|
-
}
|
4367
|
-
}
|
4368
|
-
transfer_priv->hid_dest = NULL;
|
4369
|
-
}
|
4370
|
-
// For write, we just need to free the hid buffer
|
4371
|
-
safe_free(transfer_priv->hid_buffer);
|
4372
|
-
}
|
4373
|
-
itransfer->transferred += corrected_size;
|
4374
|
-
return r;
|
4375
|
-
}
|
4376
|
-
|
4377
|
-
|
4378
|
-
/*
|
4379
|
-
* Composite API functions
|
4380
|
-
*/
|
4381
|
-
static int composite_init(int sub_api, struct libusb_context *ctx)
|
4382
|
-
{
|
4383
|
-
return LIBUSB_SUCCESS;
|
4384
|
-
}
|
4385
|
-
|
4386
|
-
static int composite_exit(int sub_api)
|
4387
|
-
{
|
4388
|
-
return LIBUSB_SUCCESS;
|
4389
|
-
}
|
4390
|
-
|
4391
|
-
static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
|
4392
|
-
{
|
4393
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4394
|
-
int r = LIBUSB_ERROR_NOT_FOUND;
|
4395
|
-
uint8_t i;
|
4396
|
-
// SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
|
4397
|
-
bool available[SUB_API_MAX+1] = {0};
|
4398
|
-
|
4399
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
4400
|
-
switch (priv->usb_interface[i].apib->id) {
|
4401
|
-
case USB_API_WINUSBX:
|
4402
|
-
if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
|
4403
|
-
available[priv->usb_interface[i].sub_api] = true;
|
4404
|
-
break;
|
4405
|
-
case USB_API_HID:
|
4406
|
-
available[SUB_API_MAX] = true;
|
4407
|
-
break;
|
4408
|
-
default:
|
4409
|
-
break;
|
4410
|
-
}
|
4411
|
-
}
|
4412
|
-
|
4413
|
-
for (i=0; i<SUB_API_MAX; i++) { // WinUSB-like drivers
|
4414
|
-
if (available[i]) {
|
4415
|
-
r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle);
|
4416
|
-
if (r != LIBUSB_SUCCESS) {
|
4417
|
-
return r;
|
4418
|
-
}
|
4419
|
-
}
|
4420
|
-
}
|
4421
|
-
if (available[SUB_API_MAX]) { // HID driver
|
4422
|
-
r = hid_open(SUB_API_NOTSET, dev_handle);
|
4423
|
-
}
|
4424
|
-
return r;
|
4425
|
-
}
|
4426
|
-
|
4427
|
-
static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
|
4428
|
-
{
|
4429
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4430
|
-
uint8_t i;
|
4431
|
-
// SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
|
4432
|
-
bool available[SUB_API_MAX+1] = {0};
|
4433
|
-
|
4434
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
4435
|
-
switch (priv->usb_interface[i].apib->id) {
|
4436
|
-
case USB_API_WINUSBX:
|
4437
|
-
if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
|
4438
|
-
available[priv->usb_interface[i].sub_api] = true;
|
4439
|
-
break;
|
4440
|
-
case USB_API_HID:
|
4441
|
-
available[SUB_API_MAX] = true;
|
4442
|
-
break;
|
4443
|
-
default:
|
4444
|
-
break;
|
4445
|
-
}
|
4446
|
-
}
|
4447
|
-
|
4448
|
-
for (i=0; i<SUB_API_MAX; i++) { // WinUSB-like drivers
|
4449
|
-
if (available[i]) {
|
4450
|
-
usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
|
4451
|
-
}
|
4452
|
-
}
|
4453
|
-
if (available[SUB_API_MAX]) { // HID driver
|
4454
|
-
hid_close(SUB_API_NOTSET, dev_handle);
|
4455
|
-
}
|
4456
|
-
}
|
4457
|
-
|
4458
|
-
static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
4459
|
-
{
|
4460
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4461
|
-
return priv->usb_interface[iface].apib->
|
4462
|
-
claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
|
4463
|
-
}
|
4464
|
-
|
4465
|
-
static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
|
4466
|
-
{
|
4467
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4468
|
-
return priv->usb_interface[iface].apib->
|
4469
|
-
set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
|
4470
|
-
}
|
4471
|
-
|
4472
|
-
static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
4473
|
-
{
|
4474
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4475
|
-
return priv->usb_interface[iface].apib->
|
4476
|
-
release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
|
4477
|
-
}
|
4478
|
-
|
4479
|
-
static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
|
4480
|
-
{
|
4481
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4482
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4483
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4484
|
-
struct libusb_config_descriptor *conf_desc;
|
4485
|
-
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer;
|
4486
|
-
int iface, pass, r;
|
4487
|
-
|
4488
|
-
// Interface shouldn't matter for control, but it does in practice, with Windows'
|
4489
|
-
// restrictions with regards to accessing HID keyboards and mice. Try to target
|
4490
|
-
// a specific interface first, if possible.
|
4491
|
-
switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) {
|
4492
|
-
case LIBUSB_RECIPIENT_INTERFACE:
|
4493
|
-
iface = setup->index & 0xFF;
|
4494
|
-
break;
|
4495
|
-
case LIBUSB_RECIPIENT_ENDPOINT:
|
4496
|
-
r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
|
4497
|
-
if (r == LIBUSB_SUCCESS) {
|
4498
|
-
iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF));
|
4499
|
-
libusb_free_config_descriptor(conf_desc);
|
4500
|
-
break;
|
4501
|
-
}
|
4502
|
-
// Fall through if not able to determine interface
|
4503
|
-
default:
|
4504
|
-
iface = -1;
|
4505
|
-
break;
|
4506
|
-
}
|
4507
|
-
|
4508
|
-
// Try and target a specific interface if the control setup indicates such
|
4509
|
-
if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
|
4510
|
-
usbi_dbg("attempting control transfer targeted to interface %d", iface);
|
4511
|
-
if (priv->usb_interface[iface].path != NULL) {
|
4512
|
-
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
|
4513
|
-
if (r == LIBUSB_SUCCESS) {
|
4514
|
-
return r;
|
4515
|
-
}
|
4516
|
-
}
|
4517
|
-
}
|
4518
|
-
|
4519
|
-
// Either not targeted to a specific interface or no luck in doing so.
|
4520
|
-
// Try a 2 pass approach with all interfaces.
|
4521
|
-
for (pass = 0; pass < 2; pass++) {
|
4522
|
-
for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
|
4523
|
-
if (priv->usb_interface[iface].path != NULL) {
|
4524
|
-
if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
|
4525
|
-
usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
|
4526
|
-
continue;
|
4527
|
-
}
|
4528
|
-
usbi_dbg("using interface %d", iface);
|
4529
|
-
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
|
4530
|
-
// If not supported on this API, it may be supported on another, so don't give up yet!!
|
4531
|
-
if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
|
4532
|
-
continue;
|
4533
|
-
}
|
4534
|
-
return r;
|
4535
|
-
}
|
4536
|
-
}
|
4537
|
-
}
|
4538
|
-
|
4539
|
-
usbi_err(ctx, "no libusb supported interfaces to complete request");
|
4540
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4541
|
-
}
|
4542
|
-
|
4543
|
-
static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
4544
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4545
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4546
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
4547
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4548
|
-
int current_interface;
|
4549
|
-
|
4550
|
-
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
|
4551
|
-
if (current_interface < 0) {
|
4552
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
|
4553
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4554
|
-
}
|
4555
|
-
|
4556
|
-
return priv->usb_interface[current_interface].apib->
|
4557
|
-
submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);}
|
4558
|
-
|
4559
|
-
static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
|
4560
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4561
|
-
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4562
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
|
4563
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4564
|
-
int current_interface;
|
4565
|
-
|
4566
|
-
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
|
4567
|
-
if (current_interface < 0) {
|
4568
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
|
4569
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4570
|
-
}
|
4571
|
-
|
4572
|
-
return priv->usb_interface[current_interface].apib->
|
4573
|
-
submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer);}
|
4574
|
-
|
4575
|
-
static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
|
4576
|
-
{
|
4577
|
-
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
4578
|
-
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
4579
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4580
|
-
int current_interface;
|
4581
|
-
|
4582
|
-
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
|
4583
|
-
if (current_interface < 0) {
|
4584
|
-
usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
|
4585
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
4586
|
-
}
|
4587
|
-
|
4588
|
-
return priv->usb_interface[current_interface].apib->
|
4589
|
-
clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);}
|
4590
|
-
|
4591
|
-
static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
|
4592
|
-
{
|
4593
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4594
|
-
struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
4595
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4596
|
-
|
4597
|
-
return priv->usb_interface[transfer_priv->interface_number].apib->
|
4598
|
-
abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);}
|
4599
|
-
|
4600
|
-
static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
|
4601
|
-
{
|
4602
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4603
|
-
struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
4604
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4605
|
-
|
4606
|
-
return priv->usb_interface[transfer_priv->interface_number].apib->
|
4607
|
-
abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);}
|
4608
|
-
|
4609
|
-
static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
|
4610
|
-
{
|
4611
|
-
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4612
|
-
int r;
|
4613
|
-
uint8_t i;
|
4614
|
-
bool available[SUB_API_MAX];
|
4615
|
-
for (i = 0; i<SUB_API_MAX; i++) {
|
4616
|
-
available[i] = false;
|
4617
|
-
}
|
4618
|
-
for (i=0; i<USB_MAXINTERFACES; i++) {
|
4619
|
-
if ( (priv->usb_interface[i].apib->id == USB_API_WINUSBX)
|
4620
|
-
&& (priv->usb_interface[i].sub_api != SUB_API_NOTSET) ) {
|
4621
|
-
available[priv->usb_interface[i].sub_api] = true;
|
4622
|
-
}
|
4623
|
-
}
|
4624
|
-
for (i=0; i<SUB_API_MAX; i++) {
|
4625
|
-
if (available[i]) {
|
4626
|
-
r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle);
|
4627
|
-
if (r != LIBUSB_SUCCESS) {
|
4628
|
-
return r;
|
4629
|
-
}
|
4630
|
-
}
|
4631
|
-
}
|
4632
|
-
return LIBUSB_SUCCESS;
|
4633
|
-
}
|
4634
|
-
|
4635
|
-
static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
|
4636
|
-
{
|
4637
|
-
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4638
|
-
struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
|
4639
|
-
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4640
|
-
|
4641
|
-
return priv->usb_interface[transfer_priv->interface_number].apib->
|
4642
|
-
copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size);
|
4643
|
-
}
|