libusb 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +1 -0
- data/History.md +10 -0
- data/README.md +19 -6
- data/Rakefile +1 -1
- data/ext/extconf.rb +17 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
- data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
- data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
- data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
- data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
- data/ext/libusbx-1.0.17/android/README +114 -0
- data/ext/libusbx-1.0.17/android/config.h +90 -0
- data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
- data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
- data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
- data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
- data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
- data/ext/libusbx-1.0.17/compile +347 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
- data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
- data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
- data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
- data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
- data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
- data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
- data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
- data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
- data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
- data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
- data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
- data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
- data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
- data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
- data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
- data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
- data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
- data/ext/libusbx-1.0.17/missing +215 -0
- data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
- data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
- data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
- data/ext/libusbx-1.0.17/tests/stress.c +160 -0
- data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
- data/lib/libusb.rb +4 -0
- data/lib/libusb/call.rb +43 -1
- data/lib/libusb/constants.rb +5 -0
- data/lib/libusb/context.rb +100 -0
- data/lib/libusb/dev_handle.rb +27 -0
- data/lib/libusb/device.rb +10 -4
- data/lib/libusb/version_gem.rb +1 -1
- data/test/test_libusb_capability.rb +2 -2
- data/test/test_libusb_compat.rb +2 -2
- data/test/test_libusb_compat_mass_storage.rb +2 -2
- data/test/test_libusb_descriptors.rb +4 -2
- data/test/test_libusb_event_machine.rb +2 -2
- data/test/test_libusb_gc.rb +2 -2
- data/test/test_libusb_hotplug.rb +115 -0
- data/test/test_libusb_iso_transfer.rb +3 -3
- data/test/test_libusb_mass_storage.rb +6 -16
- data/test/test_libusb_mass_storage2.rb +26 -3
- data/test/test_libusb_structs.rb +2 -2
- data/test/test_libusb_threads.rb +2 -2
- data/test/test_libusb_version.rb +2 -2
- metadata +127 -68
- metadata.gz.sig +0 -0
- data/ext/libusbx-1.0.14/THANKS +0 -7
- data/ext/libusbx-1.0.14/compile +0 -143
- data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
- data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
- data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
- data/ext/libusbx-1.0.14/missing +0 -376
@@ -0,0 +1,131 @@
|
|
1
|
+
/*
|
2
|
+
* Windows CE backend for libusbx 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 libusbx 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
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
/*
|
2
|
+
* Windows backend common header for libusbx 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)
|
@@ -34,7 +34,7 @@
|
|
34
34
|
#include <objbase.h>
|
35
35
|
#include <winioctl.h>
|
36
36
|
|
37
|
-
#include
|
37
|
+
#include "libusbi.h"
|
38
38
|
#include "poll_windows.h"
|
39
39
|
#include "windows_usb.h"
|
40
40
|
|
@@ -42,8 +42,6 @@
|
|
42
42
|
#define LOOP_CHECK(fcall) { r=fcall; if (r != LIBUSB_SUCCESS) continue; }
|
43
43
|
#define LOOP_BREAK(err) { r=err; continue; }
|
44
44
|
|
45
|
-
extern void usbi_fd_notification(struct libusb_context *ctx);
|
46
|
-
|
47
45
|
// Helper prototypes
|
48
46
|
static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian);
|
49
47
|
static int windows_clock_gettime(int clk_id, struct timespec *tp);
|
@@ -153,7 +151,7 @@ static char *windows_error_str(uint32_t retval)
|
|
153
151
|
static char err_string[ERR_BUFFER_SIZE];
|
154
152
|
|
155
153
|
DWORD size;
|
156
|
-
|
154
|
+
ssize_t i;
|
157
155
|
uint32_t error_code, format_error;
|
158
156
|
|
159
157
|
error_code = retval?retval:GetLastError();
|
@@ -172,7 +170,7 @@ static char err_string[ERR_BUFFER_SIZE];
|
|
172
170
|
safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code);
|
173
171
|
} else {
|
174
172
|
// Remove CR/LF terminators
|
175
|
-
for (i=safe_strlen(err_string)-1; ((err_string[i]==0x0A) || (err_string[i]==0x0D)); i--) {
|
173
|
+
for (i=safe_strlen(err_string)-1; (i>=0) && ((err_string[i]==0x0A) || (err_string[i]==0x0D)); i--) {
|
176
174
|
err_string[i] = 0;
|
177
175
|
}
|
178
176
|
}
|
@@ -261,7 +259,7 @@ static int init_dlls(void)
|
|
261
259
|
* incremented index starting at zero) until all interfaces have been returned.
|
262
260
|
*/
|
263
261
|
static bool get_devinfo_data(struct libusb_context *ctx,
|
264
|
-
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, char* usb_class, unsigned _index)
|
262
|
+
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char* usb_class, unsigned _index)
|
265
263
|
{
|
266
264
|
if (_index <= 0) {
|
267
265
|
*dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
|
@@ -365,7 +363,7 @@ err_exit:
|
|
365
363
|
}
|
366
364
|
|
367
365
|
/* For libusb0 filter */
|
368
|
-
SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
|
366
|
+
static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
|
369
367
|
HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID* guid, unsigned _index, char* filter_path){
|
370
368
|
SP_DEVICE_INTERFACE_DATA dev_interface_data;
|
371
369
|
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
@@ -537,6 +535,9 @@ static unsigned long htab_hash(char* str)
|
|
537
535
|
int c;
|
538
536
|
char* sz = str;
|
539
537
|
|
538
|
+
if (str == NULL)
|
539
|
+
return 0;
|
540
|
+
|
540
541
|
// Compute main hash value (algorithm suggested by Nokia)
|
541
542
|
while ((c = *sz++) != 0)
|
542
543
|
r = ((r << 5) + r) + c;
|
@@ -635,7 +636,7 @@ static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
|
|
635
636
|
if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) {
|
636
637
|
return 0;
|
637
638
|
}
|
638
|
-
// TODO (post hotplug): try without sanitizing
|
639
|
+
// TODO: (post hotplug): try without sanitizing
|
639
640
|
sanitized_path = sanitize_path(path);
|
640
641
|
if (sanitized_path == NULL) {
|
641
642
|
return 0;
|
@@ -688,7 +689,7 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
|
|
688
689
|
|
689
690
|
// Lookup for a match in the list of API driver names
|
690
691
|
// return -1 if not found, driver match number otherwise
|
691
|
-
int get_sub_api(char* driver, int api){
|
692
|
+
static int get_sub_api(char* driver, int api){
|
692
693
|
int i;
|
693
694
|
const char sep_str[2] = {LIST_SEPARATOR, 0};
|
694
695
|
char *tok, *tmp_str;
|
@@ -885,6 +886,12 @@ static int windows_init(struct libusb_context *ctx)
|
|
885
886
|
}
|
886
887
|
SetThreadAffinityMask(timer_thread, 0);
|
887
888
|
|
889
|
+
// Wait for timer thread to init before continuing.
|
890
|
+
if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) {
|
891
|
+
usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting");
|
892
|
+
goto init_exit;
|
893
|
+
}
|
894
|
+
|
888
895
|
// Create a hash table to store session ids. Second parameter is better if prime
|
889
896
|
htab_create(ctx, HTAB_SIZE);
|
890
897
|
}
|
@@ -1109,7 +1116,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
|
|
1109
1116
|
dev->port_number = port_number;
|
1110
1117
|
priv->depth = parent_priv->depth + 1;
|
1111
1118
|
priv->parent_dev = parent_dev;
|
1112
|
-
dev->parent_dev = parent_dev;
|
1119
|
+
dev->parent_dev = libusb_ref_device(parent_dev);
|
1113
1120
|
|
1114
1121
|
// If the device address is already set, we can stop here
|
1115
1122
|
if (dev->device_address != 0) {
|
@@ -1169,6 +1176,8 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
|
|
1169
1176
|
force_hcd_device_descriptor(dev);
|
1170
1177
|
}
|
1171
1178
|
|
1179
|
+
usbi_sanitize_device(dev);
|
1180
|
+
|
1172
1181
|
usbi_dbg("(bus: %d, addr: %d, depth: %d, port: %d): '%s'",
|
1173
1182
|
dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
|
1174
1183
|
|
@@ -1176,7 +1185,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
|
|
1176
1185
|
}
|
1177
1186
|
|
1178
1187
|
// Returns the api type, or 0 if not found/unsupported
|
1179
|
-
void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
|
1188
|
+
static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
|
1180
1189
|
SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
|
1181
1190
|
{
|
1182
1191
|
// Precedence for filter drivers vs driver is in the order of this array
|
@@ -1277,7 +1286,7 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev
|
|
1277
1286
|
priv->usb_interface[interface_number].apib = &usb_api_backend[api];
|
1278
1287
|
priv->usb_interface[interface_number].sub_api = sub_api;
|
1279
1288
|
if ((api == USB_API_HID) && (priv->hid == NULL)) {
|
1280
|
-
priv->hid = calloc(1, sizeof(struct hid_device_priv));
|
1289
|
+
priv->hid = (struct hid_device_priv*) calloc(1, sizeof(struct hid_device_priv));
|
1281
1290
|
if (priv->hid == NULL)
|
1282
1291
|
return LIBUSB_ERROR_NO_MEM;
|
1283
1292
|
}
|
@@ -1288,6 +1297,7 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev
|
|
1288
1297
|
static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* dev,
|
1289
1298
|
char* dev_interface_path)
|
1290
1299
|
{
|
1300
|
+
int i;
|
1291
1301
|
struct windows_device_priv *priv = _device_priv(dev);
|
1292
1302
|
|
1293
1303
|
if (priv->hid == NULL) {
|
@@ -1298,8 +1308,11 @@ static int set_hid_interface(struct libusb_context* ctx, struct libusb_device* d
|
|
1298
1308
|
usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
|
1299
1309
|
return LIBUSB_ERROR_NO_DEVICE;
|
1300
1310
|
}
|
1301
|
-
|
1302
|
-
|
1311
|
+
for (i=0; i<priv->hid->nb_interfaces; i++) {
|
1312
|
+
if (safe_strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
|
1313
|
+
usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
|
1314
|
+
return LIBUSB_SUCCESS;
|
1315
|
+
}
|
1303
1316
|
}
|
1304
1317
|
|
1305
1318
|
priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
|
@@ -1316,7 +1329,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
|
|
1316
1329
|
{
|
1317
1330
|
struct discovered_devs *discdevs;
|
1318
1331
|
HDEVINFO dev_info = { 0 };
|
1319
|
-
char* usb_class[] = {"USB", "NUSB3", "IUSB3"};
|
1332
|
+
const char* usb_class[] = {"USB", "NUSB3", "IUSB3"};
|
1320
1333
|
SP_DEVINFO_DATA dev_info_data = { 0 };
|
1321
1334
|
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
1322
1335
|
GUID hid_guid;
|
@@ -1329,7 +1342,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
|
|
1329
1342
|
#define HID_PASS 4
|
1330
1343
|
int r = LIBUSB_SUCCESS;
|
1331
1344
|
int api, sub_api;
|
1332
|
-
|
1345
|
+
size_t class_index = 0;
|
1333
1346
|
unsigned int nb_guids, pass, i, j, ancestor;
|
1334
1347
|
char path[MAX_PATH_LENGTH];
|
1335
1348
|
char strbuf[MAX_PATH_LENGTH];
|
@@ -1750,8 +1763,9 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf
|
|
1750
1763
|
|
1751
1764
|
size = min(config_header->wTotalLength, len);
|
1752
1765
|
memcpy(buffer, priv->config_descriptor[config_index], size);
|
1766
|
+
*host_endian = 0;
|
1753
1767
|
|
1754
|
-
return
|
1768
|
+
return (int)size;
|
1755
1769
|
}
|
1756
1770
|
|
1757
1771
|
/*
|
@@ -1906,7 +1920,7 @@ static void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
|
|
1906
1920
|
{
|
1907
1921
|
struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
|
1908
1922
|
|
1909
|
-
usbi_free_fd(transfer_priv->pollable_fd
|
1923
|
+
usbi_free_fd(&transfer_priv->pollable_fd);
|
1910
1924
|
safe_free(transfer_priv->hid_buffer);
|
1911
1925
|
// When auto claim is in use, attempt to release the auto-claimed interface
|
1912
1926
|
auto_release(itransfer);
|
@@ -2030,9 +2044,9 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t
|
|
2030
2044
|
{
|
2031
2045
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
2032
2046
|
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
2033
|
-
int status;
|
2047
|
+
int status, istatus;
|
2034
2048
|
|
2035
|
-
usbi_dbg("handling I/O completion with errcode %d", io_result);
|
2049
|
+
usbi_dbg("handling I/O completion with errcode %d, size %d", io_result, io_size);
|
2036
2050
|
|
2037
2051
|
switch(io_result) {
|
2038
2052
|
case NO_ERROR:
|
@@ -2047,6 +2061,10 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t
|
|
2047
2061
|
status = LIBUSB_TRANSFER_TIMED_OUT;
|
2048
2062
|
break;
|
2049
2063
|
case ERROR_OPERATION_ABORTED:
|
2064
|
+
istatus = priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
|
2065
|
+
if (istatus != LIBUSB_TRANSFER_COMPLETED) {
|
2066
|
+
usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
|
2067
|
+
}
|
2050
2068
|
if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) {
|
2051
2069
|
usbi_dbg("detected timeout");
|
2052
2070
|
status = LIBUSB_TRANSFER_TIMED_OUT;
|
@@ -2056,7 +2074,7 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t
|
|
2056
2074
|
}
|
2057
2075
|
break;
|
2058
2076
|
default:
|
2059
|
-
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(0));
|
2077
|
+
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %d: %s", io_result, windows_error_str(0));
|
2060
2078
|
status = LIBUSB_TRANSFER_ERROR;
|
2061
2079
|
break;
|
2062
2080
|
}
|
@@ -2160,6 +2178,11 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
|
|
2160
2178
|
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
|
2161
2179
|
}
|
2162
2180
|
|
2181
|
+
// Signal windows_init() that we're ready to service requests
|
2182
|
+
if (ReleaseSemaphore(timer_response, 1, NULL) == 0) {
|
2183
|
+
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
|
2184
|
+
}
|
2185
|
+
|
2163
2186
|
// Main loop - wait for requests
|
2164
2187
|
while (1) {
|
2165
2188
|
timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0;
|
@@ -2194,7 +2217,7 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
|
|
2194
2217
|
nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
|
2195
2218
|
if ( (nb_responses)
|
2196
2219
|
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
|
2197
|
-
usbi_dbg("unable to release timer semaphore
|
2220
|
+
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
|
2198
2221
|
}
|
2199
2222
|
continue;
|
2200
2223
|
case 1: // time to quit
|
@@ -2253,16 +2276,19 @@ static int windows_clock_gettime(int clk_id, struct timespec *tp)
|
|
2253
2276
|
// NB: MSVC6 does not support named initializers.
|
2254
2277
|
const struct usbi_os_backend windows_backend = {
|
2255
2278
|
"Windows",
|
2279
|
+
USBI_CAP_HAS_HID_ACCESS,
|
2256
2280
|
windows_init,
|
2257
2281
|
windows_exit,
|
2258
2282
|
|
2259
2283
|
windows_get_device_list,
|
2284
|
+
NULL, /* hotplug_poll */
|
2260
2285
|
windows_open,
|
2261
2286
|
windows_close,
|
2262
2287
|
|
2263
2288
|
windows_get_device_descriptor,
|
2264
2289
|
windows_get_active_config_descriptor,
|
2265
2290
|
windows_get_config_descriptor,
|
2291
|
+
NULL, /* get_config_descriptor_by_value() */
|
2266
2292
|
|
2267
2293
|
windows_get_configuration,
|
2268
2294
|
windows_set_configuration,
|
@@ -2594,6 +2620,8 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
|
|
2594
2620
|
HANDLE file_handle;
|
2595
2621
|
int i;
|
2596
2622
|
|
2623
|
+
if (sub_api == SUB_API_NOTSET)
|
2624
|
+
sub_api = priv->sub_api;
|
2597
2625
|
if (!WinUSBX[sub_api].initialized)
|
2598
2626
|
return;
|
2599
2627
|
|
@@ -2662,9 +2690,10 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
|
|
2662
2690
|
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2663
2691
|
bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
|
2664
2692
|
HANDLE file_handle, winusb_handle;
|
2693
|
+
DWORD err;
|
2665
2694
|
int i;
|
2666
2695
|
SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
|
2667
|
-
HDEVINFO dev_info;
|
2696
|
+
HDEVINFO dev_info = INVALID_HANDLE_VALUE;
|
2668
2697
|
SP_DEVINFO_DATA dev_info_data;
|
2669
2698
|
char* dev_path_no_guid = NULL;
|
2670
2699
|
char filter_path[] = "\\\\.\\libusb0-0000";
|
@@ -2683,15 +2712,15 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
|
|
2683
2712
|
|
2684
2713
|
if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
|
2685
2714
|
handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
|
2686
|
-
|
2687
|
-
switch(
|
2715
|
+
err = GetLastError();
|
2716
|
+
switch(err) {
|
2688
2717
|
case ERROR_BAD_COMMAND:
|
2689
2718
|
// The device was disconnected
|
2690
2719
|
usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
|
2691
2720
|
return LIBUSB_ERROR_NO_DEVICE;
|
2692
2721
|
default:
|
2693
2722
|
// it may be that we're using the libusb0 filter driver.
|
2694
|
-
//
|
2723
|
+
// TODO: can we move this whole business into the K/0 DLL?
|
2695
2724
|
for (i = 0; ; i++) {
|
2696
2725
|
safe_free(dev_interface_details);
|
2697
2726
|
safe_free(dev_path_no_guid);
|
@@ -2717,7 +2746,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
|
|
2717
2746
|
}
|
2718
2747
|
}
|
2719
2748
|
if (!found_filter) {
|
2720
|
-
usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(
|
2749
|
+
usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
|
2721
2750
|
return LIBUSB_ERROR_ACCESS;
|
2722
2751
|
}
|
2723
2752
|
}
|
@@ -2730,11 +2759,11 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
|
|
2730
2759
|
// must first claim the first interface before you claim the others
|
2731
2760
|
if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) {
|
2732
2761
|
file_handle = handle_priv->interface_handle[0].dev_handle;
|
2733
|
-
if (
|
2762
|
+
if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
|
2734
2763
|
handle_priv->interface_handle[0].api_handle = winusb_handle;
|
2735
2764
|
usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
|
2736
2765
|
} else {
|
2737
|
-
usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB)", iface);
|
2766
|
+
usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
|
2738
2767
|
return LIBUSB_ERROR_ACCESS;
|
2739
2768
|
}
|
2740
2769
|
}
|
@@ -2860,7 +2889,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
|
|
2860
2889
|
usbi_dbg("will use interface %d", current_interface);
|
2861
2890
|
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
2862
2891
|
|
2863
|
-
wfd = usbi_create_fd(winusb_handle,
|
2892
|
+
wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL);
|
2864
2893
|
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
2865
2894
|
if (wfd.fd < 0) {
|
2866
2895
|
return LIBUSB_ERROR_NO_MEM;
|
@@ -2871,7 +2900,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
|
|
2871
2900
|
&& (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION) ) {
|
2872
2901
|
if (setup->value != priv->active_config) {
|
2873
2902
|
usbi_warn(ctx, "cannot set configuration other than the default one");
|
2874
|
-
usbi_free_fd(wfd
|
2903
|
+
usbi_free_fd(&wfd);
|
2875
2904
|
return LIBUSB_ERROR_INVALID_PARAM;
|
2876
2905
|
}
|
2877
2906
|
wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
|
@@ -2880,7 +2909,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
|
|
2880
2909
|
if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) {
|
2881
2910
|
if(GetLastError() != ERROR_IO_PENDING) {
|
2882
2911
|
usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
|
2883
|
-
usbi_free_fd(wfd
|
2912
|
+
usbi_free_fd(&wfd);
|
2884
2913
|
return LIBUSB_ERROR_IO;
|
2885
2914
|
}
|
2886
2915
|
} else {
|
@@ -2949,7 +2978,7 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
|
|
2949
2978
|
|
2950
2979
|
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
|
2951
2980
|
|
2952
|
-
wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ?
|
2981
|
+
wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
|
2953
2982
|
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
2954
2983
|
if (wfd.fd < 0) {
|
2955
2984
|
return LIBUSB_ERROR_NO_MEM;
|
@@ -2965,7 +2994,7 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
|
|
2965
2994
|
if (!ret) {
|
2966
2995
|
if(GetLastError() != ERROR_IO_PENDING) {
|
2967
2996
|
usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
|
2968
|
-
usbi_free_fd(wfd
|
2997
|
+
usbi_free_fd(&wfd);
|
2969
2998
|
return LIBUSB_ERROR_IO;
|
2970
2999
|
}
|
2971
3000
|
} else {
|
@@ -3055,7 +3084,7 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
|
|
3055
3084
|
* IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
|
3056
3085
|
* cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
|
3057
3086
|
*/
|
3058
|
-
// TODO (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
|
3087
|
+
// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
|
3059
3088
|
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
|
3060
3089
|
{
|
3061
3090
|
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
@@ -3074,7 +3103,7 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
|
|
3074
3103
|
{
|
3075
3104
|
// Cancel any pollable I/O
|
3076
3105
|
usbi_remove_pollfd(ctx, wfd.fd);
|
3077
|
-
usbi_free_fd(wfd
|
3106
|
+
usbi_free_fd(&wfd);
|
3078
3107
|
wfd = handle_to_winfd(winusb_handle);
|
3079
3108
|
}
|
3080
3109
|
|
@@ -3214,8 +3243,7 @@ static int _hid_get_config_descriptor(struct hid_device_priv* dev, void *data, s
|
|
3214
3243
|
ed->bmAttributes = 3;
|
3215
3244
|
ed->wMaxPacketSize = dev->input_report_size - 1;
|
3216
3245
|
ed->bInterval = 10;
|
3217
|
-
|
3218
|
-
ed++;
|
3246
|
+
ed = (struct libusb_endpoint_descriptor *)((char*)ed + LIBUSB_DT_ENDPOINT_SIZE);
|
3219
3247
|
}
|
3220
3248
|
|
3221
3249
|
if (dev->output_report_size) {
|
@@ -3626,7 +3654,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
|
|
3626
3654
|
int i, j;
|
3627
3655
|
// report IDs handling
|
3628
3656
|
ULONG size[3];
|
3629
|
-
char* type[3] = {"input", "output", "feature"};
|
3657
|
+
const char* type[3] = {"input", "output", "feature"};
|
3630
3658
|
int nb_ids[2]; // zero and nonzero report IDs
|
3631
3659
|
|
3632
3660
|
CHECK_HID_AVAILABLE;
|
@@ -3882,9 +3910,9 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
|
|
3882
3910
|
usbi_dbg("will use interface %d", current_interface);
|
3883
3911
|
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3884
3912
|
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
3885
|
-
wfd = usbi_create_fd(hid_handle,
|
3913
|
+
wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
|
3886
3914
|
if (wfd.fd < 0) {
|
3887
|
-
return
|
3915
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
3888
3916
|
}
|
3889
3917
|
|
3890
3918
|
switch(LIBUSB_REQ_TYPE(setup->request_type)) {
|
@@ -3952,7 +3980,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
|
|
3952
3980
|
transfer_priv->pollable_fd = wfd;
|
3953
3981
|
transfer_priv->interface_number = (uint8_t)current_interface;
|
3954
3982
|
} else {
|
3955
|
-
usbi_free_fd(wfd
|
3983
|
+
usbi_free_fd(&wfd);
|
3956
3984
|
}
|
3957
3985
|
|
3958
3986
|
return r;
|
@@ -3988,7 +4016,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
|
|
3988
4016
|
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
|
3989
4017
|
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
|
3990
4018
|
|
3991
|
-
wfd = usbi_create_fd(hid_handle, direction_in?
|
4019
|
+
wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL);
|
3992
4020
|
// Always use the handle returned from usbi_create_fd (wfd.handle)
|
3993
4021
|
if (wfd.fd < 0) {
|
3994
4022
|
return LIBUSB_ERROR_NO_MEM;
|
@@ -4010,7 +4038,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
|
|
4010
4038
|
|
4011
4039
|
if (direction_in) {
|
4012
4040
|
transfer_priv->hid_dest = transfer->buffer;
|
4013
|
-
usbi_dbg("reading %d bytes (report ID:
|
4041
|
+
usbi_dbg("reading %d bytes (report ID: 0x00)", length);
|
4014
4042
|
ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length+1, &size, wfd.overlapped);
|
4015
4043
|
} else {
|
4016
4044
|
if (!priv->hid->uses_report_ids[1]) {
|
@@ -4025,7 +4053,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
|
|
4025
4053
|
if (!ret) {
|
4026
4054
|
if (GetLastError() != ERROR_IO_PENDING) {
|
4027
4055
|
usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
|
4028
|
-
usbi_free_fd(wfd
|
4056
|
+
usbi_free_fd(&wfd);
|
4029
4057
|
safe_free(transfer_priv->hid_buffer);
|
4030
4058
|
return LIBUSB_ERROR_IO;
|
4031
4059
|
}
|
@@ -4169,30 +4197,37 @@ static int composite_exit(int sub_api)
|
|
4169
4197
|
static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
|
4170
4198
|
{
|
4171
4199
|
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4172
|
-
int r;
|
4200
|
+
int r = LIBUSB_ERROR_NOT_FOUND;
|
4173
4201
|
uint8_t i;
|
4174
|
-
|
4175
|
-
|
4176
|
-
for (i = 0; i<SUB_API_MAX; i++) {
|
4177
|
-
available[i] = false;
|
4178
|
-
}
|
4202
|
+
// SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
|
4203
|
+
bool available[SUB_API_MAX+1] = {0};
|
4179
4204
|
|
4180
4205
|
for (i=0; i<USB_MAXINTERFACES; i++) {
|
4181
|
-
|
4182
|
-
|
4183
|
-
|
4206
|
+
switch (priv->usb_interface[i].apib->id) {
|
4207
|
+
case USB_API_WINUSBX:
|
4208
|
+
if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
|
4209
|
+
available[priv->usb_interface[i].sub_api] = true;
|
4210
|
+
break;
|
4211
|
+
case USB_API_HID:
|
4212
|
+
available[SUB_API_MAX] = true;
|
4213
|
+
break;
|
4214
|
+
default:
|
4215
|
+
break;
|
4184
4216
|
}
|
4185
4217
|
}
|
4186
4218
|
|
4187
|
-
for (i=0; i<SUB_API_MAX; i++) {
|
4219
|
+
for (i=0; i<SUB_API_MAX; i++) { // WinUSB-like drivers
|
4188
4220
|
if (available[i]) {
|
4189
|
-
r = usb_api_backend[USB_API_WINUSBX].open(
|
4221
|
+
r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle);
|
4190
4222
|
if (r != LIBUSB_SUCCESS) {
|
4191
4223
|
return r;
|
4192
4224
|
}
|
4193
4225
|
}
|
4194
4226
|
}
|
4195
|
-
|
4227
|
+
if (available[SUB_API_MAX]) { // HID driver
|
4228
|
+
r = hid_open(SUB_API_NOTSET, dev_handle);
|
4229
|
+
}
|
4230
|
+
return r;
|
4196
4231
|
}
|
4197
4232
|
|
4198
4233
|
static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
|