Thursday, August 27, 2020

Hacker's Intro to USB hardware


Low-speed 1.5Mbps and full-speed 12Mbps USB, while more complicated than a UART, are still hacker-friendly.  As the standard approaches 25 years old, I've decided to document some of the more useful highlights I've learned.

While some USB devices will have accessible PCB pads where you can probe signals, it's best to have some breakouts and pass-thru cables with test points.  I've found broken micro-USB cables to be a cheap option.  I cut the micro-b end off, strip the wires, and solder them to some protoboard with 4 pin headers for the ground 5V, D+ and D- connections.  A crude USB voltage tester can be made with a couple silicon diodes and white or blue LED in series, powered by the 5V line.  In the 20mA range, a 1N4148 has a vF of about 0.8V, so a 3.4V LED will be brightly lit if 5V is present.  I've also made a custom USB-A extension cable with a section of the D+ and D- wires exposed for easy attachment of alligator clips.

Although USB power is 5V, typically at up to 500mA, the signalling is 3.3V.  At the host, the data pins are pulled to ground with a resistance between 15k and 22k, so a typical host will use 18.5k Ohms.  At the device, the D+(full-speed) or D-(low-speed) pin is pulled up to 3.3V to signal to the host that a device is attached.  The spec (pdf) shows this being done with a 1.5k pullup to 3.6V, creates a 18.5k/20k divider, resulting in 3.6V * 0.925 or 3.33V. I've found a 10k pullup to 5V works just fine, and many devices use a 1.5k pullup to 3.3V. since the spec requires a minimum of 2.7V for detection to work.  For a connected low-speed device (like a mouse), D+ will be near 0V, and D- will be near 3.3V.  For a full-speed device, the polarity will be reversed.  High-speed devices use low-swing 400mV signalling with both D+ and D- at 0V when idle.

The frequency counter on a multimeter can be used to tell if a device is alive, or if the host has failed to recognize it.  For a device that has been enumerated by a host, the host will send a keepalive signal to the device.  For a low-speed device, this is a single-ended 0 (SE0) where D- is pulled low for 1.3us every ms.  Therefore, a frequency of at least 1kHz will be detected on the D- line.

You can get a USB device to reconnect without unplugging it by forcing a bus reset.  This can be done by shorting the D+(full-speed) or D-(low-speed).  To avoid releasing the magic smoke by accidentally shorting the wrong connection, I suggest using 100-150 ohm resistor, which is still more than sufficient to reset the bus.