1
votes

I need an USB expert. I have a little hardware with a MAX3421 as USB host. I connect my printer that internally is composed of two devices: the printer itself and the scanner. Both are exposed as individual devices via a built-in hub. The devices are Full-Speed.

I have read the huge USB 2.0 manual (http://www.usb.org/developers/docs/usb20_docs) where I searched the way how to communicate through the hub with the devices behind, but the documentation is lacking this important detail.

I can send commands to the hub as decribed in chapter 11.24.2, like for example getting the Hub descriptor, SET_FEATURE(Reset) which resets a device in the printer, GET_STATUS(Port1) which returns correctly the 4 bytes with the state of port 1 in the hub.

But how do I get for example the device descriptor of the scanner?

I have assigned device address 1 to the hub and tried to communicate with the scanner/printer on device address 2 (supposing that it might be there) but the MAX3421 answers with a JERR error when I send a GET_DESCRIPTOR(Device) to device address 2 although both hub ports are powered and enabled after executing a Reset.

I have read a lot about SPLIT tokens, but they seem to be used only in High-Speed hubs. But the hub in my printer is Full-Speed.

The documentation does not say in any place how to do that. Where is this documented ?

2

2 Answers

1
votes

It is somewhat true that the process of device enumeration behind USB ports (root ports or hub ports) is not explained in the USB 2.0 specifications in layman terms, but the entire idea is embedded in all state machines for DS (downstream) port behavior.

Initially, ALL USB ports are disabled for communication. The only enabled function is "port connect" status. If several devices are plugged into several ports (either at once, or on power-up), no USB communication happens yet. ALL USB devices at power-up are designed to respond to DEFAULT address 00. But since no ports are enabled yet, no one responds to anything.

Then HOST then goes to each individual port that indicates "connection", starting from first port. The host sets the port into PORT_RESET mode, and the attached device will respond with either Chirp-K, or with nothing, or it initially has D- pulled, indicating that it is a LS device. All other devices are still behind disabled ports, and therefore see no activity.

After the first particular port gets correct speed status, the port gets enabled, and corresponding idle bus traffic starts, followed by get_descriptor command using the DEFAULT ADDRESS 00. Then the host assigns a non-trivial address to this device by SET_ADDRESS(). From this point the device will respond only to this particular assigned address.

Then the host enables the next port where it shows that something is attached. Again, all other non-enumerated devices are set to respond to the 00 address, but only one fresh port is enabled at a time. Since the first device has already an address that is different from default 00, no conflict happens, the first device simply ignores the traffic addressed to default pipe 00.

The process is repeated for the second device, first by communicating at 00 address, then next available USB address is assigned to the second device. And the process repeats for each port that shows attached status.

The keyword to remember is that a USB port is not "enabled" unless the host controller gets a command "port_reset" to root ports, or sends SET_FEATURE(PORT_RESET) (or something like that) to ports behind connected and already enumerated hub.

0
votes

No answer? Seems to be a difficult question.

Meanwhile I found the answer here: http://www.microchip.com/forums/m523103.aspx#523499

After sending a SET_FEATURE(Reset) to a port on the hub the device that is connected to that port appears with device address 00 on the USB bus. Then you can get the device descriptor the usual way and execute a SET_ADDRESS to this device.

The USB specification is definitely incomplete.