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