XHCI: Address Device command fails for devices behind a hub

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
qookie
Member
Member
Posts: 72
Joined: Sun Apr 30, 2017 12:16 pm
Libera.chat IRC: qookie
Location: Poland

XHCI: Address Device command fails for devices behind a hub

Post by qookie »

Hi,

as stated in the title, I've a problem with the Address Device command failing with an USB transaction error for devices that are behind a hub. According to the XHCI spec this means that the SET_ADDRESS request has failed, but I can't think of a reason why.
I've tried a few of HS, FS and LS devices, and noticed that it only fails for HS devices. One thing also worth noting is that one device I tried is an USB 3 SSD, which is addressed correctly when plugged into an USB 3 root port, and yet fails when plugged into the USB 2 hub port.

I've observed this on a Raspberry Pi 4, which uses the VL805 XHCI controller, which has an integrated 4 port USB 2 hub (which is the main reason for implementing hub support right now), and I unfortunately don't have any other USB 2 HS hubs (only an FS one).

The code for the XHCI driver can be found here: https://github.com/qookei/managarm/tree ... s/xhci/src, and the USB hub driver code is here https://github.com/qookei/managarm/blob ... rc/hub.cpp.
One point of interest is the place the device is actually addressed: https://github.com/qookei/managarm/blob ... #L830-L902

For reference, here are the logs produced by this code:
Image
Working on managarm.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: XHCI: Address Device command fails for devices behind a

Post by BenLunt »

When you are setting the address of the device, you aren't actually sending the SET_ADDRESS request, correct? xHCI does not allow the SET_ADDRESS request to populate the bus.

You must send the Set Address command twice, once to set the address of the device (Block bit set), then a little bit later to let the xHCI send the SET_ADDRESS request (Block bit clear).

Also, since it is only happening on High-speed devices, it probably isn't with your "addressDevice()" code. It probably is something else pertaining to the way you set your CONTEXTs with high-speed devices.

Is the hub a high-speed hub? You say you only have a full-speed hub. Remember, a high-speed device plugged into a full-speed hub is now a full-speed device. You have to account for this.

Ben
User avatar
qookie
Member
Member
Posts: 72
Joined: Sun Apr 30, 2017 12:16 pm
Libera.chat IRC: qookie
Location: Poland

Re: XHCI: Address Device command fails for devices behind a

Post by qookie »

Hi Ben, thanks for responding.
BenLunt wrote:When you are setting the address of the device, you aren't actually sending the SET_ADDRESS request, correct? xHCI does not allow the SET_ADDRESS request to populate the bus.
Correct, I'm letting the controller do it via the Address Device command. I only mentioned it because the spec says that that error happens when the SET_ADDRESS request failed (stall or such).
BenLunt wrote:You must send the Set Address command twice, once to set the address of the device (Block bit set), then a little bit later to let the xHCI send the SET_ADDRESS request (Block bit clear).
Could you expand on what the correct order of commands to the controller would be? Currently my code does:
1. Enable Slot,
2. Address Device (with the slot and EP1 contexts set up in the input context) with BSR=0

And afterwards carries on with the device, it reads the device descriptor to get the class, vendor and product IDs etc, and finally at the request of a class/device-specific driver reads more descriptors, sets up other EPs as per the configuration descriptor (via the Configure Endpoint command), and sets the configuration via SET_CONFIGURATION request.

As mentioned this order of things works for one of the USB 3 devices I tried when plugged into an USB 3 root port instead of the HS hub, so it is probably indeed likely that this is not the problem in this case.
BenLunt wrote:Also, since it is only happening on High-speed devices, it probably isn't with your "addressDevice()" code. It probably is something else pertaining to the way you set your CONTEXTs with high-speed devices.
As far as I can tell the only difference is that LS/FS devices require the hub slot and port number fields filled out for split transactions, and for HS those fields should be 0, which is what I do in my code.
BenLunt wrote:Is the hub a high-speed hub? You say you only have a full-speed hub. Remember, a high-speed device plugged into a full-speed hub is now a full-speed device. You have to account for this.
The hub I was testing with is integrated into the XHCI controller chip, which has only one USB 2 root port, and an integrated 4 port hub (but 4 USB 3 root ports and no hub on those). The FS hub I mentioned is a standalone one, and I only mentioned it to say I can't test other HS hubs or on any other controller etc.
Working on managarm.
rdos
Member
Member
Posts: 3296
Joined: Wed Oct 01, 2008 1:55 pm

Re: XHCI: Address Device command fails for devices behind a

Post by rdos »

I'm more inclined to think that the hub is handled incorrectly. USB 2 hubs must be programmed correctly, which include the speed of the device connected to ports. The hub itself is running as an USB 2 device, but the hub ports either are directly connected or go through a transaction interface that converts to lower speed. This is not automatic. I think that is why certain device types works while other doesn't.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: XHCI: Address Device command fails for devices behind a

Post by Gigasoft »

You must send the Set Address command twice, once to set the address of the device (Block bit set), then a little bit later to let the xHCI send the SET_ADDRESS request (Block bit clear).
This is usually not required. The BSR bit exists only as a workaround for some broken device or devices which the specification does not name, which require a nonstandard initialization sequence.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: XHCI: Address Device command fails for devices behind a

Post by BenLunt »

Gigasoft wrote:
You must send the Set Address command twice, once to set the address of the device (Block bit set), then a little bit later to let the xHCI send the SET_ADDRESS request (Block bit clear).
This is usually not required. The BSR bit exists only as a workaround for some broken device or devices which the specification does not name, which require a nonstandard initialization sequence.
And you are absolutely correct. However, how do you know that the user hasn't plugged one of these broken devices into the port? This is the reason for the multiple calls. :-)
Sending the address command once, works on most devices, while sending it twice (as I suggest) works on most devices "plus" those broken devices. I have witnessed this personally.

Cheers,
Ben
Post Reply