tags:

views:

66

answers:

1

One of our current milestones on our (open source) project at the moment is to complete USB support, and as such we're working hard on drivers at the moment. Our current development focuses on EHCI on both x86 and ARM (OMAP35xx SoC specifically, EHCI-only in the silicon of the board). We have mostly everything running smoothly in a variety of emulators - VMware (free and non-free versions), QEMU, and VirtualBox.

When we do testing on real hardware however, we get absolutely nowhere. The basic routine for device enumeration in our system goes something like this:

  1. Turn on port power (if the option is available) and wait for power to stabilise to the device
  2. Perform a port reset (held for 50 ms) and then wait as long as needed for the reset to complete (while loop)
  3. If the port has a device present, and is enabled, notify the system that a new USB device is available for initialisation.
  4. Send the SET ADDRESS command to assign an address to the device. This is where we run into problems everywhere:
    1. The SETUP transaction for this command completes without error
    2. The zero-length IN transaction (status phase) throws a transaction error, halts the qTD, and disables the port.

Our timing delays are basically the same as Linux's driver (if anything, longer).

According to the USB 2.0 specification, this behaviour is a "Port Error" (section 11.8) but to be completely honest I don't see how to translate its description of a port error into a working solution for our driver. As we are an open source project we also don't have the money to go out and purchase a proper hardware USB protocol analyser to investigate exactly what's going on on the line either.

Has anyone faced a similar problem and knows a solution?

+1  A: 

We have identified the cause of this problem has been a timing issue, but in our case the issue was too much of a delay.

By modifying our qTD/QH creation code to create a single QH with multiple linked qTDs associated with it, we've been able to get successful runs on physical hardware.

We also had to use te EHCI 64-bit data structures, which had not been implemented previously.

Matthew Iselin
Furthermore, on some real hardware stopping the host controller and resuming it during IRQ handling actually causes this error. I believe it has to do with the asynchronous schedule not being properly shut down, creating a desync in perceived state between the host and the device.
Matthew Iselin
How did you use 64-bit data structures? I thought the CTRLDSSEGMENT register was used as a selector for 64-bit systems.
Jonas Gulle
@Jonas: we just added the "64-bit extension fields" to our qTD structure - all the 64-bit data structures have is 5 more DWORDS. We had metadata in that area. This also simplifies our code for handling host controllers that do support 64-bit structures (as we don't need to have two different types). The CTRLDSSEGMENT register is just zero, I haven't yet found a use for it on our test systems.
Matthew Iselin
@Matthew I see, we stumbled across the exact same error :) After some strange memory corruptions during development we had to do the same in our implementation. AFAIK that wasn't really specified in the EHCI spec.
Jonas Gulle