On Tue, 12 Sep 2006, David Brownell wrote:
> > First of all, at91_udc activates the pullup in ..._register_driver(),
> > so even if I don't load any gadget module, the host starts enumeration.
> 
> I don't follow.  If you (successfully) register a gadget driver
> and don't usb_gadget_disconnect() in the gadget driver bind()
> method, it's *required* to be ready to enumerate.  What's the
> problem here? There's no "load" operation, so maybe you're
> wrongly thinking that register() isn't the last step before
> the host may enumerate...

I'm sorry, after couple of hours spent on this issue I got it all wrong.
You're right, usb_gadget_register_driver() works as expected. I wrongly 
assumed that this function is called when the peripherial driver is
loaded, not the gadget driver.

Also I forgot to mention that I was unable to use at91_udc with gadgetfs
because gadgetfs' driver uses .speed = USB_SPEED_HIGH for probing
controller name. at91_udc supports only USB_SPEED_FULL, so it seems that
no one has tested this setup recently. The patch is trivial, as the real
usb_gadget_driver structure deals with that:

 static struct usb_gadget_driver probe_driver = {
+#ifdef CONFIG_USB_GADGET_DUALSPEED
        .speed          = USB_SPEED_HIGH,
+#else
+       .speed          = USB_SPEED_FULL,
+#endif

I can send it as a separate patch in the proper format to this mailing
list if you wish. But I'd like to know first if it isn't just my
misunderstanding of the code.

> Please explain the problem you're seeing ...  once you register the
> gadget driver (there's no notion of "loaded"), software control over
> the pullup is active, and will default to "peripheral responds to host".
> Last I checked, that was also true of omap_udc, though the details are
> clearly different.

I have at91_udc compiled into the kernel and gadgetfs as a module (so I
can easily play with other gadget drivers). After bootup I insmod the
gadgetfs module. At this point connecting the device to a host has no
effect, because gadgetfs hasn't called usb_gadget_register_driver() yet.
Then I mount gadgetfs, but don't load userspace driver, reconnect the
device and get a kernel panic.

After further debugging I found that error handling in at91_udc's
usb_gadget_register_driver seems broken:

        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.driver_data = &driver->driver;
        udc->enabled = 1;
        udc->selfpowered = 1;
        
        retval = driver->bind(&udc->gadget);
        if (retval) {
                DBG("driver->bind() returned %d\n", retval);
                udc->driver = NULL;
                return retval;
        }

The dummy registration to get the controller name for gadgetfs returns
error on bind(), so udc->gadget, udc->enabled and udc->selfpowered are
left in a initialized state. Unfortunately the VBUS interrupt handler
enables pullups if udc->enabled is set without checking for udc->driver.
The enumeration begins and some bad things happen.

I fixed this with the following:

        retval = driver->bind(&udc->gadget);
        if (retval) {
                DBG("driver->bind() returned %d\n", retval);
                udc->driver = NULL;
+               udc->gadget.dev.driver = NULL;
+               udc->gadget.dev.driver_data = NULL;
+               udc->enabled = 0;
+               udc->selfpowered = 0;
                return retval;
        }

An extra check in at91_vbus_session() would be nice:

-       pullup(udc, is_active);
+       if (udc->driver)
+               pullup(udc, is_active);
+       else
+               pullup(udc, 0);

We could also modify handle_setup() so a spurious enumeration won't
cause kernel panics:

-       status = udc->driver->setup(&udc->gadget, &pkt.r);
+       if (udc->driver)
+               status = udc->driver->setup(&udc->gadget, &pkt.r);
+       else
+               status = -ENODEV;

And voila! Everything seems to work fine now. If you think that these
modifications are acceptable, I'll send a patch.

All the tests were done on 2.6.18-rc7, as you suggested. Except my own
board definition file (copy of board-at91rm9200dk.c with slightly
modified pin assignments) the kernel is unmodified.

Regards,
Wojtek

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to