This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problems with multiple HID reports, ReportID



I've followed the steps in the 'USB Library User's Guide' to implement a custom HID device. First I implemented a device with only one report and it worked fine. Now I want to add a second report and tried to add a report ID to each report descriptor. As soon as I do this, Windows shows a Error Code 10 for the device and it doesn't work anymore.

Here is the code for the report descriptors:

/**
 * The LED report descriptor
 */
static const unsigned char g_pucCustomHidReportDescriptorLEDs[]=
{
        ReportID(1),
        UsagePage(0x08), // LED
        Usage(0x4E),
        Collection(USB_HID_APPLICATION),

        LogicalMinimum(0),
        LogicalMaximum(0xFFFF),
        Usage(0x4E),

        ReportSize(8),
        ReportCount(6),
        Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS),

        EndCollection,
};

/**
 * The buttons report descriptor
 */
static const unsigned char g_pucCustomHidReportDescriptorButtons[]=
{
        ReportID(2),
        UsagePage(USB_HID_CONSUMER_DEVICE),
        Usage(USB_HID_USAGE_CONSUMER_CONTROL),
        Collection(USB_HID_APPLICATION),

        LogicalMinimum(0),
        LogicalMaximum(1),
        Usage(0x36), // function buttons

        ReportSize(1), // 1 bit per button
        ReportCount(2), // 2 buttons
        Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // variable, absolute data

        ReportCount(6),
        Input(USB_HID_INPUT_CONSTANT | USB_HID_INPUT_ARRAY | USB_HID_INPUT_ABS),

        EndCollection,
};

Both descriptors work fine when used alone and without the ReportID() macro but as soon as I add this macro I get the error described above.

As far as I know the report ID field is needed to support multiple reports. When I remove the report ID field the device is displayed as functional in the Device Manager but only the first descriptor works.

I'm using the Stellaris Launchpad with Code Composer Studio.

How to fix this error?

  • Nobody got an idea?

  • Not sure if I can help. How are g_pucCustomHidReportDescriptorLEDs and g_pucCustomHidReportDescriptorButtons used? They should be referenced in the class descriptor array and the HID descriptor list. Did you remember to bump up bNumDescriptors in the HID Descriptor?

  • Here the HID descesciptor list:

    static const tHIDDescriptor g_sCustomHIDDescriptor =
    {
            12, // bLength
            USB_HID_DTYPE_HID, // bDescriptorType
            0x111, // bcdHID (version 1.11 compliant)
            0, // bCountryCode (not localized)
            2, // bNumDescriptors
            {
                    {
                    USB_HID_DTYPE_REPORT, // Report descriptor
                    sizeof(g_pucCustomHidReportDescriptorLEDs), // Size of report descriptor
                    },
                    {
                    USB_HID_DTYPE_REPORT, // Report descriptor
                    sizeof(g_pucCustomHidReportDescriptorButtons) // Size of report descriptor
                    }
            }
    };

    I get a 'excess initializers are ignored' warning for the second entry in the array, so I've changed

    tHIDClassDescriptorInfo sClassDescriptor[1];

    in 'usbhid.h' to

    tHIDClassDescriptorInfo sClassDescriptor[2];

    and recompiled the usblib, but that didn't help.

    The complete code is in the attached archive.

  • Your code looks correct functionally correct. Descriptors look all good. Sizes look right. Perhaps defining more than one TYPE_REPORT descriptors is not allowed in the USB HID spec. I admit that I never have defined more than one report using separate report descriptors. I have defined more than one report within one report descriptor that has one user page that has one collection. That's extent of my knowledge. Hopefully a USB Guru that's well versed in StellarisWare can comment.

  • Here's my guess at the two descriptors merged into one:

    static const unsigned char g_pucCustomHidReportDescriptor[]=
    {
      UsagePage(USB_HID_CONSUMER_DEVICE),
      Usage(USB_HID_USAGE_CONSUMER_CONTROL),
      Collection(USB_HID_APPLICATION),

      UsagePage(0x08), // LED
      Usage(0xFE), // random value
      ReportID(1),
      LogicalMinimum(0),
      LogicalMaximum(0xFFFF),

      // 6 byte (2 byte per LED)
      ReportSize(8),
      ReportCount(6),
      Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS),

      UsagePage(USB_HID_CONSUMER_DEVICE),
      Usage(0x36), // function buttons
      ReportID(2),
      LogicalMinimum(0),
      LogicalMaximum(1),

      ReportSize(1), // 1 bit per button
      ReportCount(2), // 2 buttons
      Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // variable, absolute data

      // pad remaining 6 bit
      ReportCount(6),
      Input(USB_HID_INPUT_CONSTANT | USB_HID_INPUT_ARRAY | USB_HID_INPUT_ABS),

      EndCollection,
    };

    Note that Usage() and UsagePage() take 1 byte values.