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:
XHCI: Address Device command fails for devices behind a hub
Re: XHCI: Address Device command fails for devices behind a
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
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
Re: XHCI: Address Device command fails for devices behind a
Hi Ben, thanks for responding.
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.
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: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.
Could you expand on what the correct order of commands to the controller would be? Currently my code does: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).
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.
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: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.
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.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.
Working on managarm.
Re: XHCI: Address Device command fails for devices behind a
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.
Re: XHCI: Address Device command fails for devices behind a
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.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).
Re: XHCI: Address Device command fails for devices behind a
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. :-)Gigasoft wrote: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.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).
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