TMS320F28388D: Binding to WinUSB

Part Number: TMS320F28388D

Hi,

  I am working on developing USB communication through CM core in F28388D. I tested and confirmed the example 'USB Generic Bulk Device (usb_dev_bulk) - CM'. For this example, I have to install the driver 'usb_dev_bulk.inf'. But, I would like to automatically bind to WinUSB.sys without install the driver.

  I tried to use BOS Descriptor and MS OS 2.0 Descriptor as follows but I failed. Let me know if you have any solutions or suggetions.

uint8_t g_pBOSDescriptor[] = {

    /* BOS Descriptor Header */
    0x05,               /* bLength */
    0x0F,               /* bDescriptorType = BOS */
    0x21, 0x00,         /* wTotalLength = 33 bytes */
    0x01,               /* bNumDeviceCaps = 1 */

    /* Microsoft OS 2.0 Platform Capability Descriptor */
    0x1C,               /* bLength = 28 bytes */
    0x10,               /* bDescriptorType = DEVICE CAPABILITY */
    0x05,               /* bDevCapabilityType = PLATFORM */
    0x00,               /* bReserved */

    /* Platform Capability UUID (MS OS 2.0) D8DD60DF-4589-4CC7-9CD2-659D9E648A9F */
    0xDF, 0x60, 0xDD, 0xD8,
    0x89, 0x45, 0xC7, 0x4C,
    0x9C, 0xD2, 0x65, 0x9D,
    0x9E, 0x64, 0x8A, 0x9F,

    /* Windows version (8.1+) */
    0x00, 0x00, 0x03, 0x06, /* dwWindowsVersion = 0x06030000 */

    /* wMSOSDescriptorSetTotalLength (size of MS OS 2.0 descriptor set) */
    0x2E, 0x00,             /* 46(=0x2E) bytes */

    /* bMS_VendorCode (used in vendor request to fetch MS OS 2.0 set) */
    0x01,                   /* Vendor code */

    /* bAltEnumCode */
    0x00

};

 

uint8_t g_pMSOS20DescriptorSet[] = {

    // MS OS 2.0 Descriptor Set Header (10 bytes)
    0x0A, 0x00,             // wLength = 10 bytes
    0x00, 0x00,             // MSOS20_SET_HEADER_DESCRIPTOR (0x0000)
    0x00, 0x00, 0x03, 0x06, // dwWindowsVersion = Windows 8.1 / 10+ (0x06030000)
    0x2E, 0x00,             // wTotalLength = 46 bytes (0x002E)

    // MS OS 2.0 Configuration Subset Header (8 bytes)
    0x08, 0x00,             // wLength = 8 bytes
    0x01, 0x00,             // MSOS20_SUBSET_HEADER_CONFIGURATION (0x0001)
    0x01,                   // bConfigurationValue = 1
    0x00,                   // bReserved = 0
    0x24, 0x00,             // wTotalLength = 36 bytes (0x0024)

    // MS OS 2.0 Function Subset Header (8 bytes)
    0x08, 0x00,             // wLength = 8 bytes
    0x02, 0x00,             // MSOS20_SUBSET_HEADER_FUNCTION (0x0002)
    0x00,                   // bFirstInterface = 0
    0x00,                   // bReserved = 0
    0x1C, 0x00,             // wSubsetLength = 28 bytes (0x001C)

    // MS OS 2.0 Compatible ID Descriptor (20 bytes)
    0x14, 0x00,             // wLength = 20 bytes
    0x03, 0x00,             // MSOS20_FEATURE_COMPATIBLE_ID (0x0003)
    'W',  'I',  'N',  'U',  'S',  'B',  0x00, 0x00, // Compatible ID: "WINUSB\0\0"
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Sub-Compatible ID: Null
};

 

Jeong

  • Hi,

      I am working with Don. He wants to add more details.

    Here are some additional details on the issue we are having:

    We are debugging an issue with MS OS 2.0 descriptor retrieval on the TMS320F28388D device using the ROM USB Device Controller Driver (DCD). To understand what Windows is requesting during enumeration, we added instrumentation to USBDReadAndDispatchRequest() in usbdenum.c and captured every SETUP packet sent by Windows. Below are the first several requests in human‑readable form:

    [1]  GET_DESCRIPTOR(Device) — wValue=0x0100, wLength=64
    [2]  SET_ADDRESS — new USB address = 31
    [3]  GET_DESCRIPTOR(Device) — wValue=0x0100, wLength=18
    [4]  GET_DESCRIPTOR(Configuration) — wValue=0x0200, wLength=255
    [5]  GET_DESCRIPTOR(BOS) — wValue=0x0F00, wLength=255
    [6]  MS OS 2.0 Descriptor Set Request — bRequest=0x01, wIndex=7, wLength=46
    [7]  MS OS 2.0 Descriptor Set Request — bRequest=0x01, wIndex=7, wLength=46 (retry #1)

    Requests [1]–[5] show normal enumeration, including a successful BOS descriptor fetch. USBView confirms that Windows received the BOS descriptor correctly, including the MS OS 2.0 Platform Capability UUID, dwWindowsVersion, the descriptor set length (46 bytes), and the vendor code (0x01).

    Request [6] shows Windows properly requesting the MS OS 2.0 descriptor set using:
      bmRequestType = 0xC0 (IN | Vendor | Device)
      bRequest      = 0x01 (vendor code from BOS)
      wValue        = 0x0000
      wIndex        = 0x0007 (MS OS 2.0 descriptor set)
      wLength       = 46 (exact size of our descriptor set)

    Request [7] is an immediate retry, indicating Windows did not accept the response.

    Our handler for this request is:

    static void BulkRequestHandler(void *pvInstance, tUSBRequest *pUSBRequest)
    {
        uint8_t  bm      = pUSBRequest->bmRequestType;
        uint8_t  br      = pUSBRequest->bRequest;
        uint16_t wValue  = pUSBRequest->wValue;
        uint16_t wIndex  = pUSBRequest->wIndex;
        uint16_t wLength = pUSBRequest->wLength;

        if ((bm == (USB_RTYPE_DIR_IN | USB_RTYPE_VENDOR | USB_RTYPE_DEVICE)) &&
            (br == 0x01) &&
            (wValue == 0x0000) &&
            (wIndex == 0x0007))
        {
            uint16_t usLength = wLength;
            if (usLength > sizeof(g_pMSOS20DescriptorSet))
                usLength = sizeof(g_pMSOS20DescriptorSet);

            USBDCDSendDataEP0(0, (uint8_t *)g_pMSOS20DescriptorSet, usLength);
            return;
        }
    }

    We verified that the pointer passed to USBDCDSendDataEP0() is correct and that the size passed in is 46 bytes. The function in the ROM DCD is:

    void USBDCDSendDataEP0(uint32_t ui32Index, uint8_t *pui8Data, uint32_t ui32Size)
    {
        g_psDCDInst[0].pui8EP0Data = pui8Data;
        g_psDCDInst[0].ui32EP0DataRemain = ui32Size;
        g_psDCDInst[0].ui32OUTDataSize = ui32Size;
        USBDEP0StateTx(0);
    }

    Despite this, Windows retries the MS OS 2.0 request repeatedly. Between retries, Windows re‑enumerates the device. Here are additional requests later in the capture:

    [13] MS OS 2.0 Descriptor Set Request — retry #2
    [14] MS OS 2.0 Descriptor Set Request — retry #3
    [20] MS OS 2.0 Descriptor Set Request — retry #4
    [21] MS OS 2.0 Descriptor Set Request — retry #5
    [27] MS OS 2.0 Descriptor Set Request — retry #6

    Between these retries, Windows again issues GET_DESCRIPTOR(Device), SET_ADDRESS, GET_DESCRIPTOR(Configuration), GET_DESCRIPTOR(BOS), etc., indicating repeated attempts to restart enumeration.

    Ultimately, Windows aborts and the SET_CONFIGURATION message is never sent and enumeration is not completed.


    Questions:

    1. Does the MS OS 2.0 descriptor set (g_pMSOS20DescriptorSet) appear malformed or incorrect in any way?
    2. Is the use of USBDCDSendDataEP0() appropriate for returning the MS OS 2.0 descriptor set?
    3. Is there any known issue or limitation with USBDEP0StateTx() when returning vendor-specific descriptors?
    4. Based on the repeated retries, what might cause Windows to reject the descriptor response?

    Any guidance on why Windows is not accepting the MS OS 2.0 descriptor set would be appreciated.

    Thanks,

    Jeong

  • Hi,

      Don wants to correct as the following:

    "Correction, we are not using the ROM USB DCD.  We are using the software version."

    Thanks,

    Jeong

  • Hi TI,

      Let me know if you have any solutions or suggestions.

    Thanks,

    Jeong

  • Hi TI,

    I hope you are having a productive week.

    I am still following up on my previous message. Do you have any updates you can share at this time?

    Best regards,

    Jeong

  • Hi,

    Apiologies for delay in responding to this thread. 

    Few things that you can check is 

    1. Pls check if the execution after the BulkRequestHandler enters USBDReadAndDispatchRequest. Since the custom handler has a void return and doesn't halt the driver, execution may be falling into the stack's unhandled fallback route, causing the driver to forcefully run USBDCDStallEP0().  

    2. Before writing to the EP0 FIFO via USBDCDSendDataEP0, the host expects the device to acknowledge that the control request was valid. Standard descriptors do this implicitly.
    Try adding 
    USBDevEndpointDataAck(USB0_BASE, USB_EP_0, true); before calling USBDCDSendDataEP0.

    Best Regards

    Siddharth

  • Hi Siddharth,

      Thank you for your reply.

    I tested your proposal and I wrote the results as follows.

     

     The proposals:

    1. Pls check if the execution after the BulkRequestHandler enters USBDReadAndDispatchRequest. Since the custom handler has a void return and doesn't halt the driver, execution may be falling into the stack's unhandled fallback route, causing the driver to forcefully run USBDCDStallEP0().  

    ==> I confirmed that USBReadAndDispatchRequest was hit after BulkRequestHandler.

    2. Before writing to the EP0 FIFO via USBDCDSendDataEP0, the host expects the device to acknowledge that the control request was valid. Standard descriptors do this implicitly.
    Try adding USBDevEndpointDataAck(USB0_BASE, USB_EP_0, true); before calling USBDCDSendDataEP0.

    ==> I changed the input parameter from ‘false’ to ‘true’ as your proposal.

    Before

    After

    // STEP 1: ACK the SETUP packet
    USBDevEndpointDataAck(USB_BASE, USB_EP_0, false);

    // STEP 2: Send the descriptor data
    USBDCDSendDataEP0(0, (uint8_t *)g_pWCIDDescriptor, usLength);

    // STEP 1: ACK the SETUP packet
    // USBDevEndpointDataAck(USB_BASE, USB_EP_0, false);
    USBDevEndpointDataAck(USB_BASE, USB_EP_0, true);

    // STEP 2: Send the descriptor data
    USBDCDSendDataEP0(0, (uint8_t *)g_pWCIDDescriptor, usLength);

     

    WinUSB is still not installed as the following.

    I copied USB Viewer results as the following.


    [Port5]

    Is Port User Connectable:         yes

    Is Port Debug Capable:            no

    Companion Port Number:            0

    Companion Hub Symbolic Link Name:

    Protocols Supported:

    USB 1.1:                         yes

    USB 2.0:                         yes

    USB 3.0:                         no

     

     

           ---===>Device Information<===---

    String Descriptor for index 2 not available while device is in low power state.

     

    ConnectionStatus:                 

    Current Config Value:              0x00  -> Device Bus Speed: Full (is not SuperSpeed or higher capable)

    Device Address:                    0x2F

    Open Pipes:                           0

    *!*ERROR:  No open pipes!

     

              ===>Device Descriptor<===

    bLength:                           0x12

    bDescriptorType:                   0x01

    bcdUSB:                          0x0210

    bDeviceClass:                      0xFF  -> This is a Vendor Specific Device

    bDeviceSubClass:                   0x00

    bDeviceProtocol:                   0x00

    bMaxPacketSize0:                   0x40 = (64) Bytes

    idVendor:                        0x1CBE = Texas Instruments - Stellaris

    idProduct:                       0x0006

    bcdDevice:                       0x0116

    iManufacturer:                     0x01

    String Descriptor for index 1 not available while device is in low power state.

    iProduct:                          0x02

    String Descriptor for index 2 not available while device is in low power state.

    iSerialNumber:                     0x00

    bNumConfigurations:                0x01

     

           ---===>Full Configuration Descriptor<===---

     

              ===>Configuration Descriptor<===

    bLength:                           0x09

    bDescriptorType:                   0x02

    wTotalLength:                    0x0020  -> Validated

    bNumInterfaces:                    0x01

    bConfigurationValue:               0x01

    iConfiguration:                    0x05

    String Descriptor for index 5 not available while device is in low power state.

    bmAttributes:                      0x80  -> Bus Powered

    MaxPower:                          0xFA = 500 mA

     

              ===>Interface Descriptor<===

    bLength:                           0x09

    bDescriptorType:                   0x04

    bInterfaceNumber:                  0x00

    bAlternateSetting:                 0x00

    bNumEndpoints:                     0x02

    bInterfaceClass:                   0xFF  -> Interface Class Unknown to USBView

    bInterfaceSubClass:                0x00

    bInterfaceProtocol:                0x00

    iInterface:                        0x04

    String Descriptor for index 4 not available while device is in low power state.

     

              ===>Endpoint Descriptor<===

    bLength:                           0x07

    bDescriptorType:                   0x05

    bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1

    bmAttributes:                      0x02  -> Bulk Transfer Type

    wMaxPacketSize:                  0x0040 = 0x40 bytes

    bInterval:                         0x00

     

              ===>Endpoint Descriptor<===

    bLength:                           0x07

    bDescriptorType:                   0x05

    bEndpointAddress:                  0x01  -> Direction: OUT - EndpointID: 1

    bmAttributes:                      0x02  -> Bulk Transfer Type

    wMaxPacketSize:                  0x0040 = 0x40 bytes

    bInterval:                         0x00

     

              ===>BOS Descriptor<===

    bLength:                           0x05

    bDescriptorType:                   0x0F

    wTotalLength:                      0x0021

    bNumDeviceCaps:                    0x01

     

              ===>Platform Capability Descriptor<===

    bLength:                           0x1C

    bDescriptorType:                   0x10

    bDevCapabilityType:                0x05

    bReserved:                         0x00

    Platform Capability UUID:          D8DD60DF-4589-4CC7-9CD2-659D9E648A9F

    00 00 03 06 2E 00 01 00 


     

    Let me know if you have any other suggestions.

  • Hi, 

    Since you confirmed that USBReadAndDispatchRequest was hit after BulkRequestHandler, does it invoke the USBDCDStallEP0 function which will stall the request.  It looks like the execution maybe falling into the stack's default: fallback route, which directly calls USBDCDStallEP0().

    You can also check for the state machine status by tracking the variable g_psDCDInst[0].iEP0State. 

    Best Regards

    Siddharth

    .

  • Hi Siddharth,

      I checked iEP0State. When USBDReadAndDispatchRequest was hit, the iEP0State is eUSBStateIdle.
    Then the execution firstly calls case USB_DTYPE_STRING(= 3) from ‘psUSBRequest->wValue >> 8’ in USBDGetDescriptor then the execution hit USBDGetDescriptor again as followings.

    USB_DTYPE_STRING (first call)  ->  USB_DTYPE_DEVICE(= 1)  ->  USB_DTYPE_DEVICE(= 1)  ->  USB_DTYPE_CONFIGURATION(= 2)  ->  default(= 15)  ->  USB_DTYPE_STRING(= 3)  ->  USB_DTYPE_STRING(= 3)  ->  0x06 (Device Qualifier – high speed only)  ->  USBDCDStallEP0


    FYI, I commented out ‘case 0x0F’ to calls default for BOS in USBDGetDescriptor as followings:

    //Manually stall any impossible descriptor requests. This is a hack to
    //pass certification, which requires a stall in response to a request
    //for a BOS descriptor. For some reason, the driver doesn't do this
    //properly, possibly because of the extra callback handler.
    case 0x06: //Device qualifier -- high speed only
    case 0x07: //Other speed config -- high speed only
    case 0x09: //OTG -- not available on Octave, not supported on others (yet?)
    //case 0x0F: //BOS -- SuperSpeed only  ==> Commented out
    case 0x10: //Device capability -- SuperSpeed only
    case 0x30: //SuperSpeed endpoint companion -- SuperSpeed only
    USBDCDStallEP0(0);
    psUSBControl->pui8EP0Data = 0;
    psUSBControl->ui32EP0DataRemain = 0;
    break;


    The followings are Don's questions:

    In summary, we confirmed that the vendor specific MS OS 2.0 request (VendorCode = 0x01, wIndex = 0x0007, wLength = 0x002E) is successfully received by our firmware and that our handler is being called. We call USBDevEndpointDataAck() and then USBDCDSendDataEP0() with the full descriptor set.

    However, EP0 remains in eUSBStateIdle after our handler runs, and the stack continues into USBDGetDescriptor() and eventually calls USBCDStallEP0(). This suggests that the stack believes the request was not fully handled.

    You mentioned that our handler is declared void, but that is what is expected by the TI stack (otherwise we'd get a compiler error).

    Since the handler is declared void, we cannot return a status value. Could you please clarify:

    1. What specific EP0 state transitions or internal flags must be set for the TI USB stack to consider the vendor specific request fully handled?

    2. Is there an additional function we must call after USBDCDSendDataEP0() to indicate that the DATA phase has begun?

    3. What conditions cause the stack to continue into fallback descriptor parsing after a vendor specific handler runs?


    Thanks,

    Jeong