On Tue, 30 Dec 2008, Erik Ekman wrote: > > Okay, this is starting to narrow things down. Here's a kernel patch to > > add some extra debugging information to the log. Run the same test as > > before (you don't need to set usbfs_snoop this time) and post the > > resulting dmesg log. > > > > Alan Stern > > > > Here is the resulting dmesg of tf-tool --acquire: The initial stuff is all normal. ... > findintfep: 0 > checkintf: 0 > ep addr: 129: ptr: f6526f40 Through here. > findintfep: 0 > checkintf: 0 > ep addr: 129: ptr: 00000000 > findintfep: 0 > checkintf: 0 > ep addr: 129: ptr: 00000000 > findintfep: 0 > checkintf: 0 > ep addr: 129: ptr: 00000000 > findintfep: 0 > checkintf: 0 > ep addr: 2: ptr: 00000000 This part indicates where the trouble starts. And I believe I see the cause of the problem; the interface gets disabled but never re-enabled. You can remove the earlier patch and try the patch below; it should fix this problem. Timo, pay attention to this: There may still be another problem lurking in the library source code. _libthinkfinger_usb_hello() behaves very badly: It sends a direct Set-Config request without using usb_set_configuration(). You should remove the entire first call to usb_control_msg() from that function. I know the comment says "should not be relevant", but the comment is wrong. If it turns out that the Set-Config really is needed (it might indeed be necessary for Windows systems), it shouldn't be done this way. Instead, usb_set_configuration() should be called from within _libthinkfinger_usb_init(), just before usb_claim_interface(). Alan Stern Index: 2.6.28/drivers/usb/core/usb.h =================================================================== --- 2.6.28.orig/drivers/usb/core/usb.h +++ 2.6.28/drivers/usb/core/usb.h @@ -10,7 +10,9 @@ extern int usb_create_ep_files(struct de extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); extern void usb_enable_endpoint(struct usb_device *dev, - struct usb_host_endpoint *ep); + struct usb_host_endpoint *ep, bool reset_toggle); +extern void usb_enable_interface(struct usb_device *dev, + struct usb_interface *intf, bool reset_toggles); extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf); Index: 2.6.28/drivers/usb/core/driver.c =================================================================== --- 2.6.28.orig/drivers/usb/core/driver.c +++ 2.6.28/drivers/usb/core/driver.c @@ -279,9 +279,12 @@ static int usb_unbind_interface(struct d * altsetting means creating new endpoint device entries). * When either of these happens, defer the Set-Interface. */ - if (intf->cur_altsetting->desc.bAlternateSetting == 0) - ; /* Already in altsetting 0 so skip Set-Interface */ - else if (!error && intf->dev.power.status == DPM_ON) + if (intf->cur_altsetting->desc.bAlternateSetting == 0) { + /* Already in altsetting 0 so skip Set-Interface. + * Just re-enable it without affecting the endpoint toggles. + */ + usb_enable_interface(udev, intf, false); + } else if (!error && intf->dev.power.status == DPM_ON) usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); else Index: 2.6.28/drivers/usb/core/message.c =================================================================== --- 2.6.28.orig/drivers/usb/core/message.c +++ 2.6.28/drivers/usb/core/message.c @@ -1113,22 +1113,26 @@ void usb_disable_device(struct usb_devic * usb_enable_endpoint - Enable an endpoint for USB communications * @dev: the device whose interface is being enabled * @ep: the endpoint + * @reset_toggle: flag to set the endpoint's toggle back to 0 * - * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers. + * Resets the endpoint toggle if asked, and sets dev->ep_{in,out} pointers. * For control endpoints, both the input and output sides are handled. */ -void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep) +void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep, + bool reset_toggle) { int epnum = usb_endpoint_num(&ep->desc); int is_out = usb_endpoint_dir_out(&ep->desc); int is_control = usb_endpoint_xfer_control(&ep->desc); if (is_out || is_control) { - usb_settoggle(dev, epnum, 1, 0); + if (reset_toggle) + usb_settoggle(dev, epnum, 1, 0); dev->ep_out[epnum] = ep; } if (!is_out || is_control) { - usb_settoggle(dev, epnum, 0, 0); + if (reset_toggle) + usb_settoggle(dev, epnum, 0, 0); dev->ep_in[epnum] = ep; } ep->enabled = 1; @@ -1138,17 +1142,18 @@ void usb_enable_endpoint(struct usb_devi * usb_enable_interface - Enable all the endpoints for an interface * @dev: the device whose interface is being enabled * @intf: pointer to the interface descriptor + * @reset_toggles: flag to set the endpoints' toggles back to 0 * * Enables all the endpoints for the interface's current altsetting. */ -static void usb_enable_interface(struct usb_device *dev, - struct usb_interface *intf) +void usb_enable_interface(struct usb_device *dev, + struct usb_interface *intf, bool reset_toggles) { struct usb_host_interface *alt = intf->cur_altsetting; int i; for (i = 0; i < alt->desc.bNumEndpoints; ++i) - usb_enable_endpoint(dev, &alt->endpoint[i]); + usb_enable_endpoint(dev, &alt->endpoint[i], reset_toggles); } /** @@ -1271,7 +1276,7 @@ int usb_set_interface(struct usb_device * during the SETUP stage - hence EP0 toggles are "don't care" here. * (Likewise, EP0 never "halts" on well designed devices.) */ - usb_enable_interface(dev, iface); + usb_enable_interface(dev, iface, true); if (device_is_registered(&iface->dev)) usb_create_sysfs_intf_files(iface); @@ -1346,7 +1351,7 @@ int usb_reset_configuration(struct usb_d alt = &intf->altsetting[0]; intf->cur_altsetting = alt; - usb_enable_interface(dev, intf); + usb_enable_interface(dev, intf, true); if (device_is_registered(&intf->dev)) usb_create_sysfs_intf_files(intf); } @@ -1604,7 +1609,7 @@ free_interfaces: alt = &intf->altsetting[0]; intf->cur_altsetting = alt; - usb_enable_interface(dev, intf); + usb_enable_interface(dev, intf, true); intf->dev.parent = &dev->dev; intf->dev.driver = NULL; intf->dev.bus = &usb_bus_type; Index: 2.6.28/drivers/usb/core/usb.c =================================================================== --- 2.6.28.orig/drivers/usb/core/usb.c +++ 2.6.28/drivers/usb/core/usb.c @@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; /* ep0 maxpacket comes later, from device descriptor */ - usb_enable_endpoint(dev, &dev->ep0); + usb_enable_endpoint(dev, &dev->ep0, true); dev->can_submit = 1; /* Save readable and stable topology id, distinguishing devices Index: 2.6.28/drivers/usb/core/hub.c =================================================================== --- 2.6.28.orig/drivers/usb/core/hub.c +++ 2.6.28/drivers/usb/core/hub.c @@ -2385,7 +2385,7 @@ void usb_ep0_reinit(struct usb_device *u { usb_disable_endpoint(udev, 0 + USB_DIR_IN); usb_disable_endpoint(udev, 0 + USB_DIR_OUT); - usb_enable_endpoint(udev, &udev->ep0); + usb_enable_endpoint(udev, &udev->ep0, true); } EXPORT_SYMBOL_GPL(usb_ep0_reinit); -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html