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.

Tivaware 2.1.4.178 USBLIB Descriptor Problem

I've spent about a week trying to get a USB HID device registered and properly enumerated on a TM4C129X dev board, but various test tools

on the Windows host just choke and report an invalid descriptor. If anyone could kindly look over my descriptors and see if they notice anything I'd be very grateful.

I've tried so many variations of ReportDescriptor and configuration my head's spinning.

I'm using TivaWare release C 2.1.4.178

Thanks.


/* USB Language descriptor */
STATIC const uint8_t mLangDescriptor[] =
{
    4,
    USB_DTYPE_STRING,
    USBShort( USB_LANG_EN_UK )
};

/* USB Manufacturer string */
STATIC const uint8_t mManufacturerString[] =
{
    (27 + 1) * 2,
    USB_DTYPE_STRING,
    'M', 0, 'a', 0, 'n', 0, 'u', 0, 'f', 0, 'a', 0, 'c', 0, 't', 0, 'u', 0,
    'r', 0, 'e', 0, 'r', 0, ' ', 0, 'P', 0, 'l', 0, 'a', 0, 'c', 0, 'e', 0,
    'h', 0, 'o', 0, 'l', 0, 'd', 0, 'e', 0, 'r', 0, ' ', 0, 'X', 0, '.', 0
};

// Device Product String
STATIC const uint8_t mProductString[] =
{
    (16 + 1) * 2,
    USB_DTYPE_STRING,
    'P', 0, 'r', 0, 'o', 0, 'd', 0, 'u', 0, 'c', 0, 't', 0, ' ', 0,
    'g', 0, 'o', 0, 'e', 0, 's', 0, 'h', 0, 'e', 0, 'r', 0, 'e', 0
};

// Device Serial Number.
STATIC uint8_t mSerialNumberString[] =
{
    (8 + 1) * 2,
    USB_DTYPE_STRING,
    '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0
};

/* Device Interface name. This specifies the interface class as being HID
*/
STATIC const uint8_t mHIDInterfaceString[] =
{
    (7 + 1) * 2,
    USB_DTYPE_STRING,
    'U', 0, 'S', 0, 'B', 0, ' ', 0, 'H', 0, 'I', 0, 'D', 0
};

// Device Configuration string. This simply names the configuration descriptor
STATIC const uint8_t mConfigString[] =
{
    (20 + 1) * 2,
    USB_DTYPE_STRING,
    'T', 0, 'e', 0, 's', 0, 't', 0, 'e', 0, 'r', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0,
    'f', 0, 'i', 0, 'g', 0, 'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
};

/* USB descriptor string table */
STATIC const uint8_t * const mStringDescriptors[] =
{
    mLangDescriptor,            // Language descriptor,
    mManufacturerString,        // Manufacturer name string (language 1),
    mProductString,             // product name string (language 1),
    mSerialNumberString,        // Serial number string (language 1),
    mHIDInterfaceString,        // HID Interface description string (language 1),
    mConfigString               // Configuration description string (language 1),
};

#define NUM_STRING_DESCRIPTORS (sizeof(mStringDescriptors) / sizeof(uint8_t *))





/*
 * This describes the device input, output and feature reports providing
 * usage information for each one as well as the size of the data itself
 */

STATIC const uint8_t mReportDescriptor[]=
{
    UsagePage( USB_HID_GENERIC_DESKTOP ),
    Usage( USB_HID_USAGE_SYSTEM_CONTROL ),
    Collection(USB_HID_APPLICATION),
        UsagePage( USB_HID_GENERIC_DESKTOP ),
        Usage( USB_HID_USAGE_SYSTEM_CONTROL ),
        LogicalMinimum(0),
        LogicalMaximum(255),
        UsageMinimum(0),
        UsageMaximum( PACKET_SIZE ),

    // Input report - used for sending messages from the device to the host
        ReportID(1),
        ReportSize(8),
        ReportCount(PAYLOAD_BYTES),
        Input( USB_HID_INPUT_DATA  | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS ),

    // Output report - used for receiving messages from the host to the device
        ReportID(2),
        ReportSize(8),
        ReportCount(PAYLOAD_BYTES),
        Output( USB_HID_OUTPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS ),

    EndCollection,
};












/* USB input report polling rates, one entry for each INPUT report. Generally for the MPS9001 we do not want polling at all
 * so the times are simply set to 0.
 */
STATIC tHIDReportIdle mReportIdle[ 1] =
{
    { 0, 1, 0, 0 }     // Report 1 is not polled (0mS timeout)
};


/////////////////////////////////////////////////////////////////////////





// Configuration descriptor
STATIC const uint8_t mConfigDescriptor[] =
{
    9,                              /* Size of the configuration descriptor.       */
    USB_DTYPE_CONFIGURATION,        /* Type of this descriptor.                    */
    USBShort(9),                    /* The total size of this full structure (patched by library)  */
    1,                              /* Number of interfaces in this configuration  */
    1,                              /* The unique value/ID for this configuration.    */
    5,                              /* The string identifier that describes this configuration.    */
    USB_CONF_ATTR_SELF_PWR,         /* Bus Powered, Self Powered, remote wake up.  */
    POWER_CONSUMPTION_MA   /* The maximum power in 2mA increments.        */
};


// The Interface descriptor
STATIC const uint8_t mInterfaceDescriptor[] =
{
    9,                          /* Size of the interface descriptor.           */
    USB_DTYPE_INTERFACE,        /* Type of this descriptor.                    */
    0,                          /* The index for this interface.               */
    0,                          /* The alternate setting for this interface.   */
    1,                          /* The number of endpoints                     */
    USB_CLASS_HID,              /* The interface class                         */
    USB_HID_SCLASS_NONE,        /* The interface sub-class.                    */
    USB_HID_PROTOCOL_NONE,      /* The interface protocol for the sub-class    */
    4,                          /* The string index for this interface.       */
};


// The HID descriptor itself
STATIC const tHIDDescriptor mHIDDescriptor[] =
{
    9,                                                  /* bLength                         */
    USB_HID_DTYPE_HID,                                  /* bDescriptorType                 */
    0x0111,                                             /* bcdHID (version 1.11 compliant) */
    0,                                                  /* bCountryCode (not localized)    */
    1,                                                  /* # HID class descriptors to follow                 */
    {
         {
              USB_HID_DTYPE_REPORT,                     /* Report descriptor               */
              sizeof( mReportDescriptor )               /* Size of report descriptor       */
         }
    }
};


// The INTERRUPT IN endpoint descriptor
STATIC const uint8_t mInEndpointDescriptor[] =
{
    7,                                               /* The size of the endpoint descriptor.       */
    USB_DTYPE_ENDPOINT,                              /* Descriptor type is an endpoint.            */
    USB_EP_DESC_IN | USBEPToIndex(USB_EP_1),         /*                                            */
    USB_EP_ATTR_INT,                                 /* Endpoint is an interrupt endpoint.         */
    USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)),    /* The maximum packet size.                   */
    16,                                              /* The polling interval for this endpoint.    */
};



STATIC const tConfigSection mHIDSection =
{
    sizeof( mHIDDescriptor ),
    (const uint8_t *) &mHIDDescriptor
};

STATIC const tConfigSection mInEndpointSection =
{
    sizeof( mInEndpointDescriptor ),
    mInEndpointDescriptor
};

STATIC const tConfigSection mConfigSection =
{
    sizeof( mConfigDescriptor ),
    mConfigDescriptor
};

STATIC const tConfigSection mInterfaceSection =
{
    sizeof( mInterfaceDescriptor ),
    mInterfaceDescriptor
};




STATIC const uint8_t * const mClassDescriptors[] =
{
    mReportDescriptor
};



/* Collation of the config sections */
STATIC const tConfigSection *mHIDSections[] =
{
    &mConfigSection,
    &mInterfaceSection,
    &mHIDSection,
    &mInEndpointSection,
};

#define NUM_HID_SECTIONS (sizeof( mHIDSections ) / sizeof( tConfigSection* ))



// Point to all the descriptor sections
STATIC const tConfigHeader mHIDConfigHeader =
{
    NUM_HID_SECTIONS,
    mHIDSections
};

// Root data structure to all our descriptors
STATIC tConfigHeader const * const mHIDConfigDescriptors[] =
{
    &mHIDConfigHeader
};








/* The complete specification for the USB HID class device
This variable definition collates everything in the above definitions into
a single structure for the purpose of intialising the Texas Instruments
USB Library to configure the USB chip into a HID class device mode.
*/
STATIC tUSBDHIDDevice mHIDDeviceSpecification =
{
    //! The vendor ID that this device is to present in the device descriptor.
    //
    USB_VID_VENDOR_ID,

    //! The product ID that this device is to present in the device descriptor.
    //
    USB_PID_PRODUCT_ID,

    //! The maximum power consumption of the device, expressed in milliamps.
    //
    POWER_CONSUMPTION_MA,

    //! Indicates whether the device is self- or bus-powered and whether or not
    //! it supports remote wakeup.  Valid values are USB_CONF_ATTR_SELF_PWR or
    //! USB_CONF_ATTR_BUS_PWR, optionally ORed with USB_CONF_ATTR_RWAKE.
    //
    USB_CONF_ATTR_SELF_PWR,

    //! The interface subclass to publish to the server for this HID device.
    //
    USB_HID_SCLASS_NONE,

    //! The interface protocol to publish to the server for this HID device.
    //
    USB_HID_PROTOCOL_NONE,

    //! The number of >INPUT< reports that this device supports.  This field
    //! must equal the number of reports published in the HID class descriptors
    //! for the device and also the number of entries in the array whose first
    //! element is pointed to by field pi16ReportIdle below.
    //
    1,

    //
    //! A pointer to the first element in an array of structures used to track
    //! idle time for each Input report.  When USBDHIDInit is called, the
    //! ui8Duration4mS and ui8ReportID fields of each of these array members
    //! should be initialized to indicate the default idle timeout for each
    //! input report.  This array must be in RAM since the HID device class
    //! driver will update values in it in response to requests from the host
    //! and to track elapsed time.  The number of elements in the array must
    //! match the number supplied in the ui8NumInputReports field above.
    //
    mReportIdle,

    //! A pointer to the callback function which will be called to notify
    //! the application of general events, events related to report transfers
    //! on endpoint zero and events related to reception of Output and Feature
    //! reports via the (optional) interrupt OUT endpoint.
    //
    mUSBReceiveCallbackHandler,

    //! A client-supplied pointer which will be sent as the first
    //! parameter in all calls made to the receive channel callback,
    //! pfnRxCallback.
    //
    0,

    //! A pointer to the callback function which will be called to notify
    //! the application of events related to transmission of Input reports
    //! via the interrupt IN endpoint.
    //
    mUSBTransmitCallbackHandler,

    //! A client-supplied pointer which will be sent as the first
    //! parameter in all calls made to the transmit channel callback,
    //! pfnTxCallback.
    //
    0,

    //! If set to true, this field indicates that the device should use a
    //! dedicated interrupt OUT endpoint to receive reports from the host.  In
    //! this case, reports from the host are passed to the application via the
    //! receive callback using USB_EVENT_RX_AVAILABLE events.  If false,
    //! reports from the host are received via endpoint zero and passed to the
    //! application via USBD_HID_EVENT_REPORT_SENT events.
    //
    false,

    //! The HID descriptor that the device is to publish (following the
    //! standard interface descriptor and prior to the endpoint descriptors for
    //! the interface).
    //
    mHIDDescriptor,

    //! The HID class descriptors offered by the device are defined in an
    //! array of byte pointers and this field points to that array.  The
    //! order and number of elements in the array must match the associated
    //! information provided in the HID descriptor in field by
    //! pi16HIDDescriptor.
    //
    mClassDescriptors,

    //! A pointer to the string descriptor array for this device.  This array
    //! must contain the following string descriptor pointers in this order:
    //! Language descriptor, Manufacturer string, Product string, Serial number
    //! string, HID Interface description string, Configuration string, and
    //! (optionally) First HID device-specific string. Then (optionally)
    //! Second HID device-specific string
    //!
    //! If supporting more than 1 language, the descriptor block (except for
    //! string descriptor 0) must be repeated for each language defined in the
    //! language descriptor.
    //!
    //! The number of HID device-specific strings is dependent upon the content
    //! of the report descriptor passed to the interface and is, thus,
    //! application controlled.
    //
    mStringDescriptors,

    //! The number of descriptors provided in the ppStringDescriptors
    //! array.  This must be 1 + ((5 + (num HID strings)) * (num languages)).
    //
    NUM_STRING_DESCRIPTORS,
    
    // ! The configuration descriptors for this HID device.
    //
    mHIDConfigDescriptors,
    
    // Default initialise the private/reserved memory to zero
    { 0 }
};


  • Hello Tony,

    Let's take a brief step back for a moment, have you been able to get TivaWare examples to enumerate correctly?

    If so, what are you modifying from TivaWare examples?

    What type of HID Device are you trying to setup?

    Lastly, what version of Windows are you on?
  • Hello Tony,

    Still awaiting feedback on my prior queries so I can try and help you with this issue.
  • Very sorry Ralph. I was out of the office two days last week.

    It seems the project environment I was working on had been configured with CCS 7.x and although TivaWare 2.1.4.178 was also installed, the CCS project was picking up driverlib & usblib from a TivaWare 2.0.1.11577 install. So basically the dev environment was a mess. Friday and today I have been cleaning everything up and bringing the installed packages up to date. So hopefully I'll have more info tomorrow. I'd appreciate it if you could leave this thread open a couple of days so I can report back.

    Regards,
    Tony.
  • Hello Tony,

    Sure, no problem!