2 * windows backend for libusb 1.0
3 * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
4 * Copyright © 2016-2018 Chris Dickens <christopher.a.dickens@gmail.com>
5 * With contributions from Michael Plante, Orin Eman et al.
6 * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
7 * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
8 * Hash table functions adapted from glibc, by Ulrich Drepper et al.
9 * Major code testing contribution by Xiaofan Chen
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.
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.
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
40 #include "windows_common.h"
41 #include "windows_winusb.h"
43 #define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
45 // The 2 macros below are used in conjunction with safe loops.
46 #define LOOP_CHECK(fcall) \
49 if (r != LIBUSB_SUCCESS) \
52 #define LOOP_BREAK(err) \
58 // WinUSB-like API prototypes
59 static int winusbx_init(struct libusb_context *ctx);
60 static void winusbx_exit(void);
61 static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
62 static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
63 static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
64 static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
65 static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
66 static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
67 static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
68 static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
69 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
70 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
71 static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
72 static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
73 static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
74 static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
76 static int hid_init(struct libusb_context *ctx);
77 static void hid_exit(void);
78 static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
79 static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
80 static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
81 static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
82 static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
83 static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
84 static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
85 static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
86 static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
87 static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
88 static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
89 // Composite API prototypes
90 static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
91 static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
92 static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
93 static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
94 static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
95 static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
96 static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
97 static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
98 static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
99 static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
100 static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
101 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
102 static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
104 static usbi_mutex_t autoclaim_lock;
107 static HMODULE WinUSBX_handle = NULL;
108 static struct winusb_interface WinUSBX[SUB_API_MAX];
109 #define CHECK_WINUSBX_AVAILABLE(sub_api) \
111 if (sub_api == SUB_API_NOTSET) \
112 sub_api = priv->sub_api; \
113 if (!WinUSBX[sub_api].initialized) \
114 return LIBUSB_ERROR_ACCESS; \
117 static bool api_hid_available = false;
118 #define CHECK_HID_AVAILABLE \
120 if (!api_hid_available) \
121 return LIBUSB_ERROR_ACCESS; \
124 #if defined(ENABLE_LOGGING)
125 static const char *guid_to_string(const GUID *guid)
127 static char guid_string[MAX_GUID_STRING_LENGTH];
132 sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
133 (unsigned int)guid->Data1, guid->Data2, guid->Data3,
134 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
135 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
142 * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
143 * Return an allocated sanitized string or NULL on error.
145 static char *sanitize_path(const char *path)
147 const char root_prefix[] = {'\\', '\\', '.', '\\'};
155 size = strlen(path) + 1;
157 // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
158 if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\'))
159 || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
160 add_root = sizeof(root_prefix);
164 ret_path = malloc(size);
165 if (ret_path == NULL)
168 strcpy(&ret_path[add_root], path);
170 // Ensure consistency with root prefix
171 memcpy(ret_path, root_prefix, sizeof(root_prefix));
173 // Same goes for '\' and '#' after the root prefix. Ensure '#' is used
174 for (j = sizeof(root_prefix); j < size; j++) {
175 ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too
176 if (ret_path[j] == '\\')
184 * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions
186 static BOOL init_dlls(void)
188 DLL_GET_HANDLE(Cfgmgr32);
189 DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
190 DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE);
192 // Prefixed to avoid conflict with header files
193 DLL_GET_HANDLE(AdvAPI32);
194 DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
195 DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
197 DLL_GET_HANDLE(OLE32);
198 DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE);
200 DLL_GET_HANDLE(SetupAPI);
201 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE);
202 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE);
203 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE);
204 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE);
205 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
206 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
207 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE);
208 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
209 DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
214 static void exit_dlls(void)
216 DLL_FREE_HANDLE(Cfgmgr32);
217 DLL_FREE_HANDLE(AdvAPI32);
218 DLL_FREE_HANDLE(OLE32);
219 DLL_FREE_HANDLE(SetupAPI);
223 * enumerate interfaces for the whole USB class
226 * dev_info: a pointer to a dev_info list
227 * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
228 * enumerator: the generic USB class for which to retrieve interface details
229 * index: zero based index of the interface in the device info list
231 * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
232 * structure returned and call this function repeatedly using the same guid (with an
233 * incremented index starting at zero) until all interfaces have been returned.
235 static bool get_devinfo_data(struct libusb_context *ctx,
236 HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index)
239 *dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
240 if (*dev_info == INVALID_HANDLE_VALUE) {
241 usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s",
242 enumerator, windows_error_str(0));
247 dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
248 if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
249 if (GetLastError() != ERROR_NO_MORE_ITEMS)
250 usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s",
251 enumerator, _index, windows_error_str(0));
253 pSetupDiDestroyDeviceInfoList(*dev_info);
254 *dev_info = INVALID_HANDLE_VALUE;
261 * enumerate interfaces for a specific GUID
264 * dev_info: a pointer to a dev_info list
265 * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
266 * guid: the GUID for which to retrieve interface details
267 * index: zero based index of the interface in the device info list
269 * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
270 * structure returned and call this function repeatedly using the same guid (with an
271 * incremented index starting at zero) until all interfaces have been returned.
273 static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
274 PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path)
276 SP_DEVICE_INTERFACE_DATA dev_interface_data;
277 PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
280 dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
281 dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
283 if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) {
284 if (GetLastError() != ERROR_NO_MORE_ITEMS) {
285 usbi_err(ctx, "Could not obtain device info data for %s index %lu: %s",
286 guid_to_string(guid), *_index, windows_error_str(0));
287 return LIBUSB_ERROR_OTHER;
291 return LIBUSB_SUCCESS;
294 // Always advance the index for the next iteration
297 if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data))
300 if (GetLastError() != ERROR_NO_MORE_ITEMS) {
301 usbi_err(ctx, "Could not obtain interface data for %s devInst %lX: %s",
302 guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
303 return LIBUSB_ERROR_OTHER;
306 // Device does not have an interface matching this GUID, skip
309 // Read interface data (dummy + actual) to access the device path
310 if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
311 // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
312 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
313 usbi_err(ctx, "could not access interface data (dummy) for %s devInst %lX: %s",
314 guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
315 return LIBUSB_ERROR_OTHER;
318 usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong");
319 return LIBUSB_ERROR_OTHER;
322 dev_interface_details = malloc(size);
323 if (dev_interface_details == NULL) {
324 usbi_err(ctx, "could not allocate interface data for %s devInst %lX",
325 guid_to_string(guid), dev_info_data->DevInst);
326 return LIBUSB_ERROR_NO_MEM;
329 dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
330 if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data,
331 dev_interface_details, size, NULL, NULL)) {
332 usbi_err(ctx, "could not access interface data (actual) for %s devInst %lX: %s",
333 guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0));
334 free(dev_interface_details);
335 return LIBUSB_ERROR_OTHER;
338 *dev_interface_path = sanitize_path(dev_interface_details->DevicePath);
339 free(dev_interface_details);
341 if (*dev_interface_path == NULL) {
342 usbi_err(ctx, "could not allocate interface path for %s devInst %lX",
343 guid_to_string(guid), dev_info_data->DevInst);
344 return LIBUSB_ERROR_NO_MEM;
347 return LIBUSB_SUCCESS;
350 /* For libusb0 filter */
351 static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
352 HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path)
354 SP_DEVICE_INTERFACE_DATA dev_interface_data;
355 SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details;
359 *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
361 if (dev_info_data != NULL) {
362 dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
363 if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
364 if (GetLastError() != ERROR_NO_MORE_ITEMS)
365 usbi_err(ctx, "Could not obtain device info data for index %u: %s",
366 _index, windows_error_str(0));
368 pSetupDiDestroyDeviceInfoList(*dev_info);
369 *dev_info = INVALID_HANDLE_VALUE;
374 dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
375 if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
376 if (GetLastError() != ERROR_NO_MORE_ITEMS)
377 usbi_err(ctx, "Could not obtain interface data for index %u: %s",
378 _index, windows_error_str(0));
380 pSetupDiDestroyDeviceInfoList(*dev_info);
381 *dev_info = INVALID_HANDLE_VALUE;
385 // Read interface data (dummy + actual) to access the device path
386 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
387 // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
388 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
389 usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
390 _index, windows_error_str(0));
394 usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
398 dev_interface_details = calloc(1, size);
399 if (dev_interface_details == NULL) {
400 usbi_err(ctx, "could not allocate interface data for index %u.", _index);
404 dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
405 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL))
406 usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
407 _index, windows_error_str(0));
409 // [trobinso] lookup the libusb0 symbolic index.
410 if (dev_interface_details) {
411 HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
412 if (hkey_device_interface != INVALID_HANDLE_VALUE) {
413 DWORD libusb0_symboliclink_index = 0;
414 DWORD value_length = sizeof(DWORD);
415 DWORD value_type = 0;
418 status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type,
419 (LPBYTE)&libusb0_symboliclink_index, &value_length);
420 if (status == ERROR_SUCCESS) {
421 if (libusb0_symboliclink_index < 256) {
422 // libusb0.sys is connected to this device instance.
423 // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
424 sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
425 usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
427 // libusb0.sys was connected to this device instance at one time; but not anymore.
430 pRegCloseKey(hkey_device_interface);
434 return dev_interface_details;
437 pSetupDiDestroyDeviceInfoList(*dev_info);
438 *dev_info = INVALID_HANDLE_VALUE;
443 * Returns the first known ancestor of a device
445 static struct libusb_device *get_ancestor(struct libusb_context *ctx,
446 DEVINST devinst, PDEVINST _parent_devinst)
448 struct libusb_device *dev = NULL;
449 DEVINST parent_devinst;
451 while (dev == NULL) {
452 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
454 devinst = parent_devinst;
455 dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst);
458 if ((dev != NULL) && (_parent_devinst != NULL))
459 *_parent_devinst = devinst;
465 * Determine which interface the given endpoint address belongs to
467 static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
469 const struct libusb_interface *intf;
470 const struct libusb_interface_descriptor *intf_desc;
473 for (i = 0; i < conf_desc->bNumInterfaces; i++) {
474 intf = &conf_desc->interface[i];
475 for (j = 0; j < intf->num_altsetting; j++) {
476 intf_desc = &intf->altsetting[j];
477 for (k = 0; k < intf_desc->bNumEndpoints; k++) {
478 if (intf_desc->endpoint[k].bEndpointAddress == ep) {
479 usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
480 return intf_desc->bInterfaceNumber;
486 usbi_dbg("endpoint %02X not found on any interface", ep);
487 return LIBUSB_ERROR_NOT_FOUND;
491 * Populate the endpoints addresses of the device_priv interface helper structs
493 static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
496 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
497 struct libusb_config_descriptor *conf_desc;
498 const struct libusb_interface_descriptor *if_desc;
499 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
501 r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc);
502 if (r != LIBUSB_SUCCESS) {
503 usbi_warn(ctx, "could not read config descriptor: error %d", r);
507 if_desc = &conf_desc->interface[iface].altsetting[altsetting];
508 safe_free(priv->usb_interface[iface].endpoint);
510 if (if_desc->bNumEndpoints == 0) {
511 usbi_dbg("no endpoints found for interface %d", iface);
512 libusb_free_config_descriptor(conf_desc);
513 priv->usb_interface[iface].current_altsetting = altsetting;
514 return LIBUSB_SUCCESS;
517 priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
518 if (priv->usb_interface[iface].endpoint == NULL) {
519 libusb_free_config_descriptor(conf_desc);
520 return LIBUSB_ERROR_NO_MEM;
523 priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
524 for (i = 0; i < if_desc->bNumEndpoints; i++) {
525 priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
526 usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface);
528 libusb_free_config_descriptor(conf_desc);
530 // Extra init may be required to configure endpoints
531 if (priv->apib->configure_endpoints)
532 r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface);
534 if (r == LIBUSB_SUCCESS)
535 priv->usb_interface[iface].current_altsetting = altsetting;
540 // Lookup for a match in the list of API driver names
541 // return -1 if not found, driver match number otherwise
542 static int get_sub_api(char *driver, int api)
545 const char sep_str[2] = {LIST_SEPARATOR, 0};
547 size_t len = strlen(driver);
550 return SUB_API_NOTSET;
552 tmp_str = _strdup(driver);
554 return SUB_API_NOTSET;
556 tok = strtok(tmp_str, sep_str);
557 while (tok != NULL) {
558 for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) {
559 if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
564 tok = strtok(NULL, sep_str);
568 return SUB_API_NOTSET;
572 * auto-claiming and auto-release helper functions
574 static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
576 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
577 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(
578 transfer->dev_handle);
579 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
580 int current_interface = *interface_number;
581 int r = LIBUSB_SUCCESS;
584 case USB_API_WINUSBX:
588 return LIBUSB_ERROR_INVALID_PARAM;
591 usbi_mutex_lock(&autoclaim_lock);
592 if (current_interface < 0) { // No serviceable interface was found
593 for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
594 // Must claim an interface of the same API type
595 if ((priv->usb_interface[current_interface].apib->id == api_type)
596 && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
597 usbi_dbg("auto-claimed interface %d for control request", current_interface);
598 if (handle_priv->autoclaim_count[current_interface] != 0)
599 usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
600 handle_priv->autoclaim_count[current_interface]++;
604 if (current_interface == USB_MAXINTERFACES) {
605 usbi_err(ctx, "could not auto-claim any interface");
606 r = LIBUSB_ERROR_NOT_FOUND;
609 // If we have a valid interface that was autoclaimed, we must increment
610 // its autoclaim count so that we can prevent an early release.
611 if (handle_priv->autoclaim_count[current_interface] != 0)
612 handle_priv->autoclaim_count[current_interface]++;
614 usbi_mutex_unlock(&autoclaim_lock);
616 *interface_number = current_interface;
620 static void auto_release(struct usbi_transfer *itransfer)
622 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
623 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
624 libusb_device_handle *dev_handle = transfer->dev_handle;
625 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
628 usbi_mutex_lock(&autoclaim_lock);
629 if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) {
630 handle_priv->autoclaim_count[transfer_priv->interface_number]--;
631 if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
632 r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
633 if (r == LIBUSB_SUCCESS)
634 usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
636 usbi_dbg("failed to auto-release interface %d (%s)",
637 transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
640 usbi_mutex_unlock(&autoclaim_lock);
644 * init: libusb backend init function
646 static int winusb_init(struct libusb_context *ctx)
650 // We need a lock for proper auto-release
651 usbi_mutex_init(&autoclaim_lock);
655 usbi_err(ctx, "could not resolve DLL functions");
656 return LIBUSB_ERROR_OTHER;
659 // Initialize the low level APIs (we don't care about errors at this stage)
660 for (i = 0; i < USB_API_MAX; i++) {
661 if (usb_api_backend[i].init && usb_api_backend[i].init(ctx))
662 usbi_warn(ctx, "error initializing %s backend",
663 usb_api_backend[i].designation);
666 return LIBUSB_SUCCESS;
670 * exit: libusb backend deinitialization function
672 static void winusb_exit(struct libusb_context *ctx)
676 for (i = 0; i < USB_API_MAX; i++) {
677 if (usb_api_backend[i].exit)
678 usb_api_backend[i].exit();
682 usbi_mutex_destroy(&autoclaim_lock);
686 * fetch and cache all the config descriptors through I/O
688 static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
690 struct libusb_context *ctx = DEVICE_CTX(dev);
691 struct winusb_device_priv *priv = _device_priv(dev);
692 DWORD size, ret_size;
695 USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
696 PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request
697 PUSB_CONFIGURATION_DESCRIPTOR cd_data;
699 if (dev->num_configurations == 0)
702 priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
703 if (priv->config_descriptor == NULL) {
704 usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
708 for (i = 0; i <= dev->num_configurations; i++) {
709 safe_free(cd_buf_actual);
711 if (i == dev->num_configurations)
714 size = sizeof(cd_buf_short);
715 memset(&cd_buf_short, 0, size);
717 cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number;
718 cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
719 cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR;
720 cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i;
721 cd_buf_short.req.SetupPacket.wIndex = 0;
722 cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR);
724 // Dummy call to get the required data size. Initial failures are reported as info rather
725 // than error as they can occur for non-penalizing situations, such as with some hubs.
726 // coverity[tainted_data_argument]
727 if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
728 &cd_buf_short, size, &ret_size, NULL)) {
729 usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0));
733 if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
734 usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id);
738 size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength;
739 cd_buf_actual = malloc(size);
740 if (cd_buf_actual == NULL) {
741 usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
746 cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number;
747 cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
748 cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR;
749 cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i;
750 cd_buf_actual->SetupPacket.wIndex = 0;
751 cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength;
753 if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
754 cd_buf_actual, size, &ret_size, NULL)) {
755 usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0));
759 cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
761 if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) {
762 usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id);
766 if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) {
767 usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id);
771 usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
772 i, cd_data->bConfigurationValue, cd_data->wTotalLength);
774 // Cache the descriptor
775 priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
776 if (priv->config_descriptor[i] != NULL) {
777 memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
779 usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
785 * Populate a libusb device structure
787 static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev,
788 uint8_t port_number, DEVINST devinst)
790 struct libusb_context *ctx;
791 struct libusb_device *tmp_dev;
792 struct winusb_device_priv *priv, *parent_priv;
793 USB_NODE_CONNECTION_INFORMATION_EX conn_info;
794 USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
797 uint8_t bus_number, depth;
801 priv = _device_priv(dev);
803 // If the device is already initialized, we can stop here
804 if (priv->initialized)
805 return LIBUSB_SUCCESS;
807 if (parent_dev != NULL) { // Not a HCD root hub
808 ctx = DEVICE_CTX(dev);
809 parent_priv = _device_priv(parent_dev);
810 if (parent_priv->apib->id != USB_API_HUB) {
811 usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id);
812 return LIBUSB_ERROR_NOT_FOUND;
815 // Calculate depth and fetch bus number
816 bus_number = parent_dev->bus_number;
817 if (bus_number == 0) {
818 tmp_dev = get_ancestor(ctx, devinst, &devinst);
819 if (tmp_dev != parent_dev) {
820 usbi_err(ctx, "program assertion failed - first ancestor is not parent");
821 return LIBUSB_ERROR_NOT_FOUND;
823 libusb_unref_device(tmp_dev);
825 for (depth = 1; bus_number == 0; depth++) {
826 tmp_dev = get_ancestor(ctx, devinst, &devinst);
827 if (tmp_dev->bus_number != 0) {
828 bus_number = tmp_dev->bus_number;
829 depth += _device_priv(tmp_dev)->depth;
831 libusb_unref_device(tmp_dev);
834 depth = parent_priv->depth + 1;
837 if (bus_number == 0) {
838 usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id);
839 return LIBUSB_ERROR_NOT_FOUND;
842 dev->bus_number = bus_number;
843 dev->port_number = port_number;
844 dev->parent_dev = parent_dev;
847 hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
849 if (hub_handle == INVALID_HANDLE_VALUE) {
850 usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0));
851 return LIBUSB_ERROR_ACCESS;
854 memset(&conn_info, 0, sizeof(conn_info));
855 conn_info.ConnectionIndex = (ULONG)port_number;
856 // coverity[tainted_data_argument]
859 if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info),
860 &conn_info, sizeof(conn_info), &size, NULL)) {
861 usbi_warn(ctx, "could not get node connection information for device '%s': %s",
862 priv->dev_id, windows_error_str(0));
863 CloseHandle(hub_handle);
864 return LIBUSB_ERROR_NO_DEVICE;
867 if (conn_info.ConnectionStatus == NoDeviceConnected) {
868 usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id);
869 CloseHandle(hub_handle);
870 return LIBUSB_ERROR_NO_DEVICE;
873 memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
874 dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
875 priv->active_config = conn_info.CurrentConfigurationValue;
876 if (priv->active_config == 0) {
877 usbi_dbg("0x%x:0x%x found %u configurations (active conf: %u) \n",
878 priv->dev_descriptor.idVendor,
879 priv->dev_descriptor.idProduct,
880 dev->num_configurations,
881 priv->active_config);
883 if (priv->active_config == 0)
885 } while (priv->active_config == 0 && --ginfotimeout >= 0);
887 if (priv->active_config == 0) {
888 usbi_dbg("after try 0x%x:0x%x found %u configurations (active conf: %u) \n",
889 priv->dev_descriptor.idVendor,
890 priv->dev_descriptor.idProduct,
891 dev->num_configurations,
892 priv->active_config);
893 usbi_dbg("Force this device active config to 1 in libusb! \nNOTICE: Should not reach this place!!!!!! \n");
894 priv->active_config = 1;
897 usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
899 // Cache as many config descriptors as we can
900 cache_config_descriptors(dev, hub_handle);
902 // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
903 if (windows_version >= WINDOWS_8) {
904 conn_info_v2.ConnectionIndex = (ULONG)port_number;
905 conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2);
906 conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
907 if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
908 &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) {
909 usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
910 priv->dev_id, windows_error_str(0));
911 } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) {
913 } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
918 CloseHandle(hub_handle);
920 if (conn_info.DeviceAddress > UINT8_MAX)
921 usbi_err(ctx, "program assertion failed - device address overflow");
923 dev->device_address = (uint8_t)conn_info.DeviceAddress;
925 switch (conn_info.Speed) {
926 case 0: dev->speed = LIBUSB_SPEED_LOW; break;
927 case 1: dev->speed = LIBUSB_SPEED_FULL; break;
928 case 2: dev->speed = LIBUSB_SPEED_HIGH; break;
929 case 3: dev->speed = LIBUSB_SPEED_SUPER; break;
930 case 4: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
932 usbi_warn(ctx, "unknown device speed %u", conn_info.Speed);
937 r = usbi_sanitize_device(dev);
941 priv->initialized = true;
943 usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
944 dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id);
946 return LIBUSB_SUCCESS;
949 static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id,
950 uint8_t bus_number, DEVINST devinst)
952 struct libusb_device *dev;
953 struct winusb_device_priv *priv;
954 unsigned long session_id;
955 DEVINST child_devinst;
957 if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) {
958 usbi_warn(ctx, "could not get child devinst for '%s'", dev_id);
959 return LIBUSB_SUCCESS;
962 session_id = (unsigned long)child_devinst;
963 dev = usbi_get_device_by_session_id(ctx, session_id);
965 usbi_warn(ctx, "program assertion failed - HCD '%s' child not found", dev_id);
966 return LIBUSB_SUCCESS;
969 if (dev->bus_number == 0) {
971 usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number);
972 priv = _device_priv(dev);
973 dev->bus_number = bus_number;
974 dev->num_configurations = 1;
975 priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE;
976 priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
977 priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB;
978 priv->dev_descriptor.bNumConfigurations = 1;
979 priv->active_config = 1;
980 priv->root_hub = true;
981 if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) {
982 usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id);
983 priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
984 priv->dev_descriptor.idProduct = 1;
988 libusb_unref_device(dev);
989 return LIBUSB_SUCCESS;
992 // Returns the api type, or 0 if not found/unsupported
993 static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
994 SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
996 // Precedence for filter drivers vs driver is in the order of this array
997 struct driver_lookup lookup[3] = {
998 {"\0\0", SPDRP_SERVICE, "driver"},
999 {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"},
1000 {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"}
1002 DWORD size, reg_type;
1006 // Check the service & filter names to know the API we should use
1007 for (k = 0; k < 3; k++) {
1008 if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop,
1009 ®_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) {
1010 // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
1011 if (lookup[k].reg_prop == SPDRP_SERVICE)
1012 // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed
1013 lookup[k].list[strlen(lookup[k].list) + 1] = 0;
1015 // MULTI_SZ is a pain to work with. Turn it into something much more manageable
1016 // NB: none of the driver names we check against contain LIST_SEPARATOR,
1017 // (currently ';'), so even if an unsuported one does, it's not an issue
1018 for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) {
1019 if (lookup[k].list[l] == 0)
1020 lookup[k].list[l] = LIST_SEPARATOR;
1022 usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
1024 if (GetLastError() != ERROR_INVALID_DATA)
1025 usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
1026 lookup[k].list[0] = 0;
1030 for (i = 2; i < USB_API_MAX; i++) {
1031 for (k = 0; k < 3; k++) {
1032 j = get_sub_api(lookup[k].list, i);
1034 usbi_dbg("matched %s name against %s", lookup[k].designation,
1035 (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]);
1044 static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev,
1045 char *dev_interface_path, char *device_id, int api, int sub_api)
1047 struct winusb_device_priv *priv = _device_priv(dev);
1048 int interface_number;
1051 // Because MI_## are not necessarily in sequential order (some composite
1052 // devices will have only MI_00 & MI_03 for instance), we retrieve the actual
1053 // interface number from the path's MI value
1054 mi_str = strstr(device_id, "MI_");
1055 if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) {
1056 interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0');
1058 usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id);
1059 interface_number = 0;
1062 if (interface_number >= USB_MAXINTERFACES) {
1063 usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path);
1064 return LIBUSB_ERROR_ACCESS;
1067 if (priv->usb_interface[interface_number].path != NULL) {
1068 if (api == USB_API_HID) {
1069 // HID devices can have multiple collections (COL##) for each MI_## interface
1070 usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
1071 interface_number, device_id);
1072 return LIBUSB_ERROR_ACCESS;
1074 // In other cases, just use the latest data
1075 safe_free(priv->usb_interface[interface_number].path);
1078 usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
1079 priv->usb_interface[interface_number].path = dev_interface_path;
1080 priv->usb_interface[interface_number].apib = &usb_api_backend[api];
1081 priv->usb_interface[interface_number].sub_api = sub_api;
1082 if ((api == USB_API_HID) && (priv->hid == NULL)) {
1083 priv->hid = calloc(1, sizeof(struct hid_device_priv));
1084 if (priv->hid == NULL)
1085 return LIBUSB_ERROR_NO_MEM;
1088 return LIBUSB_SUCCESS;
1091 static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
1092 char *dev_interface_path)
1095 struct winusb_device_priv *priv = _device_priv(dev);
1097 if (priv->hid == NULL) {
1098 usbi_err(ctx, "program assertion failed: parent is not HID");
1099 return LIBUSB_ERROR_NO_DEVICE;
1100 } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
1101 usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
1102 return LIBUSB_ERROR_NO_DEVICE;
1105 for (i = 0; i < priv->hid->nb_interfaces; i++) {
1106 if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
1107 usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
1108 return LIBUSB_ERROR_ACCESS;
1112 priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
1113 priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
1114 usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
1115 priv->hid->nb_interfaces++;
1116 return LIBUSB_SUCCESS;
1120 * get_device_list: libusb backend device enumeration function
1122 static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
1124 struct discovered_devs *discdevs;
1125 HDEVINFO *dev_info, dev_info_intf, dev_info_enum;
1126 SP_DEVINFO_DATA dev_info_data;
1129 int r = LIBUSB_SUCCESS;
1131 unsigned int pass, i, j;
1132 char enumerator[16];
1133 char dev_id[MAX_PATH_LENGTH];
1134 struct libusb_device *dev, *parent_dev;
1135 struct winusb_device_priv *priv, *parent_priv;
1136 char *dev_interface_path = NULL;
1137 unsigned long session_id;
1138 DWORD size, port_nr, reg_type, install_state;
1140 WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
1149 // Keep a list of guids that will be enumerated
1150 #define GUID_SIZE_STEP 8
1151 const GUID **guid_list, **new_guid_list;
1152 unsigned int guid_size = GUID_SIZE_STEP;
1153 unsigned int nb_guids;
1154 // Keep a list of PnP enumerator strings that are found
1155 char *usb_enumerator[8] = { "USB" };
1156 unsigned int nb_usb_enumerators = 1;
1157 unsigned int usb_enum_index = 0;
1158 // Keep a list of newly allocated devs to unref
1159 #define UNREF_SIZE_STEP 16
1160 libusb_device **unref_list, **new_unref_list;
1161 unsigned int unref_size = UNREF_SIZE_STEP;
1162 unsigned int unref_cur = 0;
1164 // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
1165 // PASS 2 : (re)enumerate HUBS
1166 // PASS 3 : (re)enumerate generic USB devices (including driverless)
1167 // and list additional USB device interface GUIDs to explore
1168 // PASS 4 : (re)enumerate master USB devices that have a device interface
1169 // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and
1170 // set the device interfaces.
1172 // Init the GUID table
1173 guid_list = malloc(guid_size * sizeof(void *));
1174 if (guid_list == NULL) {
1175 usbi_err(ctx, "failed to alloc guid list");
1176 return LIBUSB_ERROR_NO_MEM;
1179 guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB;
1180 guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
1181 guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
1182 guid_list[GEN_PASS] = NULL;
1183 if (api_hid_available) {
1184 HidD_GetHidGuid(&hid_guid);
1185 guid_list[HID_PASS] = &hid_guid;
1187 guid_list[HID_PASS] = NULL;
1189 nb_guids = EXT_PASS;
1191 unref_list = malloc(unref_size * sizeof(void *));
1192 if (unref_list == NULL) {
1193 usbi_err(ctx, "failed to alloc unref list");
1194 free((void *)guid_list);
1195 return LIBUSB_ERROR_NO_MEM;
1198 dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
1199 if (dev_info_intf == INVALID_HANDLE_VALUE) {
1200 usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0));
1202 free((void *)guid_list);
1203 return LIBUSB_ERROR_OTHER;
1206 for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
1207 //#define ENUM_DEBUG
1208 #if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
1209 const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"};
1210 usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass]));
1212 if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL))
1215 dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum;
1217 for (i = 0; ; i++) {
1218 // safe loop: free up any (unprotected) dynamic resource
1219 // NB: this is always executed before breaking the loop
1220 safe_free(dev_interface_path);
1221 priv = parent_priv = NULL;
1222 dev = parent_dev = NULL;
1224 // Safe loop: end of loop conditions
1225 if (r != LIBUSB_SUCCESS)
1228 if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
1229 usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX);
1233 if (pass != GEN_PASS) {
1234 // Except for GEN, all passes deal with device interfaces
1235 r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path);
1236 if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) {
1241 // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
1242 // being listed under the "NUSB3" PnP Symbolic Name rather than "USB".
1243 // The Intel USB 3.0 driver behaves similar, but uses "IUSB3"
1244 // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3"
1245 for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) {
1246 if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i))
1250 if (usb_enum_index == nb_usb_enumerators)
1254 // Read the Device ID path
1255 if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) {
1256 usbi_warn(ctx, "could not read the device instance ID for devInst %lX, skipping",
1257 dev_info_data.DevInst);
1262 usbi_dbg("PRO: %s", dev_id);
1265 // Set API to use or get additional data from generic pass
1266 api = USB_API_UNSUPPORTED;
1267 sub_api = SUB_API_NOTSET;
1273 // Fetch the PnP enumerator class for this hub
1274 // This will allow us to enumerate all classes during the GEN pass
1275 if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
1276 NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) {
1277 usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0));
1278 LOOP_BREAK(LIBUSB_ERROR_OTHER);
1280 for (j = 0; j < nb_usb_enumerators; j++) {
1281 if (strcmp(usb_enumerator[j], enumerator) == 0)
1284 if (j == nb_usb_enumerators) {
1285 usbi_dbg("found new PnP enumerator string '%s'", enumerator);
1286 if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) {
1287 usb_enumerator[nb_usb_enumerators] = _strdup(enumerator);
1288 if (usb_enumerator[nb_usb_enumerators] != NULL) {
1289 nb_usb_enumerators++;
1291 usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator);
1292 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1295 usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible");
1300 // We use the GEN pass to detect driverless devices...
1301 if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER,
1302 NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
1303 usbi_info(ctx, "The following device has no driver: '%s'", dev_id);
1304 usbi_info(ctx, "libusb will not be able to access it");
1306 // ...and to add the additional device interface GUIDs
1307 key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
1308 if (key == INVALID_HANDLE_VALUE)
1310 // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order
1311 size = sizeof(guid_string_w);
1312 s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type,
1313 (LPBYTE)guid_string_w, &size);
1314 if (s == ERROR_FILE_NOT_FOUND)
1315 s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, ®_type,
1316 (LPBYTE)guid_string_w, &size);
1318 if ((s == ERROR_SUCCESS) &&
1319 (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) ||
1320 ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) {
1321 if (nb_guids == guid_size) {
1322 new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *));
1323 if (new_guid_list == NULL) {
1324 usbi_err(ctx, "failed to realloc guid list");
1325 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1327 guid_list = new_guid_list;
1328 guid_size += GUID_SIZE_STEP;
1330 if_guid = malloc(sizeof(*if_guid));
1331 if (if_guid == NULL) {
1332 usbi_err(ctx, "failed to alloc if_guid");
1333 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1335 if (pIIDFromString(guid_string_w, if_guid) != 0) {
1336 usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id);
1339 // Check if we've already seen this GUID
1340 for (j = EXT_PASS; j < nb_guids; j++) {
1341 if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0)
1344 if (j == nb_guids) {
1345 usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
1346 guid_list[nb_guids++] = if_guid;
1348 // Duplicate, ignore
1352 } else if (s == ERROR_SUCCESS) {
1353 usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id);
1360 // Get the API type (after checking that the driver installation is OK)
1361 if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
1362 NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) {
1363 usbi_warn(ctx, "could not detect installation state of driver for '%s': %s",
1364 dev_id, windows_error_str(0));
1365 } else if (install_state != 0) {
1366 usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping",
1367 dev_id, (unsigned int)install_state);
1370 get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api);
1374 // Find parent device (for the passes that need it)
1375 if (pass >= GEN_PASS) {
1376 parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL);
1377 if (parent_dev == NULL) {
1378 // Root hubs will not have a parent
1379 dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst);
1381 priv = _device_priv(dev);
1384 libusb_unref_device(dev);
1387 usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
1391 parent_priv = _device_priv(parent_dev);
1392 // virtual USB devices are also listed during GEN - don't process these yet
1393 if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) {
1394 libusb_unref_device(parent_dev);
1399 // Create new or match existing device, using the devInst as session id
1400 if ((pass <= GEN_PASS) && (pass != HCD_PASS)) { // For subsequent passes, we'll lookup the parent
1401 // These are the passes that create "new" devices
1402 session_id = (unsigned long)dev_info_data.DevInst;
1403 dev = usbi_get_device_by_session_id(ctx, session_id);
1406 usbi_dbg("allocating new device for session [%lX]", session_id);
1407 dev = usbi_alloc_device(ctx, session_id);
1409 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1411 priv = winusb_device_priv_init(dev);
1412 priv->dev_id = _strdup(dev_id);
1413 if (priv->dev_id == NULL) {
1414 libusb_unref_device(dev);
1415 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1418 usbi_dbg("found existing device for session [%lX]", session_id);
1420 priv = _device_priv(dev);
1421 if (strcmp(priv->dev_id, dev_id) != 0) {
1422 usbi_dbg("device instance ID for session [%lX] changed", session_id);
1423 usbi_disconnect_device(dev);
1424 libusb_unref_device(dev);
1430 // Keep track of devices that need unref
1431 if (unref_cur == unref_size) {
1432 new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *));
1433 if (new_unref_list == NULL) {
1434 usbi_err(ctx, "could not realloc list for unref - aborting");
1435 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1437 unref_list = new_unref_list;
1438 unref_size += UNREF_SIZE_STEP;
1440 unref_list[unref_cur++] = dev;
1447 // If the device has already been setup, don't do it again
1448 if (priv->path != NULL)
1450 // Take care of API initialization
1451 priv->path = dev_interface_path;
1452 dev_interface_path = NULL;
1453 priv->apib = &usb_api_backend[api];
1454 priv->sub_api = sub_api;
1456 case USB_API_COMPOSITE:
1460 priv->hid = calloc(1, sizeof(struct hid_device_priv));
1461 if (priv->hid == NULL)
1462 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1465 // For other devices, the first interface is the same as the device
1466 priv->usb_interface[0].path = _strdup(priv->path);
1467 if (priv->usb_interface[0].path == NULL)
1468 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1469 // The following is needed if we want API calls to work for both simple
1470 // and composite devices.
1471 for (j = 0; j < USB_MAXINTERFACES; j++)
1472 priv->usb_interface[j].apib = &usb_api_backend[api];
1477 r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst);
1480 // The SPDRP_ADDRESS for USB devices is the device port number on the hub
1482 if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS,
1483 NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr)))
1484 usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0));
1485 r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst);
1486 if (r == LIBUSB_SUCCESS) {
1487 // Append device to the list of discovered devices
1488 discdevs = discovered_devs_append(*_discdevs, dev);
1490 LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1492 *_discdevs = discdevs;
1493 } else if (r == LIBUSB_ERROR_NO_DEVICE) {
1494 // This can occur if the device was disconnected but Windows hasn't
1495 // refreshed its enumeration yet - in that case, we ignore the device
1499 default: // HID_PASS and later
1500 if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) {
1501 if (parent_priv->apib->id == USB_API_HID) {
1502 usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
1503 r = set_hid_interface(ctx, parent_dev, dev_interface_path);
1505 usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
1506 r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api);
1509 case LIBUSB_SUCCESS:
1510 dev_interface_path = NULL;
1512 case LIBUSB_ERROR_ACCESS:
1513 // interface has already been set => make sure dev_interface_path is freed then
1521 libusb_unref_device(parent_dev);
1527 pSetupDiDestroyDeviceInfoList(dev_info_intf);
1529 // Free any additional GUIDs
1530 for (pass = EXT_PASS; pass < nb_guids; pass++)
1531 free((void *)guid_list[pass]);
1532 free((void *)guid_list);
1534 // Free any PnP enumerator strings
1535 for (i = 1; i < nb_usb_enumerators; i++)
1536 free(usb_enumerator[i]);
1538 // Unref newly allocated devs
1539 for (i = 0; i < unref_cur; i++)
1540 libusb_unref_device(unref_list[i]);
1546 static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
1548 struct winusb_device_priv *priv = _device_priv(dev);
1550 memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH);
1551 return LIBUSB_SUCCESS;
1554 static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len)
1556 struct winusb_device_priv *priv = _device_priv(dev);
1557 PUSB_CONFIGURATION_DESCRIPTOR config_header;
1560 // config index is zero based
1561 if (config_index >= dev->num_configurations)
1562 return LIBUSB_ERROR_INVALID_PARAM;
1564 if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
1565 return LIBUSB_ERROR_NOT_FOUND;
1567 config_header = priv->config_descriptor[config_index];
1569 size = MIN(config_header->wTotalLength, len);
1570 memcpy(buffer, priv->config_descriptor[config_index], size);
1574 static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
1575 unsigned char **buffer)
1577 struct winusb_device_priv *priv = _device_priv(dev);
1578 PUSB_CONFIGURATION_DESCRIPTOR config_header;
1581 if (priv->config_descriptor == NULL)
1582 return LIBUSB_ERROR_NOT_FOUND;
1584 for (index = 0; index < dev->num_configurations; index++) {
1585 config_header = priv->config_descriptor[index];
1586 if (config_header == NULL)
1588 if (config_header->bConfigurationValue == bConfigurationValue) {
1589 *buffer = (unsigned char *)priv->config_descriptor[index];
1590 return (int)config_header->wTotalLength;
1594 return LIBUSB_ERROR_NOT_FOUND;
1598 * return the cached copy of the active config descriptor
1600 static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len)
1602 struct winusb_device_priv *priv = _device_priv(dev);
1603 unsigned char *config_desc;
1606 if (priv->active_config == 0)
1607 return LIBUSB_ERROR_NOT_FOUND;
1609 r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc);
1613 len = MIN((size_t)r, len);
1614 memcpy(buffer, config_desc, len);
1618 static int winusb_open(struct libusb_device_handle *dev_handle)
1620 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1622 CHECK_SUPPORTED_API(priv->apib, open);
1624 return priv->apib->open(SUB_API_NOTSET, dev_handle);
1627 static void winusb_close(struct libusb_device_handle *dev_handle)
1629 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1631 if (priv->apib->close)
1632 priv->apib->close(SUB_API_NOTSET, dev_handle);
1635 static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config)
1637 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1639 if (priv->active_config == 0) {
1641 return LIBUSB_ERROR_NOT_FOUND;
1644 *config = priv->active_config;
1645 return LIBUSB_SUCCESS;
1649 * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver
1650 * does not currently expose a service that allows higher-level drivers to set
1651 * the configuration."
1653 static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config)
1655 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1656 int r = LIBUSB_SUCCESS;
1658 if (config >= USB_MAXCONFIG)
1659 return LIBUSB_ERROR_INVALID_PARAM;
1661 r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
1662 LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
1663 LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
1666 if (r == LIBUSB_SUCCESS)
1667 priv->active_config = (uint8_t)config;
1672 static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface)
1674 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1677 CHECK_SUPPORTED_API(priv->apib, claim_interface);
1679 safe_free(priv->usb_interface[iface].endpoint);
1680 priv->usb_interface[iface].nb_endpoints = 0;
1682 r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface);
1684 if (r == LIBUSB_SUCCESS)
1685 r = windows_assign_endpoints(dev_handle, iface, 0);
1690 static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
1692 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1695 CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting);
1697 safe_free(priv->usb_interface[iface].endpoint);
1698 priv->usb_interface[iface].nb_endpoints = 0;
1700 r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting);
1702 if (r == LIBUSB_SUCCESS)
1703 r = windows_assign_endpoints(dev_handle, iface, altsetting);
1708 static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface)
1710 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1712 CHECK_SUPPORTED_API(priv->apib, release_interface);
1714 return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
1717 static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
1719 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1721 CHECK_SUPPORTED_API(priv->apib, clear_halt);
1723 return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
1726 static int winusb_reset_device(struct libusb_device_handle *dev_handle)
1728 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
1730 CHECK_SUPPORTED_API(priv->apib, reset_device);
1732 return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
1735 static void winusb_destroy_device(struct libusb_device *dev)
1737 winusb_device_priv_release(dev);
1740 static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
1742 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1743 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1744 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1745 int sub_api = priv->sub_api;
1747 usbi_close(transfer_priv->pollable_fd.fd);
1748 transfer_priv->pollable_fd = INVALID_WINFD;
1749 transfer_priv->handle = NULL;
1750 safe_free(transfer_priv->hid_buffer);
1752 if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && sub_api == SUB_API_WINUSB) {
1753 if (transfer_priv->isoch_buffer_handle != NULL) {
1754 if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
1755 transfer_priv->isoch_buffer_handle = NULL;
1757 usbi_dbg("Couldn't unregister isoch buffer!");
1762 safe_free(transfer_priv->iso_context);
1764 // When auto claim is in use, attempt to release the auto-claimed interface
1765 auto_release(itransfer);
1768 static int do_submit_transfer(struct usbi_transfer *itransfer, short events,
1769 int (*transfer_fn)(int, struct usbi_transfer *))
1771 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
1772 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1776 wfd = usbi_create_fd();
1778 return LIBUSB_ERROR_NO_MEM;
1780 r = usbi_add_pollfd(ctx, wfd.fd, events);
1786 // Use transfer_priv to store data needed for async polling
1787 transfer_priv->pollable_fd = wfd;
1789 r = transfer_fn(SUB_API_NOTSET, itransfer);
1791 if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) {
1792 usbi_remove_pollfd(ctx, wfd.fd);
1794 transfer_priv->pollable_fd = INVALID_WINFD;
1800 static int winusb_submit_transfer(struct usbi_transfer *itransfer)
1802 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1803 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1804 int (*transfer_fn)(int, struct usbi_transfer *);
1807 switch (transfer->type) {
1808 case LIBUSB_TRANSFER_TYPE_CONTROL:
1809 events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
1810 transfer_fn = priv->apib->submit_control_transfer;
1812 case LIBUSB_TRANSFER_TYPE_BULK:
1813 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1814 if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
1815 return LIBUSB_ERROR_NOT_SUPPORTED;
1816 events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
1817 transfer_fn = priv->apib->submit_bulk_transfer;
1819 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
1820 events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
1821 transfer_fn = priv->apib->submit_iso_transfer;
1823 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
1824 return LIBUSB_ERROR_NOT_SUPPORTED;
1826 usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
1827 return LIBUSB_ERROR_INVALID_PARAM;
1830 if (transfer_fn == NULL) {
1831 usbi_warn(TRANSFER_CTX(transfer),
1832 "unsupported transfer type %d (unrecognized device driver)",
1834 return LIBUSB_ERROR_NOT_SUPPORTED;
1837 return do_submit_transfer(itransfer, events, transfer_fn);
1840 static int windows_abort_control(struct usbi_transfer *itransfer)
1842 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1843 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1845 CHECK_SUPPORTED_API(priv->apib, abort_control);
1847 return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
1850 static int windows_abort_transfers(struct usbi_transfer *itransfer)
1852 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1853 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1855 CHECK_SUPPORTED_API(priv->apib, abort_transfers);
1857 return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
1860 static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
1862 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1864 switch (transfer->type) {
1865 case LIBUSB_TRANSFER_TYPE_CONTROL:
1866 return windows_abort_control(itransfer);
1867 case LIBUSB_TRANSFER_TYPE_BULK:
1868 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1869 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
1870 return windows_abort_transfers(itransfer);
1871 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
1872 return LIBUSB_ERROR_NOT_SUPPORTED;
1874 usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
1875 return LIBUSB_ERROR_INVALID_PARAM;
1879 static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
1881 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1882 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
1883 return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
1886 static int winusb_get_transfer_fd(struct usbi_transfer *itransfer)
1888 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1889 return transfer_priv->pollable_fd.fd;
1892 static void winusb_get_overlapped_result(struct usbi_transfer *itransfer,
1893 DWORD *io_result, DWORD *io_size)
1895 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
1896 struct winfd *pollable_fd = &transfer_priv->pollable_fd;
1898 if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
1899 *io_result = NO_ERROR;
1900 *io_size = (DWORD)pollable_fd->overlapped->InternalHigh;
1901 } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) {
1902 // Regular async overlapped
1903 *io_result = NO_ERROR;
1905 *io_result = GetLastError();
1909 // NB: MSVC6 does not support named initializers.
1910 const struct windows_backend winusb_backend = {
1913 winusb_get_device_list,
1916 winusb_get_device_descriptor,
1917 winusb_get_active_config_descriptor,
1918 winusb_get_config_descriptor,
1919 winusb_get_config_descriptor_by_value,
1920 winusb_get_configuration,
1921 winusb_set_configuration,
1922 winusb_claim_interface,
1923 winusb_release_interface,
1924 winusb_set_interface_altsetting,
1926 winusb_reset_device,
1927 winusb_destroy_device,
1928 winusb_submit_transfer,
1929 winusb_cancel_transfer,
1930 winusb_clear_transfer_priv,
1931 winusb_copy_transfer_data,
1932 winusb_get_transfer_fd,
1933 winusb_get_overlapped_result,
1940 static const char * const composite_driver_names[] = {"USBCCGP"};
1941 static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"};
1942 static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
1943 const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
1945 USB_API_UNSUPPORTED,
1947 // No supported operations
1952 // No supported operations
1957 composite_driver_names,
1958 ARRAYSIZE(composite_driver_names),
1963 NULL, /* configure_endpoints */
1964 composite_claim_interface,
1965 composite_set_interface_altsetting,
1966 composite_release_interface,
1967 composite_clear_halt,
1968 composite_reset_device,
1969 composite_submit_bulk_transfer,
1970 composite_submit_iso_transfer,
1971 composite_submit_control_transfer,
1972 composite_abort_control,
1973 composite_abort_transfers,
1974 composite_copy_transfer_data,
1979 winusbx_driver_names,
1980 ARRAYSIZE(winusbx_driver_names),
1985 winusbx_configure_endpoints,
1986 winusbx_claim_interface,
1987 winusbx_set_interface_altsetting,
1988 winusbx_release_interface,
1990 winusbx_reset_device,
1991 winusbx_submit_bulk_transfer,
1992 winusbx_submit_iso_transfer,
1993 winusbx_submit_control_transfer,
1994 winusbx_abort_control,
1995 winusbx_abort_transfers,
1996 winusbx_copy_transfer_data,
2002 ARRAYSIZE(hid_driver_names),
2007 NULL, /* configure_endpoints */
2008 hid_claim_interface,
2009 hid_set_interface_altsetting,
2010 hid_release_interface,
2013 hid_submit_bulk_transfer,
2014 NULL, /* submit_iso_transfer */
2015 hid_submit_control_transfer,
2016 hid_abort_transfers,
2017 hid_abort_transfers,
2018 hid_copy_transfer_data,
2024 * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
2026 #define WinUSBX_Set(fn) \
2028 if (native_winusb) \
2029 WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
2031 pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \
2034 #define NativeWinUSBOnly_Set(fn) \
2036 if (native_winusb) \
2037 WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
2039 WinUSBX[i].fn = NULL; \
2042 static int winusbx_init(struct libusb_context *ctx)
2047 KLIB_VERSION LibK_Version;
2048 LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
2049 LibK_GetVersion_t pLibK_GetVersion;
2051 h = LoadLibraryA("libusbK");
2054 usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
2055 h = LoadLibraryA("WinUSB");
2058 usbi_warn(ctx, "WinUSB DLL is not available either, "
2059 "you will not be able to access devices outside of enumeration");
2060 return LIBUSB_ERROR_NOT_FOUND;
2063 usbi_dbg("using libusbK DLL for universal access");
2064 pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
2065 if (pLibK_GetVersion != NULL) {
2066 pLibK_GetVersion(&LibK_Version);
2067 usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
2068 LibK_Version.Micro, LibK_Version.Nano);
2070 pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
2071 if (pLibK_GetProcAddress == NULL) {
2072 usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
2074 return LIBUSB_ERROR_NOT_FOUND;
2078 native_winusb = (pLibK_GetProcAddress == NULL);
2079 for (i = 0; i < SUB_API_MAX; i++) {
2080 WinUSBX_Set(AbortPipe);
2081 WinUSBX_Set(ControlTransfer);
2082 WinUSBX_Set(FlushPipe);
2084 WinUSBX_Set(GetAssociatedInterface);
2085 WinUSBX_Set(Initialize);
2086 WinUSBX_Set(ReadPipe);
2088 WinUSBX_Set(ResetDevice);
2089 WinUSBX_Set(ResetPipe);
2090 WinUSBX_Set(SetCurrentAlternateSetting);
2091 WinUSBX_Set(SetPipePolicy);
2092 WinUSBX_Set(WritePipe);
2093 WinUSBX_Set(IsoReadPipe);
2094 WinUSBX_Set(IsoWritePipe);
2095 NativeWinUSBOnly_Set(RegisterIsochBuffer);
2096 NativeWinUSBOnly_Set(UnregisterIsochBuffer);
2097 NativeWinUSBOnly_Set(WriteIsochPipeAsap);
2098 NativeWinUSBOnly_Set(ReadIsochPipeAsap);
2099 NativeWinUSBOnly_Set(QueryPipeEx);
2101 if (WinUSBX[i].Initialize != NULL) {
2102 WinUSBX[i].initialized = true;
2103 // Assume driver supports CancelIoEx()
2104 WinUSBX[i].CancelIoEx_supported = true;
2105 usbi_dbg("initalized sub API %s", winusbx_driver_names[i]);
2107 usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]);
2108 WinUSBX[i].initialized = false;
2113 return LIBUSB_SUCCESS;
2116 static void winusbx_exit(void)
2118 if (WinUSBX_handle != NULL) {
2119 FreeLibrary(WinUSBX_handle);
2120 WinUSBX_handle = NULL;
2122 /* Reset the WinUSBX API structures */
2123 memset(&WinUSBX, 0, sizeof(WinUSBX));
2127 // NB: open and close must ensure that they only handle interface of
2128 // the right API type, as these functions can be called wholesale from
2129 // composite_open(), with interfaces belonging to different APIs
2130 static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
2132 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2133 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2134 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2138 CHECK_WINUSBX_AVAILABLE(sub_api);
2140 // WinUSB requires a separate handle for each interface
2141 for (i = 0; i < USB_MAXINTERFACES; i++) {
2142 if ((priv->usb_interface[i].path != NULL)
2143 && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
2144 file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
2145 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2146 if (file_handle == INVALID_HANDLE_VALUE) {
2147 usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
2148 switch (GetLastError()) {
2149 case ERROR_FILE_NOT_FOUND: // The device was disconnected
2150 return LIBUSB_ERROR_NO_DEVICE;
2151 case ERROR_ACCESS_DENIED:
2152 return LIBUSB_ERROR_ACCESS;
2154 return LIBUSB_ERROR_IO;
2157 handle_priv->interface_handle[i].dev_handle = file_handle;
2161 return LIBUSB_SUCCESS;
2164 static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
2166 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2167 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2171 if (sub_api == SUB_API_NOTSET)
2172 sub_api = priv->sub_api;
2174 if (!WinUSBX[sub_api].initialized)
2177 if (priv->apib->id == USB_API_COMPOSITE) {
2178 // If this is a composite device, just free and close all WinUSB-like
2179 // interfaces directly (each is independent and not associated with another)
2180 for (i = 0; i < USB_MAXINTERFACES; i++) {
2181 if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
2182 handle = handle_priv->interface_handle[i].api_handle;
2183 if (HANDLE_VALID(handle))
2184 WinUSBX[sub_api].Free(handle);
2186 handle = handle_priv->interface_handle[i].dev_handle;
2187 if (HANDLE_VALID(handle))
2188 CloseHandle(handle);
2192 // If this is a WinUSB device, free all interfaces above interface 0,
2193 // then free and close interface 0 last
2194 for (i = 1; i < USB_MAXINTERFACES; i++) {
2195 handle = handle_priv->interface_handle[i].api_handle;
2196 if (HANDLE_VALID(handle))
2197 WinUSBX[sub_api].Free(handle);
2199 handle = handle_priv->interface_handle[0].api_handle;
2200 if (HANDLE_VALID(handle))
2201 WinUSBX[sub_api].Free(handle);
2203 handle = handle_priv->interface_handle[0].dev_handle;
2204 if (HANDLE_VALID(handle))
2205 CloseHandle(handle);
2209 static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2211 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2212 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2213 HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
2216 uint8_t endpoint_address;
2219 CHECK_WINUSBX_AVAILABLE(sub_api);
2221 // With handle and enpoints set (in parent), we can setup the default pipe properties
2222 // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
2223 for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) {
2224 endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
2225 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2226 PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout))
2227 usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
2229 if ((i == -1) || (sub_api == SUB_API_LIBUSB0))
2230 continue; // Other policies don't apply to control endpoint or libusb0
2233 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2234 SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
2235 usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
2237 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2238 IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy))
2239 usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
2242 /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
2243 https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
2244 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2245 ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy))
2246 usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
2248 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2249 AUTO_CLEAR_STALL, sizeof(UCHAR), &policy))
2250 usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
2252 if (sub_api == SUB_API_LIBUSBK) {
2253 if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
2254 ISO_ALWAYS_START_ASAP, sizeof(UCHAR), &policy))
2255 usbi_dbg("failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
2259 return LIBUSB_SUCCESS;
2262 static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2264 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2265 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2266 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2267 bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
2268 SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
2269 HDEVINFO dev_info = INVALID_HANDLE_VALUE;
2270 SP_DEVINFO_DATA dev_info_data;
2271 char *dev_path_no_guid = NULL;
2272 char filter_path[] = "\\\\.\\libusb0-0000";
2273 bool found_filter = false;
2274 HANDLE file_handle, winusb_handle;
2278 CHECK_WINUSBX_AVAILABLE(sub_api);
2280 // If the device is composite, but using the default Windows composite parent driver (usbccgp)
2281 // or if it's the first WinUSB-like interface, we get a handle through Initialize().
2282 if ((is_using_usbccgp) || (iface == 0)) {
2283 // composite device (independent interfaces) or interface 0
2284 file_handle = handle_priv->interface_handle[iface].dev_handle;
2285 if (!HANDLE_VALID(file_handle))
2286 return LIBUSB_ERROR_NOT_FOUND;
2288 if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2289 handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
2290 err = GetLastError();
2292 case ERROR_BAD_COMMAND:
2293 // The device was disconnected
2294 usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
2295 return LIBUSB_ERROR_NO_DEVICE;
2297 // it may be that we're using the libusb0 filter driver.
2298 // TODO: can we move this whole business into the K/0 DLL?
2299 for (i = 0; ; i++) {
2300 safe_free(dev_interface_details);
2301 safe_free(dev_path_no_guid);
2303 dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path);
2304 if ((found_filter) || (dev_interface_details == NULL))
2308 dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{"));
2309 if (dev_path_no_guid == NULL)
2312 if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) {
2313 file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
2314 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
2315 if (file_handle != INVALID_HANDLE_VALUE) {
2316 if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2317 // Replace the existing file handle with the working one
2318 CloseHandle(handle_priv->interface_handle[iface].dev_handle);
2319 handle_priv->interface_handle[iface].dev_handle = file_handle;
2320 found_filter = true;
2322 usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
2323 CloseHandle(file_handle);
2326 usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0));
2330 free(dev_interface_details);
2331 if (!found_filter) {
2332 usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
2333 return LIBUSB_ERROR_ACCESS;
2337 handle_priv->interface_handle[iface].api_handle = winusb_handle;
2339 // For all other interfaces, use GetAssociatedInterface()
2340 winusb_handle = handle_priv->interface_handle[0].api_handle;
2341 // It is a requirement for multiple interface devices on Windows that, to you
2342 // must first claim the first interface before you claim the others
2343 if (!HANDLE_VALID(winusb_handle)) {
2344 file_handle = handle_priv->interface_handle[0].dev_handle;
2345 if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2346 handle_priv->interface_handle[0].api_handle = winusb_handle;
2347 usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
2349 usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
2350 return LIBUSB_ERROR_ACCESS;
2353 if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1),
2354 &handle_priv->interface_handle[iface].api_handle)) {
2355 handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
2356 switch (GetLastError()) {
2357 case ERROR_NO_MORE_ITEMS: // invalid iface
2358 return LIBUSB_ERROR_NOT_FOUND;
2359 case ERROR_BAD_COMMAND: // The device was disconnected
2360 return LIBUSB_ERROR_NO_DEVICE;
2361 case ERROR_ALREADY_EXISTS: // already claimed
2362 return LIBUSB_ERROR_BUSY;
2364 usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
2365 return LIBUSB_ERROR_ACCESS;
2368 handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle;
2370 usbi_dbg("claimed interface %d", iface);
2371 handle_priv->active_interface = iface;
2373 return LIBUSB_SUCCESS;
2376 static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
2378 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2379 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2380 HANDLE winusb_handle;
2382 CHECK_WINUSBX_AVAILABLE(sub_api);
2384 winusb_handle = handle_priv->interface_handle[iface].api_handle;
2385 if (!HANDLE_VALID(winusb_handle))
2386 return LIBUSB_ERROR_NOT_FOUND;
2388 WinUSBX[sub_api].Free(winusb_handle);
2389 handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
2391 return LIBUSB_SUCCESS;
2395 * Return the first valid interface (of the same API type), for control transfers
2397 static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
2399 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2400 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2403 if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
2404 usbi_dbg("unsupported API ID");
2408 for (i = 0; i < USB_MAXINTERFACES; i++) {
2409 if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle)
2410 && HANDLE_VALID(handle_priv->interface_handle[i].api_handle)
2411 && (priv->usb_interface[i].apib->id == api_id))
2419 * Check a specific interface is valid (of the same API type), for control transfers
2421 static int check_valid_interface(struct libusb_device_handle *dev_handle, unsigned short interface, int api_id)
2423 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2424 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2426 if (interface >= USB_MAXINTERFACES)
2429 if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
2430 usbi_dbg("unsupported API ID");
2434 // try the requested interface
2435 if (HANDLE_VALID(handle_priv->interface_handle[interface].dev_handle)
2436 && HANDLE_VALID(handle_priv->interface_handle[interface].api_handle)
2437 && (priv->usb_interface[interface].apib->id == api_id))
2444 * Lookup interface by endpoint address. -1 if not found
2446 static int interface_by_endpoint(struct winusb_device_priv *priv,
2447 struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address)
2451 for (i = 0; i < USB_MAXINTERFACES; i++) {
2452 if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle))
2454 if (priv->usb_interface[i].endpoint == NULL)
2456 for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
2457 if (priv->usb_interface[i].endpoint[j] == endpoint_address)
2465 static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
2467 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2468 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2469 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2470 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2471 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2472 PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
2474 HANDLE winusb_handle;
2475 OVERLAPPED *overlapped;
2476 int current_interface;
2478 CHECK_WINUSBX_AVAILABLE(sub_api);
2480 size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
2482 // Windows places upper limits on the control transfer size
2483 // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx
2484 if (size > MAX_CTRL_BUFFER_LENGTH)
2485 return LIBUSB_ERROR_INVALID_PARAM;
2487 if ((setup->RequestType & 0x1F) == LIBUSB_RECIPIENT_INTERFACE)
2488 current_interface = check_valid_interface(transfer->dev_handle, setup->Index & 0xff, USB_API_WINUSBX);
2490 current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX);
2491 if (current_interface < 0) {
2492 if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS)
2493 return LIBUSB_ERROR_NOT_FOUND;
2496 usbi_dbg("will use interface %d", current_interface);
2498 transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2499 overlapped = transfer_priv->pollable_fd.overlapped;
2501 // Sending of set configuration control requests from WinUSB creates issues, except when using libusb0.sys
2502 if (sub_api != SUB_API_LIBUSB0
2503 && (LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD)
2504 && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
2505 if (setup->Value != priv->active_config) {
2506 usbi_warn(ctx, "cannot set configuration other than the default one");
2507 return LIBUSB_ERROR_INVALID_PARAM;
2509 windows_force_sync_completion(overlapped, 0);
2511 if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) {
2512 if (GetLastError() != ERROR_IO_PENDING) {
2513 usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
2514 return LIBUSB_ERROR_IO;
2517 windows_force_sync_completion(overlapped, size);
2521 transfer_priv->interface_number = (uint8_t)current_interface;
2523 return LIBUSB_SUCCESS;
2526 static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
2528 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2529 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2530 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2531 HANDLE winusb_handle;
2533 CHECK_WINUSBX_AVAILABLE(sub_api);
2535 if (altsetting > 255)
2536 return LIBUSB_ERROR_INVALID_PARAM;
2538 winusb_handle = handle_priv->interface_handle[iface].api_handle;
2539 if (!HANDLE_VALID(winusb_handle)) {
2540 usbi_err(ctx, "interface must be claimed first");
2541 return LIBUSB_ERROR_NOT_FOUND;
2544 if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
2545 usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
2546 return LIBUSB_ERROR_IO;
2549 return LIBUSB_SUCCESS;
2552 static enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
2554 if (USBD_SUCCESS(status))
2555 return LIBUSB_TRANSFER_COMPLETED;
2558 case USBD_STATUS_TIMEOUT:
2559 return LIBUSB_TRANSFER_TIMED_OUT;
2560 case USBD_STATUS_CANCELED:
2561 return LIBUSB_TRANSFER_CANCELLED;
2562 case USBD_STATUS_ENDPOINT_HALTED:
2563 return LIBUSB_TRANSFER_STALL;
2564 case USBD_STATUS_DEVICE_GONE:
2565 return LIBUSB_TRANSFER_NO_DEVICE;
2567 usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", status);
2568 return LIBUSB_TRANSFER_ERROR;
2572 static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct libusb_transfer *transfer)
2574 // If this callback is invoked, this means that we attempted to set ContinueStream
2575 // to TRUE when calling Read/WriteIsochPipeAsap in winusbx_do_iso_transfer.
2576 // The role of this callback is to fallback to ContinueStream = FALSE if the transfer
2579 struct winusb_transfer_priv *transfer_priv = (struct winusb_transfer_priv *)
2580 usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
2581 BOOL fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
2584 // Restore the user callback
2585 transfer->callback = transfer_priv->iso_user_callback;
2587 for (idx = 0; idx < transfer->num_iso_packets && !fallback; ++idx) {
2588 if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED) {
2594 // If the transfer was successful, we restore the user callback and call it.
2595 if (transfer->callback) {
2596 transfer->callback(transfer);
2600 // If the transfer wasn't successful we reschedule the transfer while forcing it
2601 // not to continue the stream. This might results in a 5-ms delay.
2602 transfer_priv->iso_break_stream = TRUE;
2603 libusb_submit_transfer(transfer);
2606 static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
2608 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2609 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2610 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2611 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2612 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2613 HANDLE winusb_handle;
2614 OVERLAPPED *overlapped;
2616 int current_interface;
2618 CHECK_WINUSBX_AVAILABLE(sub_api);
2620 current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
2621 if (current_interface < 0) {
2622 usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
2623 return LIBUSB_ERROR_NOT_FOUND;
2625 usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
2628 transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2629 overlapped = transfer_priv->pollable_fd.overlapped;
2631 if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
2634 size_t iso_ctx_size;
2635 PKISO_CONTEXT iso_context;
2637 iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET));
2638 transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size);
2639 if (transfer_priv->iso_context == NULL)
2640 return LIBUSB_ERROR_NO_MEM;
2643 iso_context->StartFrame = 0;
2644 iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets;
2646 // convert the transfer packet lengths to iso_packet offsets
2648 for (i = 0; i < transfer->num_iso_packets; i++) {
2649 iso_context->IsoPackets[i].offset = offset;
2650 offset += transfer->iso_packet_desc[i].length;
2653 if (IS_XFERIN(transfer)) {
2654 usbi_dbg("reading %d iso packets", transfer->num_iso_packets);
2655 ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
2657 usbi_dbg("writing %d iso packets", transfer->num_iso_packets);
2658 ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
2662 if (GetLastError() != ERROR_IO_PENDING) {
2663 usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
2664 return LIBUSB_ERROR_IO;
2667 windows_force_sync_completion(overlapped, (ULONG)transfer->length);
2670 transfer_priv->interface_number = (uint8_t)current_interface;
2672 return LIBUSB_SUCCESS;
2674 else if (sub_api == SUB_API_WINUSB) {
2675 WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 };
2676 WINUSB_ISOCH_BUFFER_HANDLE buffer_handle;
2677 ULONG iso_transfer_size_multiple;
2678 int out_transfer_length = 0;
2681 # define WINUSBX_CHECK_API_SUPPORTED(API) \
2682 if (WinUSBX[sub_api].API == NULL) \
2684 usbi_dbg(#API " isn't available"); \
2685 return LIBUSB_ERROR_NOT_SUPPORTED; \
2688 // Depending on the version of Microsoft WinUSB, isochronous transfers may not be supported.
2689 WINUSBX_CHECK_API_SUPPORTED(RegisterIsochBuffer);
2690 WINUSBX_CHECK_API_SUPPORTED(ReadIsochPipeAsap);
2691 WINUSBX_CHECK_API_SUPPORTED(WriteIsochPipeAsap);
2692 WINUSBX_CHECK_API_SUPPORTED(UnregisterIsochBuffer);
2693 WINUSBX_CHECK_API_SUPPORTED(QueryPipeEx);
2695 if (sizeof(struct libusb_iso_packet_descriptor) != sizeof(USBD_ISO_PACKET_DESCRIPTOR)) {
2696 usbi_dbg("The size of Microsoft WinUsb and libusb isochronous packet descriptor doesn't match.");
2697 return LIBUSB_ERROR_NOT_SUPPORTED;
2700 // Query the pipe extended information to find the pipe index corresponding to the endpoint.
2701 for (idx = 0; idx < priv->usb_interface[current_interface].nb_endpoints; ++idx) {
2702 ret = WinUSBX[sub_api].QueryPipeEx(winusb_handle, (UINT8)priv->usb_interface[current_interface].current_altsetting, (UCHAR)idx, &pipe_info_ex);
2704 usbi_dbg("Couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
2705 return LIBUSB_ERROR_NOT_FOUND;
2708 if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous) {
2713 // Make sure we found the index.
2714 if (idx >= priv->usb_interface[current_interface].nb_endpoints) {
2715 usbi_dbg("Couldn't find the isochronous endpoint %02x.", transfer->endpoint);
2716 return LIBUSB_ERROR_NOT_FOUND;
2719 if (IS_XFERIN(transfer)) {
2720 int interval = pipe_info_ex.Interval;
2722 // For high-speed and SuperSpeed device, the interval is 2**(bInterval-1).
2723 if (libusb_get_device_speed(libusb_get_device(transfer->dev_handle)) >= LIBUSB_SPEED_HIGH) {
2724 interval = (1 << (pipe_info_ex.Interval - 1));
2727 // WinUSB only supports isochronous transfers spanning a full USB frames. Later, we might be smarter about this
2728 // and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped
2730 iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
2731 if (transfer->length % iso_transfer_size_multiple != 0) {
2732 usbi_dbg("The length of isochronous buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
2733 return LIBUSB_ERROR_INVALID_PARAM;
2737 // If this is an OUT transfer, we make sure the isochronous packets are contiguous as this isn't supported otherwise.
2738 BOOL size_should_be_zero = FALSE;
2739 out_transfer_length = 0;
2740 for (idx = 0; idx < transfer->num_iso_packets; ++idx) {
2741 if ((size_should_be_zero && transfer->iso_packet_desc[idx].length != 0) ||
2742 (transfer->iso_packet_desc[idx].length != pipe_info_ex.MaximumBytesPerInterval && idx + 1 < transfer->num_iso_packets && transfer->iso_packet_desc[idx + 1].length > 0)) {
2743 usbi_dbg("Isochronous packets for OUT transfer with Microsoft WinUSB must be contiguous in memory.");
2744 return LIBUSB_ERROR_INVALID_PARAM;
2747 size_should_be_zero = (transfer->iso_packet_desc[idx].length == 0);
2748 out_transfer_length += transfer->iso_packet_desc[idx].length;
2752 if (transfer_priv->isoch_buffer_handle != NULL) {
2753 if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
2754 transfer_priv->isoch_buffer_handle = NULL;
2756 usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
2757 return LIBUSB_ERROR_OTHER;
2761 // Register the isochronous buffer to the operating system.
2762 ret = WinUSBX[sub_api].RegisterIsochBuffer(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, &buffer_handle);
2764 usbi_dbg("Microsoft WinUSB refused to allocate an isochronous buffer.");
2765 return LIBUSB_ERROR_NO_MEM;
2768 // Important note: the WinUSB_Read/WriteIsochPipeAsap API requires a ContinueStream parameter that tells whether the isochronous
2769 // stream must be continued or if the WinUSB driver can schedule the transfer at its conveniance. Profiling subsequent transfers
2770 // with ContinueStream = FALSE showed that 5 frames, i.e. about 5 milliseconds, were left empty between each transfer. This
2771 // is critical as this greatly diminish the achievable isochronous bandwidth. We solved the problem using the following strategy:
2772 // - Transfers are first scheduled with ContinueStream = TRUE and with winusbx_iso_transfer_continue_stream_callback as user callback.
2773 // - If the transfer succeeds, winusbx_iso_transfer_continue_stream_callback restore the user callback and calls its.
2774 // - If the transfer fails, winusbx_iso_transfer_continue_stream_callback reschedule the transfer and force ContinueStream = FALSE.
2775 if (!transfer_priv->iso_break_stream) {
2776 transfer_priv->iso_user_callback = transfer->callback;
2777 transfer->callback = winusbx_native_iso_transfer_continue_stream_callback;
2780 // Initiate the transfers.
2781 if (IS_XFERIN(transfer)) {
2782 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);
2785 ret = WinUSBX[sub_api].WriteIsochPipeAsap(buffer_handle, 0, out_transfer_length, !transfer_priv->iso_break_stream, overlapped);
2788 // Restore the ContinueStream parameter to TRUE.
2789 transfer_priv->iso_break_stream = FALSE;
2792 if (GetLastError() == ERROR_IO_PENDING) {
2793 transfer_priv->isoch_buffer_handle = buffer_handle;
2795 usbi_err(ctx, "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
2796 if (WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
2797 transfer_priv->isoch_buffer_handle = NULL;
2798 return LIBUSB_ERROR_IO;
2800 usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
2801 return LIBUSB_ERROR_OTHER;
2805 windows_force_sync_completion(overlapped, (ULONG)transfer->length);
2806 if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
2807 usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
2808 return LIBUSB_ERROR_OTHER;
2812 transfer_priv->interface_number = (uint8_t)current_interface;
2814 return LIBUSB_SUCCESS;
2816 PRINT_UNSUPPORTED_API(winusbx_submit_iso_transfer);
2817 return LIBUSB_ERROR_NOT_SUPPORTED;
2821 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
2823 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2824 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2825 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2826 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2827 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2828 HANDLE winusb_handle;
2829 OVERLAPPED *overlapped;
2831 int current_interface;
2833 CHECK_WINUSBX_AVAILABLE(sub_api);
2835 current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
2836 if (current_interface < 0) {
2837 usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
2838 return LIBUSB_ERROR_NOT_FOUND;
2841 usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
2843 transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2844 overlapped = transfer_priv->pollable_fd.overlapped;
2846 if (IS_XFERIN(transfer)) {
2847 usbi_dbg("reading %d bytes", transfer->length);
2848 ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
2850 usbi_dbg("writing %d bytes", transfer->length);
2851 ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
2855 if (GetLastError() != ERROR_IO_PENDING) {
2856 usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
2857 return LIBUSB_ERROR_IO;
2860 windows_force_sync_completion(overlapped, (ULONG)transfer->length);
2863 transfer_priv->interface_number = (uint8_t)current_interface;
2865 return LIBUSB_SUCCESS;
2868 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
2870 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2871 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2872 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2873 HANDLE winusb_handle;
2874 int current_interface;
2876 CHECK_WINUSBX_AVAILABLE(sub_api);
2878 current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
2879 if (current_interface < 0) {
2880 usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
2881 return LIBUSB_ERROR_NOT_FOUND;
2884 usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
2885 winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
2887 if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
2888 usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
2889 return LIBUSB_ERROR_NO_DEVICE;
2892 return LIBUSB_SUCCESS;
2896 * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
2897 * through testing as well):
2898 * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
2899 * the control transfer using CancelIo"
2901 static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
2903 // Cancelling of the I/O is done in the parent
2904 return LIBUSB_SUCCESS;
2907 static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
2909 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2910 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
2911 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
2912 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
2913 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
2915 int current_interface;
2917 CHECK_WINUSBX_AVAILABLE(sub_api);
2919 current_interface = transfer_priv->interface_number;
2920 if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
2921 usbi_err(ctx, "program assertion failed: invalid interface_number");
2922 return LIBUSB_ERROR_NOT_FOUND;
2924 usbi_dbg("will use interface %d", current_interface);
2926 if (WinUSBX[sub_api].CancelIoEx_supported) {
2927 // Try to use CancelIoEx if available to cancel just a single transfer
2928 handle = handle_priv->interface_handle[current_interface].dev_handle;
2929 if (CancelIoEx(handle, transfer_priv->pollable_fd.overlapped))
2930 return LIBUSB_SUCCESS;
2931 else if (GetLastError() == ERROR_NOT_FOUND)
2932 return LIBUSB_ERROR_NOT_FOUND;
2934 // Not every driver implements the necessary functionality for CancelIoEx
2935 usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]);
2936 WinUSBX[sub_api].CancelIoEx_supported = false;
2939 handle = handle_priv->interface_handle[current_interface].api_handle;
2940 if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) {
2941 usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
2942 return LIBUSB_ERROR_NO_DEVICE;
2945 return LIBUSB_SUCCESS;
2949 * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper
2950 * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx):
2951 * "WinUSB does not support host-initiated reset port and cycle port operations" and
2952 * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the
2953 * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
2954 * cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
2956 // TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
2957 static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
2959 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
2960 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
2961 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
2962 HANDLE winusb_handle;
2965 CHECK_WINUSBX_AVAILABLE(sub_api);
2967 // Reset any available pipe (except control)
2968 for (i = 0; i < USB_MAXINTERFACES; i++) {
2969 winusb_handle = handle_priv->interface_handle[i].api_handle;
2970 if (HANDLE_VALID(winusb_handle)) {
2971 for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
2972 usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
2973 if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
2974 usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
2975 priv->usb_interface[i].endpoint[j], windows_error_str(0));
2977 // FlushPipe seems to fail on OUT pipes
2978 if (IS_EPIN(priv->usb_interface[i].endpoint[j])
2979 && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])))
2980 usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
2981 priv->usb_interface[i].endpoint[j], windows_error_str(0));
2983 if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
2984 usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
2985 priv->usb_interface[i].endpoint[j], windows_error_str(0));
2990 // libusbK & libusb0 have the ability to issue an actual device reset
2991 if (WinUSBX[sub_api].ResetDevice != NULL) {
2992 winusb_handle = handle_priv->interface_handle[0].api_handle;
2993 if (HANDLE_VALID(winusb_handle))
2994 WinUSBX[sub_api].ResetDevice(winusb_handle);
2997 return LIBUSB_SUCCESS;
3000 static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
3002 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3003 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3004 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3005 PKISO_CONTEXT iso_context;
3008 if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
3009 CHECK_WINUSBX_AVAILABLE(sub_api);
3011 // for isochronous, need to copy the individual iso packet actual_lengths and statuses
3012 if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
3013 // iso only supported on libusbk-based backends for now
3014 iso_context = transfer_priv->iso_context;
3015 for (i = 0; i < transfer->num_iso_packets; i++) {
3016 transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length;
3017 // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status
3018 //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status;
3020 } else if (sub_api == SUB_API_WINUSB) {
3021 if (IS_XFERIN(transfer)) {
3022 /* Convert isochronous packet descriptor between Windows and libusb representation.
3023 * Both representation are guaranteed to have the same length in bytes.*/
3024 PUSBD_ISO_PACKET_DESCRIPTOR usbd_iso_packet_desc = (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc;
3025 for (i = 0; i < transfer->num_iso_packets; ++i)
3027 int 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;
3028 int actual_length = usbd_iso_packet_desc[i].Length;
3029 USBD_STATUS status = usbd_iso_packet_desc[i].Status;
3031 transfer->iso_packet_desc[i].length = length;
3032 transfer->iso_packet_desc[i].actual_length = actual_length;
3033 transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(status);
3037 for (i = 0; i < transfer->num_iso_packets; ++i)
3039 transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED;
3043 // This should only occur if backend is not set correctly or other backend isoc is partially implemented
3044 PRINT_UNSUPPORTED_API(copy_transfer_data);
3045 return LIBUSB_ERROR_NOT_SUPPORTED;
3049 itransfer->transferred += io_size;
3050 return LIBUSB_TRANSFER_COMPLETED;
3054 * Internal HID Support functions (from libusb-win32)
3055 * Note that functions that complete data transfer synchronously must return
3056 * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS
3058 static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
3059 static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
3061 static int _hid_wcslen(WCHAR *str)
3065 while (str[i] && (str[i] != 0x409))
3071 static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3073 struct libusb_device_descriptor d;
3075 d.bLength = LIBUSB_DT_DEVICE_SIZE;
3076 d.bDescriptorType = LIBUSB_DT_DEVICE;
3077 d.bcdUSB = 0x0200; /* 2.00 */
3079 d.bDeviceSubClass = 0;
3080 d.bDeviceProtocol = 0;
3081 d.bMaxPacketSize0 = 64; /* fix this! */
3082 d.idVendor = (uint16_t)dev->vid;
3083 d.idProduct = (uint16_t)dev->pid;
3084 d.bcdDevice = 0x0100;
3085 d.iManufacturer = dev->string_index[0];
3086 d.iProduct = dev->string_index[1];
3087 d.iSerialNumber = dev->string_index[2];
3088 d.bNumConfigurations = 1;
3090 if (*size > LIBUSB_DT_DEVICE_SIZE)
3091 *size = LIBUSB_DT_DEVICE_SIZE;
3092 memcpy(data, &d, *size);
3094 return LIBUSB_COMPLETED;
3097 static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3099 char num_endpoints = 0;
3100 size_t config_total_len = 0;
3101 char tmp[HID_MAX_CONFIG_DESC_SIZE];
3102 struct libusb_config_descriptor *cd;
3103 struct libusb_interface_descriptor *id;
3104 struct libusb_hid_descriptor *hd;
3105 struct libusb_endpoint_descriptor *ed;
3108 if (dev->input_report_size)
3110 if (dev->output_report_size)
3113 config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
3114 + LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE;
3116 cd = (struct libusb_config_descriptor *)tmp;
3117 id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE);
3118 hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
3119 + LIBUSB_DT_INTERFACE_SIZE);
3120 ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
3121 + LIBUSB_DT_INTERFACE_SIZE
3122 + LIBUSB_DT_HID_SIZE);
3124 cd->bLength = LIBUSB_DT_CONFIG_SIZE;
3125 cd->bDescriptorType = LIBUSB_DT_CONFIG;
3126 cd->wTotalLength = (uint16_t)config_total_len;
3127 cd->bNumInterfaces = 1;
3128 cd->bConfigurationValue = 1;
3129 cd->iConfiguration = 0;
3130 cd->bmAttributes = 1 << 7; /* bus powered */
3133 id->bLength = LIBUSB_DT_INTERFACE_SIZE;
3134 id->bDescriptorType = LIBUSB_DT_INTERFACE;
3135 id->bInterfaceNumber = 0;
3136 id->bAlternateSetting = 0;
3137 id->bNumEndpoints = num_endpoints;
3138 id->bInterfaceClass = 3;
3139 id->bInterfaceSubClass = 0;
3140 id->bInterfaceProtocol = 0;
3143 tmp_size = LIBUSB_DT_HID_SIZE;
3144 _hid_get_hid_descriptor(dev, hd, &tmp_size);
3146 if (dev->input_report_size) {
3147 ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
3148 ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
3149 ed->bEndpointAddress = HID_IN_EP;
3150 ed->bmAttributes = 3;
3151 ed->wMaxPacketSize = dev->input_report_size - 1;
3153 ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE);
3156 if (dev->output_report_size) {
3157 ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
3158 ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
3159 ed->bEndpointAddress = HID_OUT_EP;
3160 ed->bmAttributes = 3;
3161 ed->wMaxPacketSize = dev->output_report_size - 1;
3165 if (*size > config_total_len)
3166 *size = config_total_len;
3167 memcpy(data, tmp, *size);
3169 return LIBUSB_COMPLETED;
3172 static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
3173 void *data, size_t *size, HANDLE hid_handle)
3176 WCHAR string[MAX_USB_STRING_LENGTH];
3177 size_t tmp_size = 0;
3180 /* language ID, EN-US */
3181 char string_langid[] = {0x09, 0x04};
3183 if ((*size < 2) || (*size > 255))
3184 return LIBUSB_ERROR_OVERFLOW;
3187 tmp = string_langid;
3188 tmp_size = sizeof(string_langid) + 2;
3190 for (i = 0; i < 3; i++) {
3191 if (_index == (dev->string_index[i])) {
3192 tmp = dev->string[i];
3193 tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
3199 if (!HidD_GetIndexedString(hid_handle, _index, string, sizeof(string)))
3200 return LIBUSB_ERROR_INVALID_PARAM;
3202 tmp_size = (_hid_wcslen(string) + 1) * sizeof(WCHAR);
3207 return LIBUSB_ERROR_INVALID_PARAM;
3209 if (tmp_size < *size)
3213 ((uint8_t *)data)[0] = (uint8_t)*size;
3214 ((uint8_t *)data)[1] = LIBUSB_DT_STRING;
3215 memcpy((uint8_t *)data + 2, tmp, *size - 2);
3217 return LIBUSB_COMPLETED;
3220 static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3222 struct libusb_hid_descriptor d;
3223 uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
3224 size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
3226 _hid_get_report_descriptor(dev, tmp, &report_len);
3228 d.bLength = LIBUSB_DT_HID_SIZE;
3229 d.bDescriptorType = LIBUSB_DT_HID;
3230 d.bcdHID = 0x0110; /* 1.10 */
3232 d.bNumDescriptors = 1;
3233 d.bClassDescriptorType = LIBUSB_DT_REPORT;
3234 d.wClassDescriptorLength = (uint16_t)report_len;
3236 if (*size > LIBUSB_DT_HID_SIZE)
3237 *size = LIBUSB_DT_HID_SIZE;
3238 memcpy(data, &d, *size);
3240 return LIBUSB_COMPLETED;
3243 static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
3245 uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
3249 d[i++] = 0x06; d[i++] = dev->usagePage & 0xFF; d[i++] = dev->usagePage >> 8;
3251 d[i++] = 0x09; d[i++] = (uint8_t)dev->usage;
3252 /* start collection (application) */
3253 d[i++] = 0xA1; d[i++] = 0x01;
3255 if (dev->input_report_size) {
3256 /* usage (vendor defined) */
3257 d[i++] = 0x09; d[i++] = 0x01;
3258 /* logical minimum (0) */
3259 d[i++] = 0x15; d[i++] = 0x00;
3260 /* logical maximum (255) */
3261 d[i++] = 0x25; d[i++] = 0xFF;
3262 /* report size (8 bits) */
3263 d[i++] = 0x75; d[i++] = 0x08;
3265 d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
3266 /* input (data, variable, absolute) */
3267 d[i++] = 0x81; d[i++] = 0x00;
3270 if (dev->output_report_size) {
3271 /* usage (vendor defined) */
3272 d[i++] = 0x09; d[i++] = 0x02;
3273 /* logical minimum (0) */
3274 d[i++] = 0x15; d[i++] = 0x00;
3275 /* logical maximum (255) */
3276 d[i++] = 0x25; d[i++] = 0xFF;
3277 /* report size (8 bits) */
3278 d[i++] = 0x75; d[i++] = 0x08;
3280 d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
3281 /* output (data, variable, absolute) */
3282 d[i++] = 0x91; d[i++] = 0x00;
3284 /* feature report */
3285 if (dev->feature_report_size) {
3286 /* usage (vendor defined) */
3287 d[i++] = 0x09; d[i++] = 0x03;
3288 /* logical minimum (0) */
3289 d[i++] = 0x15; d[i++] = 0x00;
3290 /* logical maximum (255) */
3291 d[i++] = 0x25; d[i++] = 0xFF;
3292 /* report size (8 bits) */
3293 d[i++] = 0x75; d[i++] = 0x08;
3295 d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
3296 /* feature (data, variable, absolute) */
3297 d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
3300 /* end collection */
3305 memcpy(data, d, *size);
3307 return LIBUSB_COMPLETED;
3310 static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
3311 int type, int _index, void *data, size_t *size)
3314 case LIBUSB_DT_DEVICE:
3315 usbi_dbg("LIBUSB_DT_DEVICE");
3316 return _hid_get_device_descriptor(dev, data, size);
3317 case LIBUSB_DT_CONFIG:
3318 usbi_dbg("LIBUSB_DT_CONFIG");
3320 return _hid_get_config_descriptor(dev, data, size);
3321 return LIBUSB_ERROR_INVALID_PARAM;
3322 case LIBUSB_DT_STRING:
3323 usbi_dbg("LIBUSB_DT_STRING");
3324 return _hid_get_string_descriptor(dev, _index, data, size, hid_handle);
3326 usbi_dbg("LIBUSB_DT_HID");
3328 return _hid_get_hid_descriptor(dev, data, size);
3329 return LIBUSB_ERROR_INVALID_PARAM;
3330 case LIBUSB_DT_REPORT:
3331 usbi_dbg("LIBUSB_DT_REPORT");
3333 return _hid_get_report_descriptor(dev, data, size);
3334 return LIBUSB_ERROR_INVALID_PARAM;
3335 case LIBUSB_DT_PHYSICAL:
3336 usbi_dbg("LIBUSB_DT_PHYSICAL");
3337 if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
3338 return LIBUSB_COMPLETED;
3339 return LIBUSB_ERROR_OTHER;
3342 usbi_dbg("unsupported");
3343 return LIBUSB_ERROR_NOT_SUPPORTED;
3346 static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
3347 struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
3350 DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
3351 int r = LIBUSB_SUCCESS;
3353 if (tp->hid_buffer != NULL)
3354 usbi_dbg("program assertion failed: hid_buffer is not NULL");
3356 if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
3357 usbi_dbg("invalid size (%"PRIuPTR")", (uintptr_t)*size);
3358 return LIBUSB_ERROR_INVALID_PARAM;
3361 switch (report_type) {
3362 case HID_REPORT_TYPE_INPUT:
3363 ioctl_code = IOCTL_HID_GET_INPUT_REPORT;
3365 case HID_REPORT_TYPE_FEATURE:
3366 ioctl_code = IOCTL_HID_GET_FEATURE;
3369 usbi_dbg("unknown HID report type %d", report_type);
3370 return LIBUSB_ERROR_INVALID_PARAM;
3373 // Add a trailing byte to detect overflows
3374 buf = calloc(1, expected_size + 1);
3376 return LIBUSB_ERROR_NO_MEM;
3378 buf[0] = (uint8_t)id; // Must be set always
3379 usbi_dbg("report ID: 0x%02X", buf[0]);
3381 tp->hid_expected_size = expected_size;
3382 read_size = expected_size;
3384 // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3385 if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
3386 buf, expected_size + 1, &read_size, overlapped)) {
3387 if (GetLastError() != ERROR_IO_PENDING) {
3388 usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
3390 return LIBUSB_ERROR_IO;
3392 // Asynchronous wait
3393 tp->hid_buffer = buf;
3394 tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
3395 return LIBUSB_SUCCESS;
3398 // Transfer completed synchronously => copy and discard extra buffer
3399 if (read_size == 0) {
3400 usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
3404 usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
3406 if ((size_t)read_size > expected_size) {
3407 r = LIBUSB_ERROR_OVERFLOW;
3408 usbi_dbg("OVERFLOW!");
3410 r = LIBUSB_COMPLETED;
3413 *size = MIN((size_t)read_size, *size);
3415 memcpy(data, buf + 1, *size); // Discard report ID
3417 memcpy(data, buf, *size);
3424 static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
3425 struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
3427 uint8_t *buf = NULL;
3428 DWORD ioctl_code, write_size = (DWORD)*size;
3429 // If an id is reported, we must allow MAX_HID_REPORT_SIZE + 1
3430 size_t max_report_size = MAX_HID_REPORT_SIZE + (id ? 1 : 0);
3432 if (tp->hid_buffer != NULL)
3433 usbi_dbg("program assertion failed: hid_buffer is not NULL");
3435 if ((*size == 0) || (*size > max_report_size)) {
3436 usbi_dbg("invalid size (%"PRIuPTR")", (uintptr_t)*size);
3437 return LIBUSB_ERROR_INVALID_PARAM;
3440 switch (report_type) {
3441 case HID_REPORT_TYPE_OUTPUT:
3442 ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT;
3444 case HID_REPORT_TYPE_FEATURE:
3445 ioctl_code = IOCTL_HID_SET_FEATURE;
3448 usbi_dbg("unknown HID report type %d", report_type);
3449 return LIBUSB_ERROR_INVALID_PARAM;
3452 usbi_dbg("report ID: 0x%02X", id);
3453 // When report IDs are not used (i.e. when id == 0), we must add
3454 // a null report ID. Otherwise, we just use original data buffer
3458 buf = malloc(write_size);
3460 return LIBUSB_ERROR_NO_MEM;
3464 memcpy(buf + 1, data, *size);
3466 // This seems like a waste, but if we don't duplicate the
3467 // data, we'll get issues when freeing hid_buffer
3468 memcpy(buf, data, *size);
3470 usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
3473 // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3474 if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
3475 buf, write_size, &write_size, overlapped)) {
3476 if (GetLastError() != ERROR_IO_PENDING) {
3477 usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
3479 return LIBUSB_ERROR_IO;
3481 tp->hid_buffer = buf;
3482 tp->hid_dest = NULL;
3483 return LIBUSB_SUCCESS;
3486 // Transfer completed synchronously
3488 if (write_size == 0)
3489 usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
3492 return LIBUSB_COMPLETED;
3495 static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
3496 int request, int value, int _index, void *data, struct winusb_transfer_priv *tp,
3497 size_t *size, OVERLAPPED *overlapped)
3499 int report_type = (value >> 8) & 0xFF;
3500 int report_id = value & 0xFF;
3502 if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
3503 && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE))
3504 return LIBUSB_ERROR_INVALID_PARAM;
3506 if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT)
3507 return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
3509 if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT)
3510 return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
3512 return LIBUSB_ERROR_INVALID_PARAM;
3519 static int hid_init(struct libusb_context *ctx)
3521 DLL_GET_HANDLE(hid);
3523 DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE);
3524 DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE);
3525 DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE);
3526 DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE);
3527 DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE);
3528 DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE);
3529 DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE);
3530 DLL_LOAD_FUNC(hid, HidD_GetIndexedString, TRUE);
3531 DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE);
3532 DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE);
3533 DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE);
3534 DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE);
3535 DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE);
3537 api_hid_available = true;
3538 return LIBUSB_SUCCESS;
3541 static void hid_exit(void)
3543 DLL_FREE_HANDLE(hid);
3546 // NB: open and close must ensure that they only handle interface of
3547 // the right API type, as these functions can be called wholesale from
3548 // composite_open(), with interfaces belonging to different APIs
3549 static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
3551 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
3552 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3553 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3554 HIDD_ATTRIBUTES hid_attributes;
3555 PHIDP_PREPARSED_DATA preparsed_data = NULL;
3556 HIDP_CAPS capabilities;
3557 HIDP_VALUE_CAPS *value_caps;
3558 HANDLE hid_handle = INVALID_HANDLE_VALUE;
3560 // report IDs handling
3562 int nb_ids[2]; // zero and nonzero report IDs
3563 #if defined(ENABLE_LOGGING)
3564 const char * const type[3] = {"input", "output", "feature"};
3567 CHECK_HID_AVAILABLE;
3569 if (priv->hid == NULL) {
3570 usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
3571 return LIBUSB_ERROR_NOT_FOUND;
3574 for (i = 0; i < USB_MAXINTERFACES; i++) {
3575 if ((priv->usb_interface[i].path != NULL)
3576 && (priv->usb_interface[i].apib->id == USB_API_HID)) {
3577 hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
3578 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
3580 * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
3581 * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
3582 * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not
3583 * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and
3584 * HidD_GetFeature (if the device supports Feature reports)."
3586 if (hid_handle == INVALID_HANDLE_VALUE) {
3587 usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
3588 hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
3589 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
3590 if (hid_handle == INVALID_HANDLE_VALUE) {
3591 usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
3592 switch (GetLastError()) {
3593 case ERROR_FILE_NOT_FOUND: // The device was disconnected
3594 return LIBUSB_ERROR_NO_DEVICE;
3595 case ERROR_ACCESS_DENIED:
3596 return LIBUSB_ERROR_ACCESS;
3598 return LIBUSB_ERROR_IO;
3601 priv->usb_interface[i].restricted_functionality = true;
3603 handle_priv->interface_handle[i].api_handle = hid_handle;
3607 hid_attributes.Size = sizeof(hid_attributes);
3609 if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
3610 usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
3614 priv->hid->vid = hid_attributes.VendorID;
3615 priv->hid->pid = hid_attributes.ProductID;
3617 // Set the maximum available input buffer size
3618 for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2);
3619 usbi_dbg("set maximum input buffer size to %d", i / 2);
3621 // Get the maximum input and output report size
3622 if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
3623 usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
3626 if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
3627 usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
3631 // Find out if interrupt will need report IDs
3632 size[0] = capabilities.NumberInputValueCaps;
3633 size[1] = capabilities.NumberOutputValueCaps;
3634 size[2] = capabilities.NumberFeatureValueCaps;
3635 for (j = HidP_Input; j <= HidP_Feature; j++) {
3636 usbi_dbg("%lu HID %s report value(s) found", size[j], type[j]);
3637 priv->hid->uses_report_ids[j] = false;
3639 value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS));
3640 if ((value_caps != NULL)
3641 && (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS)
3642 && (size[j] >= 1)) {
3645 for (i = 0; i < (int)size[j]; i++) {
3646 usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID);
3647 if (value_caps[i].ReportID != 0)
3652 if (nb_ids[1] != 0) {
3654 usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
3656 priv->hid->uses_report_ids[j] = true;
3659 usbi_warn(ctx, " could not process %s report IDs", type[j]);
3665 // Set the report sizes
3666 priv->hid->input_report_size = capabilities.InputReportByteLength;
3667 priv->hid->output_report_size = capabilities.OutputReportByteLength;
3668 priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
3670 // Store usage and usagePage values
3671 priv->hid->usage = capabilities.Usage;
3672 priv->hid->usagePage = capabilities.UsagePage;
3674 // Fetch string descriptors
3675 priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer;
3676 if (priv->hid->string_index[0] != 0)
3677 HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0]));
3679 priv->hid->string[0][0] = 0;
3681 priv->hid->string_index[1] = priv->dev_descriptor.iProduct;
3682 if (priv->hid->string_index[1] != 0)
3683 HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1]));
3685 priv->hid->string[1][0] = 0;
3687 priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber;
3688 if (priv->hid->string_index[2] != 0)
3689 HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2]));
3691 priv->hid->string[2][0] = 0;
3695 HidD_FreePreparsedData(preparsed_data);
3697 return LIBUSB_SUCCESS;
3700 static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
3702 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3703 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3707 if (!api_hid_available)
3710 for (i = 0; i < USB_MAXINTERFACES; i++) {
3711 if (priv->usb_interface[i].apib->id == USB_API_HID) {
3712 file_handle = handle_priv->interface_handle[i].api_handle;
3713 if (HANDLE_VALID(file_handle))
3714 CloseHandle(file_handle);
3719 static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
3721 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3722 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3724 CHECK_HID_AVAILABLE;
3726 // NB: Disconnection detection is not possible in this function
3727 if (priv->usb_interface[iface].path == NULL)
3728 return LIBUSB_ERROR_NOT_FOUND; // invalid iface
3730 // We use dev_handle as a flag for interface claimed
3731 if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED)
3732 return LIBUSB_ERROR_BUSY; // already claimed
3734 handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
3736 usbi_dbg("claimed interface %d", iface);
3737 handle_priv->active_interface = iface;
3739 return LIBUSB_SUCCESS;
3742 static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
3744 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3745 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
3747 CHECK_HID_AVAILABLE;
3749 if (priv->usb_interface[iface].path == NULL)
3750 return LIBUSB_ERROR_NOT_FOUND; // invalid iface
3752 if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED)
3753 return LIBUSB_ERROR_NOT_FOUND; // invalid iface
3755 handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE;
3757 return LIBUSB_SUCCESS;
3760 static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
3762 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
3764 CHECK_HID_AVAILABLE;
3766 if (altsetting > 255)
3767 return LIBUSB_ERROR_INVALID_PARAM;
3769 if (altsetting != 0) {
3770 usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
3771 return LIBUSB_ERROR_NOT_SUPPORTED;
3774 return LIBUSB_SUCCESS;
3777 static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
3779 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3780 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3781 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3782 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3783 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
3784 WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
3786 OVERLAPPED *overlapped;
3787 int current_interface, config;
3789 int r = LIBUSB_ERROR_INVALID_PARAM;
3791 CHECK_HID_AVAILABLE;
3793 safe_free(transfer_priv->hid_buffer);
3794 transfer_priv->hid_dest = NULL;
3795 size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
3797 if (size > MAX_CTRL_BUFFER_LENGTH)
3798 return LIBUSB_ERROR_INVALID_PARAM;
3800 current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
3801 if (current_interface < 0) {
3802 if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS)
3803 return LIBUSB_ERROR_NOT_FOUND;
3806 usbi_dbg("will use interface %d", current_interface);
3808 hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3809 overlapped = transfer_priv->pollable_fd.overlapped;
3811 switch (LIBUSB_REQ_TYPE(setup->RequestType)) {
3812 case LIBUSB_REQUEST_TYPE_STANDARD:
3813 switch (setup->Request) {
3814 case LIBUSB_REQUEST_GET_DESCRIPTOR:
3815 r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
3816 (setup->Value >> 8) & 0xFF, setup->Value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
3818 case LIBUSB_REQUEST_GET_CONFIGURATION:
3819 r = winusb_get_configuration(transfer->dev_handle, &config);
3820 if (r == LIBUSB_SUCCESS) {
3822 ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
3823 r = LIBUSB_COMPLETED;
3826 case LIBUSB_REQUEST_SET_CONFIGURATION:
3827 if (setup->Value == priv->active_config) {
3828 r = LIBUSB_COMPLETED;
3830 usbi_warn(ctx, "cannot set configuration other than the default one");
3831 r = LIBUSB_ERROR_NOT_SUPPORTED;
3834 case LIBUSB_REQUEST_GET_INTERFACE:
3836 ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0;
3837 r = LIBUSB_COMPLETED;
3839 case LIBUSB_REQUEST_SET_INTERFACE:
3840 r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->Index, setup->Value);
3841 if (r == LIBUSB_SUCCESS)
3842 r = LIBUSB_COMPLETED;
3845 usbi_warn(ctx, "unsupported HID control request");
3846 return LIBUSB_ERROR_NOT_SUPPORTED;
3849 case LIBUSB_REQUEST_TYPE_CLASS:
3850 r = _hid_class_request(priv->hid, hid_handle, setup->RequestType, setup->Request, setup->Value,
3851 setup->Index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
3855 usbi_warn(ctx, "unsupported HID control request");
3856 return LIBUSB_ERROR_NOT_SUPPORTED;
3862 if (r == LIBUSB_COMPLETED) {
3863 // Force request to be completed synchronously. Transferred size has been set by previous call
3864 windows_force_sync_completion(overlapped, (ULONG)size);
3868 transfer_priv->interface_number = (uint8_t)current_interface;
3870 return LIBUSB_SUCCESS;
3873 static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
3875 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3876 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3877 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
3878 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3879 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
3881 OVERLAPPED *overlapped;
3882 bool direction_in, ret;
3883 int current_interface, length;
3885 int r = LIBUSB_SUCCESS;
3887 CHECK_HID_AVAILABLE;
3889 transfer_priv->hid_dest = NULL;
3890 safe_free(transfer_priv->hid_buffer);
3892 current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
3893 if (current_interface < 0) {
3894 usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
3895 return LIBUSB_ERROR_NOT_FOUND;
3898 usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
3900 transfer_priv->handle = hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3901 overlapped = transfer_priv->pollable_fd.overlapped;
3902 direction_in = IS_XFERIN(transfer);
3904 // If report IDs are not in use, an extra prefix byte must be added
3905 if (((direction_in) && (!priv->hid->uses_report_ids[0]))
3906 || ((!direction_in) && (!priv->hid->uses_report_ids[1])))
3907 length = transfer->length + 1;
3909 length = transfer->length;
3911 // Add a trailing byte to detect overflows on input
3912 transfer_priv->hid_buffer = calloc(1, length + 1);
3913 if (transfer_priv->hid_buffer == NULL)
3914 return LIBUSB_ERROR_NO_MEM;
3916 transfer_priv->hid_expected_size = length;
3919 transfer_priv->hid_dest = transfer->buffer;
3920 usbi_dbg("reading %d bytes (report ID: 0x00)", length);
3921 ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, &size, overlapped);
3923 if (!priv->hid->uses_report_ids[1])
3924 memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length);
3926 // We could actually do without the calloc and memcpy in this case
3927 memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
3929 usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
3930 ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, &size, overlapped);
3934 if (GetLastError() != ERROR_IO_PENDING) {
3935 usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
3936 safe_free(transfer_priv->hid_buffer);
3937 return LIBUSB_ERROR_IO;
3940 // Only write operations that completed synchronously need to free up
3941 // hid_buffer. For reads, copy_transfer_data() handles that process.
3943 safe_free(transfer_priv->hid_buffer);
3946 usbi_err(ctx, "program assertion failed - no data was transferred");
3949 if (size > (size_t)length) {
3950 usbi_err(ctx, "OVERFLOW!");
3951 r = LIBUSB_ERROR_OVERFLOW;
3953 windows_force_sync_completion(overlapped, (ULONG)size);
3956 transfer_priv->interface_number = (uint8_t)current_interface;
3961 static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
3963 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
3964 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
3965 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
3966 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
3968 int current_interface;
3970 CHECK_HID_AVAILABLE;
3972 current_interface = transfer_priv->interface_number;
3973 if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
3974 usbi_err(ctx, "program assertion failed: invalid interface_number");
3975 return LIBUSB_ERROR_NOT_FOUND;
3977 usbi_dbg("will use interface %d", current_interface);
3979 hid_handle = handle_priv->interface_handle[current_interface].api_handle;
3981 // Use CancelIoEx to cancel just a single transfer
3982 if (CancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped))
3983 return LIBUSB_SUCCESS;
3985 usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0));
3986 return LIBUSB_ERROR_NOT_FOUND;
3989 static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
3991 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
3993 int current_interface;
3995 CHECK_HID_AVAILABLE;
3997 // Flushing the queues on all interfaces is the best we can achieve
3998 for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
3999 hid_handle = handle_priv->interface_handle[current_interface].api_handle;
4000 if (HANDLE_VALID(hid_handle))
4001 HidD_FlushQueue(hid_handle);
4004 return LIBUSB_SUCCESS;
4007 static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
4009 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
4010 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
4011 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4013 int current_interface;
4015 CHECK_HID_AVAILABLE;
4017 current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
4018 if (current_interface < 0) {
4019 usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
4020 return LIBUSB_ERROR_NOT_FOUND;
4023 usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
4024 hid_handle = handle_priv->interface_handle[current_interface].api_handle;
4026 // No endpoint selection with Microsoft's implementation, so we try to flush the
4027 // whole interface. Should be OK for most case scenarios
4028 if (!HidD_FlushQueue(hid_handle)) {
4029 usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
4030 // Device was probably disconnected
4031 return LIBUSB_ERROR_NO_DEVICE;
4034 return LIBUSB_SUCCESS;
4037 // This extra function is only needed for HID
4038 static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
4040 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4041 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4042 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4043 int r = LIBUSB_TRANSFER_COMPLETED;
4044 uint32_t corrected_size = io_size;
4046 if (transfer_priv->hid_buffer != NULL) {
4047 // If we have a valid hid_buffer, it means the transfer was async
4048 if (transfer_priv->hid_dest != NULL) { // Data readout
4049 if (corrected_size > 0) {
4050 // First, check for overflow
4051 if (corrected_size > transfer_priv->hid_expected_size) {
4052 usbi_err(ctx, "OVERFLOW!");
4053 corrected_size = (uint32_t)transfer_priv->hid_expected_size;
4054 r = LIBUSB_TRANSFER_OVERFLOW;
4057 if (transfer_priv->hid_buffer[0] == 0) {
4058 // Discard the 1 byte report ID prefix
4060 memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
4062 memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
4065 transfer_priv->hid_dest = NULL;
4067 // For write, we just need to free the hid buffer
4068 safe_free(transfer_priv->hid_buffer);
4071 itransfer->transferred += corrected_size;
4077 * Composite API functions
4079 static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
4081 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4082 int r = LIBUSB_ERROR_NOT_FOUND;
4084 // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
4085 bool available[SUB_API_MAX + 1] = { 0 };
4087 for (i = 0; i < USB_MAXINTERFACES; i++) {
4088 switch (priv->usb_interface[i].apib->id) {
4089 case USB_API_WINUSBX:
4090 if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
4091 available[priv->usb_interface[i].sub_api] = true;
4094 available[SUB_API_MAX] = true;
4101 for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
4103 r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle);
4104 if (r != LIBUSB_SUCCESS)
4109 if (available[SUB_API_MAX]) { // HID driver
4110 r = hid_open(SUB_API_NOTSET, dev_handle);
4112 // On Windows 10 version 1903 (OS Build 18362) and later Windows blocks attempts to
4113 // open HID devices with a U2F usage unless running as administrator. We ignore this
4114 // failure and proceed without the HID device opened.
4115 if (r == LIBUSB_ERROR_ACCESS) {
4116 usbi_dbg("ignoring access denied error while opening HID interface of composite device");
4124 static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
4126 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4128 // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
4129 bool available[SUB_API_MAX + 1] = { 0 };
4131 for (i = 0; i < USB_MAXINTERFACES; i++) {
4132 switch (priv->usb_interface[i].apib->id) {
4133 case USB_API_WINUSBX:
4134 if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
4135 available[priv->usb_interface[i].sub_api] = true;
4138 available[SUB_API_MAX] = true;
4145 for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
4147 usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
4150 if (available[SUB_API_MAX]) // HID driver
4151 hid_close(SUB_API_NOTSET, dev_handle);
4154 static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
4156 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4158 CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface);
4160 return priv->usb_interface[iface].apib->
4161 claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
4164 static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
4166 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4168 CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting);
4170 return priv->usb_interface[iface].apib->
4171 set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
4174 static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
4176 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4178 CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface);
4180 return priv->usb_interface[iface].apib->
4181 release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
4184 static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
4186 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4187 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4188 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4189 struct libusb_config_descriptor *conf_desc;
4190 WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
4193 // Interface shouldn't matter for control, but it does in practice, with Windows'
4194 // restrictions with regards to accessing HID keyboards and mice. Try to target
4195 // a specific interface first, if possible.
4196 switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) {
4197 case LIBUSB_RECIPIENT_INTERFACE:
4198 iface = setup->Index & 0xFF;
4200 case LIBUSB_RECIPIENT_ENDPOINT:
4201 r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc);
4202 if (r == LIBUSB_SUCCESS) {
4203 iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF));
4204 libusb_free_config_descriptor(conf_desc);
4207 // Fall through if not able to determine interface
4213 // Try and target a specific interface if the control setup indicates such
4214 if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
4215 usbi_dbg("attempting control transfer targeted to interface %d", iface);
4216 if ((priv->usb_interface[iface].path != NULL)
4217 && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
4218 r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
4219 if (r == LIBUSB_SUCCESS)
4224 // Either not targeted to a specific interface or no luck in doing so.
4225 // Try a 2 pass approach with all interfaces.
4226 for (pass = 0; pass < 2; pass++) {
4227 for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
4228 if ((priv->usb_interface[iface].path != NULL)
4229 && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
4230 if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
4231 usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
4234 usbi_dbg("using interface %d", iface);
4235 r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
4236 // If not supported on this API, it may be supported on another, so don't give up yet!!
4237 if (r == LIBUSB_ERROR_NOT_SUPPORTED)
4244 usbi_err(ctx, "no libusb supported interfaces to complete request");
4245 return LIBUSB_ERROR_NOT_FOUND;
4248 static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
4249 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4250 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4251 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
4252 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4253 int current_interface;
4255 current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
4256 if (current_interface < 0) {
4257 usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
4258 return LIBUSB_ERROR_NOT_FOUND;
4261 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer);
4263 return priv->usb_interface[current_interface].apib->
4264 submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
4267 static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
4268 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4269 struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
4270 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
4271 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4272 int current_interface;
4274 current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
4275 if (current_interface < 0) {
4276 usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
4277 return LIBUSB_ERROR_NOT_FOUND;
4280 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer);
4282 return priv->usb_interface[current_interface].apib->
4283 submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
4286 static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
4288 struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
4289 struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
4290 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4291 int current_interface;
4293 current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
4294 if (current_interface < 0) {
4295 usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
4296 return LIBUSB_ERROR_NOT_FOUND;
4299 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt);
4301 return priv->usb_interface[current_interface].apib->
4302 clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
4305 static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
4307 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4308 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4309 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4310 int current_interface = transfer_priv->interface_number;
4312 if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
4313 usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
4314 return LIBUSB_ERROR_NOT_FOUND;
4317 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control);
4319 return priv->usb_interface[current_interface].apib->
4320 abort_control(priv->usb_interface[current_interface].sub_api, itransfer);
4323 static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
4325 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4326 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4327 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4328 int current_interface = transfer_priv->interface_number;
4330 if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
4331 usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
4332 return LIBUSB_ERROR_NOT_FOUND;
4335 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers);
4337 return priv->usb_interface[current_interface].apib->
4338 abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer);
4341 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
4343 struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
4346 bool available[SUB_API_MAX];
4348 for (i = 0; i < SUB_API_MAX; i++)
4349 available[i] = false;
4351 for (i = 0; i < USB_MAXINTERFACES; i++) {
4352 if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX)
4353 && (priv->usb_interface[i].sub_api != SUB_API_NOTSET))
4354 available[priv->usb_interface[i].sub_api] = true;
4357 for (i = 0; i < SUB_API_MAX; i++) {
4359 r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle);
4360 if (r != LIBUSB_SUCCESS)
4365 return LIBUSB_SUCCESS;
4368 static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
4370 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
4371 struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
4372 struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
4373 int current_interface = transfer_priv->interface_number;
4375 CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data);
4377 return priv->usb_interface[current_interface].apib->
4378 copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size);