From 24494ed5db27737fc607fc35dda722521c9fe4d4 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 5 Oct 2010 12:50:13 +0100 Subject: [PATCH] Windows: Allow claiming any interface in composite device using WinUSB Issue reported by Benjamin Dobell, see #48. The call to WinUsb_QueryInterfaceSettings() is removed since it doesn't work on any other interface but the first (a WinUSB limitation). This allows the use of WinUSB.sys in lieu of the usbccgp.sys "USB Generic Parent" default driver for composite devices. --- libusb/os/windows_usb.c | 63 ++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index b999746..9498e14 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -2504,21 +2504,42 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle); struct windows_device_priv *priv = __device_priv(dev_handle->dev); - bool is_composite = (priv->apib->id == USB_API_COMPOSITE); + bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); HANDLE file_handle, winusb_handle; - USB_INTERFACE_DESCRIPTOR if_desc; UCHAR policy; uint8_t endpoint_address; int i; CHECK_WINUSB_AVAILABLE; - // interfaces for composite devices are always independent, therefore - // "alt" interfaces are only found on non-composite - if ((!is_composite) && (iface != 0)) { + // If the device is composite, but using the default Windows composite parent driver (usbccgp) + // or if it's the first WinUSB interface, we get a handle through WinUsb_Initialize(). + if ((is_using_usbccgp) || (iface == 0)) { + // composite device (independent interfaces) or interface 0 + winusb_handle = handle_priv->interface_handle[iface].api_handle; + file_handle = handle_priv->interface_handle[iface].dev_handle; + if ((file_handle == 0) || (file_handle == INVALID_HANDLE_VALUE)) { + return LIBUSB_ERROR_NOT_FOUND; + } + + if (!WinUsb_Initialize(file_handle, &winusb_handle)) { + usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + + switch(GetLastError()) { + case ERROR_BAD_COMMAND: // The device was disconnected + return LIBUSB_ERROR_NO_DEVICE; + default: + usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + } + handle_priv->interface_handle[iface].api_handle = winusb_handle; + } else { + // For all other interfaces, use WinUsb_GetAssociatedInterface() winusb_handle = handle_priv->interface_handle[0].api_handle; - // It is a requirement on Windows that to claim an interface >= 1 - // on a non-composite WinUSB device, you must first have claimed interface 0 + // It is a requirement for multiple interface devices using WinUSB that you + // must first claim the first interface before you claim any other if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) { #if defined(AUTO_CLAIM) file_handle = handle_priv->interface_handle[0].dev_handle; @@ -2549,35 +2570,7 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i return LIBUSB_ERROR_ACCESS; } } - } else { - // composite device (independent interfaces) or interface 0 - winusb_handle = handle_priv->interface_handle[iface].api_handle; - file_handle = handle_priv->interface_handle[iface].dev_handle; - if ((file_handle == 0) || (file_handle == INVALID_HANDLE_VALUE)) { - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!WinUsb_Initialize(file_handle, &winusb_handle)) { - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - - switch(GetLastError()) { - case ERROR_BAD_COMMAND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - default: - usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - handle_priv->interface_handle[iface].api_handle = winusb_handle; } - if (!WinUsb_QueryInterfaceSettings(winusb_handle, 0, &if_desc)) { - usbi_err(ctx, "could not query interface settings for interface %d: %s", iface, windows_error_str(0)); - } else if (if_desc.bInterfaceNumber != iface) { - usbi_warn(ctx, "program assertion failed - WinUSB interface %d found at position %d", - if_desc.bInterfaceNumber, iface); - } - usbi_dbg("claimed interface %d", iface); handle_priv->active_interface = iface; -- 2.7.4