libusb 0.2.2 → 0.3.0

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