Re: Trouble with a USB 2.0 device with xhci_hcd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 24, 2013 at 10:51:04AM -0500, Alan Stern wrote:
> On Wed, 23 Jan 2013, Sarah Sharp wrote:
> 
> > > So I guess my next question is: What are you plans, if any, to add the
> > > "new" enumeration scheme to xHCI? Is this a huge amount of work?
> > 
> > Not a huge amount of work, but it does require an API change to the USB
> > host controller driver functions, so the patch itself is not likely to
> > get backported to stable kernels.  And I have no idea how the current
> > batch of USB 3.0 devices will react to an enumeration sequence change.
> 
> I thought this wasn't possible at all, because the xHCI hardware 
> automatically assigns an address to the device when a reset completes.

No, the xHCI hardware doesn't assign an address on reset completion.
The xHCI host assigns an address and sends the Set Address control
transfer when the Set Address command issued (when hcd->address_device
is called in hub_set_address).

The Set Address command does two things: it tells the xHC that the
default control endpoint ring and associated device context information
is set up, and it tells the xHC to issue the Set Address control
transfer.

There's a flag you can pass to the Set Address command to make it not
actually send the control transfer.  It's called 'Block Set Address
Request' (BSR).  After you issue the Set Address command with the BSR
flag set, you can get the device descriptor through the default control
endpoint.  Then you send the Set Address command again, with BSR
cleared, when you want to actually set the device address.

I asked the xHCI spec author to put the flag in, because I saw the two
enumeration schemes.  I just haven't had time or motivation to implement
it.

> "Old" scheme:
> 
> 	Reset
> 	Get device descriptor (8 bytes)
> 	Set address
> 	Get device descriptor (18 bytes)

Does the core really get the 8 byte device descriptor before set
address?  I'm pretty sure that would be skipped in the if block when we
try the old scheme:

        for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
                if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
                        struct usb_device_descriptor *buf;
                        int r = 0;

#define GET_DESCRIPTOR_BUFSIZE  64
                        buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
                        if (!buf) {
                                retval = -ENOMEM;
                                continue;
                        }

                        /* Retry on all errors; some devices are flakey.
                         * 255 is for WUSB devices, we actually need to use
                         * 512 (WUSB1.0[4.8.1]).
                         */
                        for (j = 0; j < 3; ++j) {
                                buf->bMaxPacketSize0 = 0;
                                r = usb_control_msg(udev, usb_rcvaddr0pipe(),
                                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                                        USB_DT_DEVICE << 8, 0,
                                        buf, GET_DESCRIPTOR_BUFSIZE,
                                        initial_descriptor_timeout);
			...
			}

		}
		...
                if (udev->wusb == 0) {
                        for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
                                retval = hub_set_address(udev, devnum);
                                if (retval >= 0)
                                        break;
                                msleep(200);
                        }
		...
		}

I thought the old scheme was:

	Reset
	Set address
	Get device descriptor (8 bytes)
	Get device descriptor (18 bytes)

> "New" scheme:
> 
> 	Reset
> 	Get device descriptor (64 bytes)
> 	Reset
> 	Set address
> 	Get device descriptor (18 bytes)
> 
> Given the way the hardware behaves, it's not really possible to do 
> either of these.

I think it's still possible to do the new enumeration scheme with the
flag to the Set Address command.  The new scheme would look like:

"New" scheme:
	Reset
	Set Address command (BSR flag set)
	Get device descriptor (64 bytes)
	Reset
	Reset Device command
	Set address
	Set Address command (BSR flag clear)
	Get device descriptor (18 bytes)

Does that make sense?

Sarah Sharp
--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux