USB Host vs. Device Detection

detectiondevicehostusb

Here is a problem to which the obvious answer is "use a switch," but that is not permitted in the design. 😉

I am writing software for a USB audio application that is supposed to be able to play audio from iP{od,ad,hone}s, Android devices, and also Samsung Audio from Samsung devices.

(quick note: USB Device with capital D = USB Peripheral = device with B-Connector)

I wouldn't have to ask this question if all these devices played nice and were just USB Devices. iPxx and Android devices are USB Devcies, but Samsung devices playing Samsung Audio act as USB Hosts (but they can also be USB Devices not playing Samsung Audio but as regular Android devices).

All devices have to connect to a single Type Standard-A connector on our embedded system running on a PIC32. Yeah, I know that's not USB-legal, but that's what the requirements are.

Since both USB Hosts and Devices have to connect to our embedded device, I need a way to detect when a device is plugged-in if it is a USB Host or a USB Device, so that my USB system shuts/brings itself up with the correct role depending on the attached device.

I have read the On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Spec. The closest thing I got was Attach Detection Protocol. That helps with the general detection of attached devices but doesn't help detect the role of the device (Host or Device). Our hardware design is not final yet, so I am able to consider any hardware solutions that help that aren't… well… a switch. 😉

Look forward to the community's insight.

Best Answer

I think you should be able to detect it quite reliably by knowing the electrical properties of the pins. USB hosts pull the DP and DN data lines low with 15kOhm resistance. USB devices pull the DP line (DN line if it's a slow speed device) to 3 volts with a 1.5K resistance. If the device at the other end pulls up and also you pull up, nothing would happen because the device doesn't react to the extra pull-up. So you could use this to check if the other end starts to send packets to the bus.

I suggest a procedure something like this:

You could start by pulling the DN line weakly high (with something like 200K to 1M resistor). You could detect a pull-down on the DN line to give a first hint that there's a host at the other side.

Then measure the VBUS, if it's high, it's a further indication that there is a host at the other side. If so, activate a 1.5k pull-up (to 3 volts) on the DP line and listen for incoming packets. If there actually is a host on the other side, it will issue a bus reset and send a GET_DESCRIPTOR packet to the bus. If this happens, you know that the other chip is a host. I suggest to do it in this order as if there's a device at the other side, it will not react to the DP pull-up.

If nothing happens, there may be a device at the other side. Release your DP pull-up and see if it's still pulled up at the other side. If that is so, then there is probably a self-powered device at the other side. If not, then start driving the VBUS line to 5 volts. At this time at the latest you should see the device's 1.5k pull-up tp 3 volts on the DP line. If you see instead 3 volts in the DN line, then there's a slow speed device such as a keyboard or a mouse at the other side.

Now act as a host and issue a BUS RESET and GET DESCRIPTOR : DEVICE DESCRIPTOR to address 0, endpoint 0. The device should now answer and finally at this point you know for sure that there is a usb device at the other end. If you haven't enabled your 5V drive to VBUS so far, I suggest that you enable it now. Test with all the devices you intend to support.

Ok, this is a hack, and the official bus doesn't work this way because if both ends would work like this then it would be a matter of luck (timing) if it detects correctly or not. But if the other end is a well-behaving USB entity, then I think that it should work. I've done a fair bit of work on the USB, but not this exact thing.