libusb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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)