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