Windows: fixed default WinUSB timeout and ineffective policy settings
authorGraeme Gill <graeme@argyllcms.com>
Tue, 8 Mar 2011 17:39:16 +0000 (17:39 +0000)
committerPeter Stuge <peter@stuge.se>
Mon, 13 Jun 2011 20:06:31 +0000 (22:06 +0200)
* default WinUSB timeout was 5 seconds, which may be to small.
  PIPE_TRANSFER_TIMEOUT policy is now set to infinite for all EPs.
* other WinUSB policy settings were called before the endpoints
  had been set. This is now fixed.

libusb/os/windows_usb.c

index 6983287..7ae3034 100644 (file)
@@ -65,6 +65,7 @@ static int winusb_init(struct libusb_context *ctx);
 static int winusb_exit(void);
 static int winusb_open(struct libusb_device_handle *dev_handle);
 static void winusb_close(struct libusb_device_handle *dev_handle);
+static int winusb_configure_endpoints(struct libusb_device_handle *dev_handle, int iface);
 static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface);
 static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface);
 static int winusb_submit_control_transfer(struct usbi_transfer *itransfer);
@@ -555,16 +556,17 @@ static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
 /*
  * Populate the endpoints addresses of the device_priv interface helper structs
  */
-static int windows_assign_endpoints(struct libusb_device *dev, int iface, int altsetting)
+static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
        int i, r;
-       struct windows_device_priv *priv = __device_priv(dev);
+       struct windows_device_priv *priv = __device_priv(dev_handle->dev);
        struct libusb_config_descriptor *conf_desc;
        const struct libusb_interface_descriptor *if_desc;
+       struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
 
-       r = libusb_get_config_descriptor(dev, 0, &conf_desc);
+       r = libusb_get_config_descriptor(dev_handle->dev, 0, &conf_desc);
        if (r != LIBUSB_SUCCESS) {
-               usbi_warn(NULL, "could not read config descriptor: error %d", r);
+               usbi_warn(ctx, "could not read config descriptor: error %d", r);
                return r;
        }
 
@@ -588,6 +590,11 @@ static int windows_assign_endpoints(struct libusb_device *dev, int iface, int al
        }
        libusb_free_config_descriptor(conf_desc);
 
+       // Extra init is required for WinUSB endpoints
+       if (priv->apib->id == USB_API_WINUSB) {
+               return winusb_configure_endpoints(dev_handle, iface);
+       }
+
        return LIBUSB_SUCCESS;
 }
 
@@ -1674,7 +1681,7 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int
        r = priv->apib->claim_interface(dev_handle, iface);
 
        if (r == LIBUSB_SUCCESS) {
-               r = windows_assign_endpoints(dev_handle->dev, iface, 0);
+               r = windows_assign_endpoints(dev_handle, iface, 0);
        }
 
        return r;
@@ -1691,7 +1698,7 @@ static int windows_set_interface_altsetting(struct libusb_device_handle *dev_han
        r = priv->apib->set_interface_altsetting(dev_handle, iface, altsetting);
 
        if (r == LIBUSB_SUCCESS) {
-               r = windows_assign_endpoints(dev_handle->dev, iface, altsetting);
+               r = windows_assign_endpoints(dev_handle, iface, altsetting);
        }
 
        return r;
@@ -2377,6 +2384,50 @@ static void winusb_close(struct libusb_device_handle *dev_handle)
        }
 }
 
+static int winusb_configure_endpoints(struct libusb_device_handle *dev_handle, int iface)
+{
+       struct windows_device_handle_priv *handle_priv = __device_handle_priv(dev_handle);
+       struct windows_device_priv *priv = __device_priv(dev_handle->dev);
+       HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
+       UCHAR policy;
+       ULONG timeout = 0;
+       uint8_t endpoint_address;
+       int i;
+
+       CHECK_WINUSB_AVAILABLE;
+
+       // With handle and enpoints set (in parent), we can setup the default pipe properties
+       // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
+       for (i=-1; i<priv->usb_interface[iface].nb_endpoints; i++) {
+               endpoint_address =(i==-1)?0:priv->usb_interface[iface].endpoint[i];
+               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
+                       PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) {
+                       usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
+               }
+               if (i == -1) continue;  // Other policies don't apply to control endpoint
+               policy = false;
+               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
+                       SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
+                       usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
+               }
+               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
+                       IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) {
+                       usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
+               }
+               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
+                       ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) {
+                       usbi_dbg("failed to disable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
+               }
+               policy = true;
+               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
+                       AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) {
+                       usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
+               }
+       }
+
+       return LIBUSB_SUCCESS;
+}
+
 static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface)
 {
        struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
@@ -2384,9 +2435,6 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i
        struct windows_device_priv *priv = __device_priv(dev_handle->dev);
        bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
        HANDLE file_handle, winusb_handle;
-       UCHAR policy;
-       uint8_t endpoint_address;
-       int i;
 
        CHECK_WINUSB_AVAILABLE;
 
@@ -2452,31 +2500,6 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i
        usbi_dbg("claimed interface %d", iface);
        handle_priv->active_interface = iface;
 
-       // With handle and enpoints set (in parent), we can setup the default
-       // pipe properties (copied from libusb-win32-v1)
-       // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
-       for (i=0; i<priv->usb_interface[iface].nb_endpoints; i++) {
-               endpoint_address = priv->usb_interface[iface].endpoint[i];
-               policy = false;
-               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
-                       SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
-                       usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
-               }
-               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
-                       IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) {
-                       usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
-               }
-               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
-                       ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) {
-                       usbi_dbg("failed to disable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
-               }
-               policy = true;
-               if (!WinUsb_SetPipePolicy(winusb_handle, endpoint_address,
-                       AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) {
-                       usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
-               }
-       }
-
        return LIBUSB_SUCCESS;
 }