Detect usb connection to phone or computer, to control power draw

Status
Not open for further replies.

ftrias

Well-known member
For my project, I'd like to be able to know if the Teensy 3.1 is connected to the USB port of a computer or a phone (via USB on-the-go or the iPhone usb adapter). The primary reason is so I can know how much power to draw for my various components. A computer allows me to draw more power, but with a phone, I have to turn a few things off. Maybe there's a way to know how much power a device can provide? Any ideas much appreciated!
 
The USB enumeration process is all about the USB device reporting its capabilities to the USB host. The host (Windows, Linux, Mac, Andriod, iOS) doesn't send info about itself to the device.

However, each host might do things somewhat differently. For example, Windows will request a specific string descriptor, which they use to detect certain type of devices. Today, Teensy just replies to those queries, but does nothing to log which steps the host took during enumeration. I've often wondered if some very simple logging could produce a useful "fingerprint" to distinguish between the different USB hosts.

Doing such a thing would involve adding code in usb_dev.h, to log which things the USB host did. Editing that code isn't easy, but if you want to try, I could suggest a few ideas.
 
Thanks for the insights. I was reading a little more on the USB spec and a few web sites suggest having two configurations, one for low power and one for high power. From http://www.beyondlogic.org/usbnutshell/usb5.shtml

For example, It is possible to have a high power bus powered configuration and a self powered configuration. If the device is plugged into a host with a mains power supply, the device driver may choose to enable the high power bus powered configuration enabling the device to be powered without a connection to the mains, yet if it is connected to a laptop or personal organiser it could enable the 2nd configuration (self powered) requiring the user to plug your device into the power point.

Does Teensy 3 support multiple configurations? From looking at usb_desc.c and usb_dev.c (SET_CONFIGURATION section), it seems there can be only one.
 
The existing code only supports a single configuration. Extending to 2 should be fairly straightforward. Just add a 2nd config descriptor, and another entry in usb_descriptor_list, with different bConfigurationValue and bMaxPower values, but everything else identical. Of course, change bNumConfigurations in the device descriptor.

Whatever configuration the host chooses is written into usb_configuration. Today it's always 1, since only a single config is offered with bConfigurationValue = 1.
 
I'm trying to implement your suggestions and having a problem. It compiles fine but when plugged in, Windows doesn't recognize it at all. Mac sees it but doesn't configure it:

Code:
          Product ID: 0x0485
          Vendor ID: 0x16c0
          Version: 6.00
          Serial Number: 545260
          Speed: Up to 12 Mb/sec
          Manufacturer: Teensyduino
          Location ID: 0x14100000 / 3
          Current Available (mA): 500
          Current Required (mA): Unknown (Device has not been configured)

This is what I did. I created a new config descriptor identical to the first except for the bConfigurationValue and bMaxPower:

Code:
static uint8_t config_descriptor2[] = {
        // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
        9,                                      // bLength;
        2,                                      // bDescriptorType;
        LSB(CONFIG_DESC_SIZE),                 // wTotalLength
        MSB(CONFIG_DESC_SIZE),
        NUM_INTERFACE,                          // bNumInterfaces
        2,                                      // bConfigurationValue
        0,                                      // iConfiguration
        0xC0,                                   // bmAttributes
        250,                                     // bMaxPower

#ifdef CDC_IAD_DESCRIPTOR
        // interface association descriptor, USB ECN, Table 9-Z
        8,                                      // bLength
        11,                                     // bDescriptorType
etc, etc.

The I added it to usb_descriptor_list:

Code:
usb_descriptor_list_t usb_descriptor_list[] = {
        //wValue, wIndex, address,          length
        {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
        {0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)},
        {0x0200, 0x0001, config_descriptor2, sizeof(config_descriptor2)},
#ifdef SEREMU_INTERFACE
        {0x2200, SEREMU_INTERFACE, seremu_report_desc, sizeof(seremu_report_desc)},
        {0x2100, SEREMU_INTERFACE, config_descriptor+SEREMU_DESC_OFFSET, 9},

Also changed device_descriptor bNumConfigurations from 1 to 2.

Code:
static uint8_t device_descriptor[] = {
        18,                                     // bLength
        1,                                      // bDescriptorType
        0x00, 0x01,                             // bcdUSB
#ifdef DEVICE_CLASS
        DEVICE_CLASS,                           // bDeviceClass
#else
        0,
#endif
#ifdef DEVICE_SUBCLASS
        DEVICE_SUBCLASS,                        // bDeviceSubClass
#else
        0,
#endif
#ifdef DEVICE_PROTOCOL
        DEVICE_PROTOCOL,                        // bDeviceProtocol
#else
        0,
#endif
        EP0_SIZE,                               // bMaxPacketSize0
        LSB(VENDOR_ID), MSB(VENDOR_ID),         // idVendor
        LSB(PRODUCT_ID), MSB(PRODUCT_ID),       // i8dProduct
#ifdef BCD_DEVICE
        LSB(BCD_DEVICE), MSB(BCD_DEVICE),       // bcdDevice
#else
        0x00, 0x06,                             // bcdDevice
#endif
        1,                                      // iManufacturer
        2,                                      // iProduct
        3,                                      // iSerialNumber
        2                                       // bNumConfigurations
};
 
I think I found my problem. In usb_descriptor_list, the added line should read:

Code:
        {0x0201, 0x0000, config_descriptor2, sizeof(config_descriptor2)},
 
Status
Not open for further replies.
Back
Top