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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. 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 <libusbi.h>
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
- size_t i;
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
- if (priv->usb_interface[priv->hid->nb_interfaces].path != NULL) {
1302
- safe_free(priv->usb_interface[priv->hid->nb_interfaces].path);
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
- int class_index = 0;
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 LIBUSB_SUCCESS;
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.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 %d: %s", windows_error_str(0));
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(GetLastError()) {
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
- // [TODO] can we move this whole business into the K/0 DLL?
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(0));
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 (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
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, _O_RDONLY);
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.fd);
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.fd);
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) ? _O_RDONLY : _O_WRONLY);
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.fd);
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.fd);
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, _O_RDONLY);
3913
+ wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
3886
3914
  if (wfd.fd < 0) {
3887
- return LIBUSB_ERROR_NO_MEM;
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.fd);
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?_O_RDONLY:_O_WRONLY);
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: 0x%02X)", length, transfer_priv->hid_buffer[0]);
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.fd);
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
- bool available[SUB_API_MAX];
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
- if ( (priv->usb_interface[i].apib->id == USB_API_WINUSBX)
4182
- && (priv->usb_interface[i].sub_api != SUB_API_NOTSET) ) {
4183
- available[priv->usb_interface[i].sub_api] = true;
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(SUB_API_NOTSET, dev_handle);
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
- return LIBUSB_SUCCESS;
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)