Issue developing a USB device with two config descriptors

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
aicastell
Posts: 12
Joined: Tue Sep 04, 2018 11:03 am
Has thanked: 6 times

Issue developing a USB device with two config descriptors

Postby aicastell » Tue Sep 04, 2018 11:33 am

This is my first question on this forum. Hope this question being useful to someone else.

I want my USB device being able to manage two different configs, but I haven't found any example on google with two different config, so that's why I am asking on this forum.

I have used a Chibios example with creates a USB device descriptor with a single config descriptor. After that I was able to add a second config descriptor (USBDescriptor type) in my source code (bConfigurationValue=1 and bConfigurationValue=2).

My issue is related with my usb_get_descriptor_cb callback (defined as second parameter of my USBConfig variable):

static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang);

Parameter "dtype" is used in a switch case with USB_DESCRIPTOR_CONFIGURATION to return the config descriptor. But, how can I get the config identifier (bConfigurationValue) to know which configuration descriptor should be returned?

Thanks a lot in advance! :-)

apmorton
Posts: 36
Joined: Fri Sep 29, 2017 10:26 am
Been thanked: 16 times

Re: Issue developing a USB device with two config descriptors

Postby apmorton » Wed Sep 05, 2018 11:37 am

the configuration index should be in dindex - exactly how it works for string descriptors.

aicastell
Posts: 12
Joined: Tue Sep 04, 2018 11:03 am
Has thanked: 6 times

Re: Issue developing a USB device with two config descriptors

Postby aicastell » Thu Sep 06, 2018 11:44 am

So depending on dtype, the dindex meaning changes. That make sense. Thanks a lot for your answer!

However, I have tried re-implement my solution in a different, and hopefully easier way. But it's not working as expected. Hope someone with more experience on this can give me some advice. I'm sorry for this very long reply, but I think its necesary to undestand my question.

My USB-device board has three functional blocks available:
* HID sensors
* HID inputs
* CDC serial port

I want to separate all that functionality in two different configs:

config 1: HID sensors + HID inputs
config 2: HID sensors + CDC serial port

In my first solution I used two different config_descriptor arrays, each one defining a single configuration:

Code: Select all

uint8_t config_descriptor_01[] = {
        SIZE,
        USB_DESC_CONFIGURATION,
            USB_DESC_INTERFACE,
                USB_DESC_HID,
                    USB_DESC_ENDPOINT, // IN sensors
                    iUSB_DESC_ENDPOINT, // OUT sensors
            USB_DESC_INTERFACE,
                USB_DESC_HID,
                    USB_DESC_ENDPOINT, // IN buttons
};

uint8_t config_descriptor_02[] = {
        SIZE,
        USB_DESC_CONFIGURATION,
            USB_DESC_INTERFACE,
                USB_DESC_HID,
                    USB_DESC_ENDPOINT, // IN sensors
                    USB_DESC_ENDPOINT, // OUT sensors
            USB_DESC_INTERFACE,
                header functional,
                call management functional,
                ACM functional,
                union functional,
                    USB_DESC_ENDPOINT, // IRQ
            USB_DESC_INTERFACE,
                USB_DESC_ENDPOINT, // IN data
                USB_DESC_ENDPOINT, // OUT data
};


That solution requires returning a pointer to the proper configuration in the usb_get_descriptor_cb. config_descriptor_02 is still work in progress, but
hardcoding config_descriptor_01, all works as expected (I can read sensors and buttos from userspace).

In my second proposed solution I have supposed all previos stuff can be merged in a single array:

Code: Select all

uint8_t config_descriptor[] = {
    SIZE,
    USB_DESC_CONFIGURATION,
        USB_DESC_INTERFACE,
            USB_DESC_HID,
                USB_DESC_ENDPOINT, // IN sensors
                iUSB_DESC_ENDPOINT, // OUT sensors
        USB_DESC_INTERFACE,
            USB_DESC_HID,
                USB_DESC_ENDPOINT, // IN buttons
    USB_DESC_CONFIGURATION,
        USB_DESC_INTERFACE,
            USB_DESC_HID,
                USB_DESC_ENDPOINT, // IN sensors
                USB_DESC_ENDPOINT, // OUT sensors
        USB_DESC_INTERFACE,
            header functional,
            call management functional,
            ACM functional,
            union functional,
                USB_DESC_ENDPOINT, // IRQ
        USB_DESC_INTERFACE,
            USB_DESC_ENDPOINT, // IN data
            USB_DESC_ENDPOINT, // OUT data
};


That solution always returns the same configuration descriptor in the usb_get_descriptor_cb.

Now my question. Taking into account the second proposed solution, this commands is not working as expected:

Code: Select all

    # lsusb -v -d product:vendor


The tree of descriptors displayed is wrong. Both the first and second Configuration Descriptor displayed shows all the fields exactly the same:

Code: Select all

    Configuration Descriptor:
        bLength                 9
        bDescriptorType         2
        wTotalLength           66
        bNumInterfaces          2
        bConfigurationValue     1
        iConfiguration          0
        bmAttributes         0x80
          (Bus Powered)


But in config_descriptor array, they are different. Do you think this is a problem related with the second proposed solution? Or that second solution should work as expected and it's simply a bug in my source code?

aicastell
Posts: 12
Joined: Tue Sep 04, 2018 11:03 am
Has thanked: 6 times

Re: Issue developing a USB device with two config descriptors

Postby aicastell » Fri Sep 07, 2018 12:45 pm

Continuing with this issue, I have another question related. On the usb_event_cb callback (first callback defined on the USBConfig variable), when the USB_EVENT_CONFIGURED event is handled, the endpoints specified in the configuration must be enabled. But I my particular case, I have two configurations, and each one has a different set of endpoints. I don't have "dindex" available in this callback. How can I know what are the endpoints to be enabled in this case?

aicastell
Posts: 12
Joined: Tue Sep 04, 2018 11:03 am
Has thanked: 6 times

Re: Issue developing a USB device with two config descriptors

Postby aicastell » Mon Sep 10, 2018 2:50 pm

I come back with my initial issue, providing all internal details for a better understanding.

My USB-device is composed of three different functional blocks:

    * HID sensors
    * HID inputs
    * CDC ttyACM

The inputs and ttyACM pins are shared.

The purpose is developing a Chibios driver to separate all the functionality in two different USB configurations:

    * usb-config-1: HID sensors + HID inputs
    * usb-config-2: HID sensors + CDC serial port

I have developed this device descriptor:

Code: Select all

    static const uint8_t usb_device_descriptor_data[] = {
    USB_DESC_DEVICE(0x0110,       // bcdUSB
                    0x00,         // bDeviceClass
                    0x00,         // bDeviceSubClass
                    0x00,         // bDeviceProtocol
                    0x40,         // bMaxPacketSize
                    VENDOR_ID,
                    PRODUCT_ID,
                    DEVICE_VER,
                    1,            // iManufacturer
                    2,            // iProduct
                    3,            // iSerialNumber
                    2)            // bNumConfigurations
    };


And these two configuration descriptors:

Code: Select all

    static const uint8_t config_descriptor_data[] = {
    // Configuration Descriptor
    USB_DESC_CONFIGURATION(9+9+9+7+7+9+9+7, // wTotalLength
                         0x02,            // bNumInterfaces
                         0x01,            // bConfigurationValue
                         0x00,            // iConfiguration
                         0x80,            // bmAttributes
                         50),             // bMaxPower (100mA)
    // Interface Descriptor
    USB_DESC_INTERFACE    (0x00,          // bInterfaceNumber
                         0x00,          // bAlternateSetting
                         0x02,          // bNumEndpoints
                         0x03,          // bInterfaceClass
                         0x00,          // bInterfaceSubClass
                         0x00,          // bInterfaceProtocol
                         0),            // iInterface
    // HID Descriptor
    USB_DESC_HID          (0x110,       // bcdHID
                         0x00,          // bCountryCode
                         0x01,          // bNumDescriptors
                         0x22,          // bDescriptorType
                         sizeof(sensors_hid_report_descriptor_data)),
    // Endpoint Descriptor
    USB_DESC_ENDPOINT     (SENSORS_EP|USB_RTYPE_DIR_HOST2DEV,
                         0x03,          // bmAttributes
                         0x0040,        // wMaxPacketSize
                         0x0A),         // bInterval (10ms)
    // Endpoint Descriptor (7 bytes)
    USB_DESC_ENDPOINT     (SENSORS_EP|USB_RTYPE_DIR_DEV2HOST,
                         0x03,          // bmAttributes
                         0x0040,        // wMaxPacketSize
                         0x0A),         // bInterval (10ms)
    // Interface Descriptor (9 bytes)
    USB_DESC_INTERFACE    (0x01,        // bInterfaceNumber
                         0x00,          // bAlternateSetting
                         0x01,          // bNumEndpoints (1)
                         0x03,          // bInterfaceClass (HID class)
                         0x00,          // bInterfaceSubClass (None)
                         0x00,          // bInterfaceProtocol (None)
                         0),            // iInterface
    // HID Descriptor (9 bytes) (buttons)
    USB_DESC_HID          (0x0110,      // bcdHID (tipical value)
                         0x00,          // bCountryCode
                         0x01,          // bNumDescriptors
                         0x22,          // bDescriptorType
                         sizeof(buttons_hid_report_descriptor_data)),
    // Endpoint Descriptor (7 bytes)
    USB_DESC_ENDPOINT    (BUTTONS_EP|USB_RTYPE_DIR_DEV2HOST,
                        0x03,           // bmAttributes (interrupt)
                        0x0008,         // wMaxPacketSize
                        0x0A),          // bInterval (10ms)
    // Configuration Descriptor
    USB_DESC_CONFIGURATION(9+9+9+7+7+9+5+5+4+5+7+9+7+7, // wTotalLength
                         0x03,          // bNumInterfaces
                         0x02,          // bConfigurationValue
                         0x00,          // iConfiguration
                         0x80,          // bmAttributes
                         50),           // bMaxPower (100mA)
    // Interface Descriptor
    USB_DESC_INTERFACE    (0x00,        // bInterfaceNumber
                         0x00,          // bAlternateSetting
                         0x02,          // bNumEndpoints
                         0x03,          // bInterfaceClass (HID class)
                         0x00,          // bInterfaceSubClass (None)
                         0x00,          // bInterfaceProtocol (None)
                         0),            // iInterface
    // HID Descriptor
    USB_DESC_HID          (0x110,       // bcdHID
                         0x00,          // bCountryCode
                         0x01,          // bNumDescriptors
                         0x22,          // bDescriptorType
                         sizeof(sensors_hid_report_descriptor_data)),
    // Endpoint Descriptor
    USB_DESC_ENDPOINT     (SENSORS_EP|USB_RTYPE_DIR_HOST2DEV,
                         0x03,          // bmAttributes (interrupt)
                         0x0040,        // wMaxPacketSize
                         0x0A),         // bInterval (10ms)
    // Endpoint Descriptor
    USB_DESC_ENDPOINT     (SENSORS_EP|USB_RTYPE_DIR_DEV2HOST,
                         0x03,          // bmAttributes (interrupt)
                         0x0040,        // wMaxPacketSize
                         0x0A),         // bInterval (10ms)
    // Interface Descriptor
    USB_DESC_INTERFACE    (0x01,        // bInterfaceNumber
                         0x00,          // bAlternateSetting
                         0x01,          // bNumEndpoints
                         CDC_COMMUNICATION_INTERFACE_CLASS,
                         CDC_ABSTRACT_CONTROL_MODEL,
                         0x01,          // bInterfaceProtocol (AT cmds)
                         0),            // iInterface                   
    // Header Functional Descriptor
    USB_DESC_BYTE         (5),                // bFunctionLength
    USB_DESC_BYTE         (CDC_CS_INTERFACE), // bDescriptorType
    USB_DESC_BYTE         (0x00),             // bDescriptorSubtype
    USB_DESC_BCD          (0x0110),           // bcdCDC
    // ACM Functional Descriptor
    USB_DESC_BYTE         (4),                // bFunctionLength
    USB_DESC_BYTE         (CDC_CS_INTERFACE), // bDescriptorType
    USB_DESC_BYTE         (0x02),             // bDescriptorSubtype
    USB_DESC_BYTE         (0x02),             // bmCapabilities (D1)
    // Union Functional Descriptor
    USB_DESC_BYTE         (5),                // bFunctionLength
    USB_DESC_BYTE         (CDC_CS_INTERFACE), // bDescriptorType
    USB_DESC_BYTE         (0x06),             // bDescriptorSubtype
    USB_DESC_BYTE         (0x01),             // bMasterInterface
    USB_DESC_BYTE         (0x02),             // bSlaveInterface
    // Call Management Functional Descriptor
    USB_DESC_BYTE         (5),                // bFunctionLength
    USB_DESC_BYTE         (CDC_CS_INTERFACE), // bDescriptorType
    USB_DESC_BYTE         (0x01),             // bDescriptorSubtype
    USB_DESC_BYTE         (0x03),             // bmCapabilities
    USB_DESC_BYTE         (0x01),             // bDataInterface
    // Notification Endpoint Descriptor
    USB_DESC_ENDPOINT     (CDC_NOTIFICATION_EP|USB_RTYPE_DIR_DEV2HOST,
                           0x03,          // bmAttributes
                           0x0040,        // wMaxPacketSize
                           0xFF),         // bInterval (10ms)
    // Interface Descriptor
    USB_DESC_INTERFACE    (0x02,          // bInterfaceNumber
                           0x00,          // bAlternateSetting
                           0x02,          // bNumEndpoints
                           CDC_DATA_INTERFACE_CLASS,
                           0x00,          // bInterfaceSubClass
                           0x00,          // bInterfaceProtocol
                           0),            // iInterface
    // Data OUT Endpoint Descriptor
    USB_DESC_ENDPOINT     (CDC_DATA_EP|USB_RTYPE_DIR_HOST2DEV,
                           0x02,          // bmAttributes (Bulk)
                           0x0200,        // wMaxPacketSize
                           0x00),         // bInterval
    // Data IN Endpoint Descriptor
    USB_DESC_ENDPOINT     (CDC_DATA_EP|USB_RTYPE_DIR_DEV2HOST,
                           0x02,          // bmAttributes (Bulk)
                           0x0200,        // wMaxPacketSize
                           0x01)          // bInterval
    };


When I plug my device, this command displays a wrong tree of descriptors:

Code: Select all

    # lsusb -v -d product:vendor
    Bus 001 Device 047: ID 0179:0002 
    Couldn't open device, some information will be missing
    Device Descriptor:
      bLength                18
      bDescriptorType         1
      bcdUSB               1.10
      bDeviceClass            0 (Defined at Interface level)
      bDeviceSubClass         0
      bDeviceProtocol         0
      bMaxPacketSize0        64
      idVendor           0x0179
      idProduct          0x0002
      bcdDevice            2.00
      iManufacturer           1
      iProduct                2
      iSerial                 3
      bNumConfigurations      2
      Configuration Descriptor:
        bLength                 9
        bDescriptorType         2
        wTotalLength           66
        bNumInterfaces          2
        bConfigurationValue     1
        iConfiguration          0
        bmAttributes         0x80
          (Bus Powered)
        MaxPower              100mA
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        0
          bAlternateSetting       0
          bNumEndpoints           2
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength     568
             Report Descriptors:
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x01  EP 1 OUT
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0040  1x 64 bytes
            bInterval              10
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x81  EP 1 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0040  1x 64 bytes
            bInterval              10
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        1
          bAlternateSetting       0
          bNumEndpoints           1
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength      23
             Report Descriptors:
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x82  EP 2 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0008  1x 8 bytes
            bInterval              10
      Configuration Descriptor:
        bLength                 9
        bDescriptorType         2
        wTotalLength           66
        bNumInterfaces          2
        bConfigurationValue     1
        iConfiguration          0
        bmAttributes         0x80
          (Bus Powered)
        MaxPower              100mA
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        0
          bAlternateSetting       0
          bNumEndpoints           2
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength     568
             Report Descriptors:
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x01  EP 1 OUT
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0040  1x 64 bytes
            bInterval              10
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x81  EP 1 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0040  1x 64 bytes
            bInterval              10
        Interface Descriptor:
          bLength                 9
          bDescriptorType         4
          bInterfaceNumber        1
          bAlternateSetting       0
          bNumEndpoints           1
          bInterfaceClass         3 Human Interface Device
          bInterfaceSubClass      0 No Subclass
          bInterfaceProtocol      0 None
          iInterface              0
            HID Device Descriptor:
              bLength                 9
              bDescriptorType        33
              bcdHID               1.10
              bCountryCode            0 Not supported
              bNumDescriptors         1
              bDescriptorType        34 Report
              wDescriptorLength      23
             Report Descriptors:
               ** UNAVAILABLE **
          Endpoint Descriptor:
            bLength                 7
            bDescriptorType         5
            bEndpointAddress     0x82  EP 2 IN
            bmAttributes            3
              Transfer Type            Interrupt
              Synch Type               None
              Usage Type               Data
            wMaxPacketSize     0x0008  1x 8 bytes
            bInterval              10


This is wrong because the second Configuration Descriptor shows the same values as the first Configuration Descriptor, but they are different as you can see in the source code (see bConfigurationValue and wTotalLength as an example).

What is wrong with that?


Return to “ChibiOS/HAL”

Who is online

Users browsing this forum: No registered users and 6 guests